diff --git a/.github/workflows/healthchecks_azure_blobstorage_cd.yml b/.github/workflows/healthchecks_azure_blobstorage_cd.yml new file mode 100644 index 0000000000..4c8e1bfe5d --- /dev/null +++ b/.github/workflows/healthchecks_azure_blobstorage_cd.yml @@ -0,0 +1,16 @@ +name: HealthChecks Azure Blob Storage CD + +on: + push: + tags: + - release-azureblobstorage-* + - release-all-* + +jobs: + build: + uses: ./.github/workflows/reusable_cd_workflow.yml + secrets: inherit + with: + BUILD_CONFIG: Release + PROJECT_PATH: ./src/HealthChecks.Azure.Storage.Blobs/HealthChecks.Azure.Storage.Blobs.csproj + PACKAGE_NAME: AspNetCore.HealthChecks.Azure.Storage.Blobs \ No newline at end of file diff --git a/.github/workflows/healthchecks_azure_blobstorage_cd_preview.yml b/.github/workflows/healthchecks_azure_blobstorage_cd_preview.yml new file mode 100644 index 0000000000..23bf3f914a --- /dev/null +++ b/.github/workflows/healthchecks_azure_blobstorage_cd_preview.yml @@ -0,0 +1,17 @@ +name: HealthChecks Azure Blob Storage Preview CD + +on: + push: + tags: + - preview-azureblobstorage-* + - 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.Azure.Storage.Blobs/HealthChecks.Azure.Storage.Blobs.csproj + PACKAGE_NAME: AspNetCore.HealthChecks.Azure.Storage.Blobs \ No newline at end of file diff --git a/.github/workflows/healthchecks_azure_blobstorage_ci.yml b/.github/workflows/healthchecks_azure_blobstorage_ci.yml new file mode 100644 index 0000000000..6fb422f99e --- /dev/null +++ b/.github/workflows/healthchecks_azure_blobstorage_ci.yml @@ -0,0 +1,37 @@ +name: HealthChecks Azure Blob Storage CI + +on: + workflow_dispatch: + push: + branches: [ master ] + paths: + - src/HealthChecks.Azure.Storage.Blobs/** + - test/HealthChecks.Azure.Storage.Blobs.Tests/** + - test/_SHARED/** + - .github/workflows/healthchecks_azure_blobstorage_ci.yml + - .github/workflows/reusable_ci_workflow.yml + - Directory.Build.props + - Directory.Build.targets + tags-ignore: + - release-* + - preview-* + + pull_request: + branches: [ master ] + paths: + - src/HealthChecks.Azure.Storage.Blobs/** + - test/HealthChecks.Azure.Storage.Blobs.Tests/** + - test/_SHARED/** + - .github/workflows/healthchecks_azure_blobstorage_ci.yml + - .github/workflows/reusable_ci_workflow.yml + - Directory.Build.props + - Directory.Build.targets + +jobs: + build: + uses: ./.github/workflows/reusable_ci_workflow.yml + with: + PROJECT_PATH: ./src/HealthChecks.Azure.Storage.Blobs/HealthChecks.Azure.Storage.Blobs.csproj + TEST_PROJECT_PATH: ./test/HealthChecks.Azure.Storage.Blobs.Tests/HealthChecks.Azure.Storage.Blobs.Tests.csproj + CODECOV_FLAGS: AzureBlobStorage + diff --git a/.github/workflows/healthchecks_azure_filestorage_cd.yml b/.github/workflows/healthchecks_azure_filestorage_cd.yml new file mode 100644 index 0000000000..eb756388b9 --- /dev/null +++ b/.github/workflows/healthchecks_azure_filestorage_cd.yml @@ -0,0 +1,16 @@ +name: HealthChecks Azure File Storage CD + +on: + push: + tags: + - release-azurefilestorage-* + - release-all-* + +jobs: + build: + uses: ./.github/workflows/reusable_cd_workflow.yml + secrets: inherit + with: + BUILD_CONFIG: Release + PROJECT_PATH: ./src/HealthChecks.Azure.Storage.Files.Shares/HealthChecks.Azure.Storage.Files.Shares.csproj + PACKAGE_NAME: AspNetCore.HealthChecks.Azure.Storage.Files.Shares \ No newline at end of file diff --git a/.github/workflows/healthchecks_azure_filestorage_cd_preview.yml b/.github/workflows/healthchecks_azure_filestorage_cd_preview.yml new file mode 100644 index 0000000000..bcd8f676cc --- /dev/null +++ b/.github/workflows/healthchecks_azure_filestorage_cd_preview.yml @@ -0,0 +1,17 @@ +name: HealthChecks Azure File Storage Preview CD + +on: + push: + tags: + - preview-azurefilestorage-* + - 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.Azure.Storage.Files.Shares/HealthChecks.Azure.Storage.Files.Shares.csproj + PACKAGE_NAME: AspNetCore.HealthChecks.Azure.Storage.Files.Shares \ No newline at end of file diff --git a/.github/workflows/healthchecks_azure_filestorage_ci.yml b/.github/workflows/healthchecks_azure_filestorage_ci.yml new file mode 100644 index 0000000000..b1e989c21a --- /dev/null +++ b/.github/workflows/healthchecks_azure_filestorage_ci.yml @@ -0,0 +1,37 @@ +name: HealthChecks Azure File Storage CI + +on: + workflow_dispatch: + push: + branches: [ master ] + paths: + - src/HealthChecks.Azure.Storage.Files.Shares/** + - test/HealthChecks.Azure.Storage.Files.Shares.Tests/** + - test/_SHARED/** + - .github/workflows/healthchecks_azure_filestorage_ci.yml + - .github/workflows/reusable_ci_workflow.yml + - Directory.Build.props + - Directory.Build.targets + tags-ignore: + - release-* + - preview-* + + pull_request: + branches: [ master ] + paths: + - src/HealthChecks.Azure.Storage.Files.Shares/** + - test/HealthChecks.Azure.Storage.Files.Shares.Tests/** + - test/_SHARED/** + - .github/workflows/healthchecks_azure_filestorage_ci.yml + - .github/workflows/reusable_ci_workflow.yml + - Directory.Build.props + - Directory.Build.targets + +jobs: + build: + uses: ./.github/workflows/reusable_ci_workflow.yml + with: + PROJECT_PATH: ./src/HealthChecks.Azure.Storage.Files.Shares/HealthChecks.Azure.Storage.Files.Shares.csproj + TEST_PROJECT_PATH: ./test/HealthChecks.Azure.Storage.Files.Shares.Tests/HealthChecks.Azure.Storage.Files.Shares.Tests.csproj + CODECOV_FLAGS: AzureFileStorage + diff --git a/.github/workflows/healthchecks_azure_queuestorage_cd.yml b/.github/workflows/healthchecks_azure_queuestorage_cd.yml new file mode 100644 index 0000000000..b42ea2c711 --- /dev/null +++ b/.github/workflows/healthchecks_azure_queuestorage_cd.yml @@ -0,0 +1,16 @@ +name: HealthChecks Azure Blob Storage CD + +on: + push: + tags: + - release-azurequeuestorage-* + - release-all-* + +jobs: + build: + uses: ./.github/workflows/reusable_cd_workflow.yml + secrets: inherit + with: + BUILD_CONFIG: Release + PROJECT_PATH: ./src/HealthChecks.Azure.Storage.Queues/HealthChecks.Azure.Storage.Queues.csproj + PACKAGE_NAME: AspNetCore.HealthChecks.Azure.Storage.Queues \ No newline at end of file diff --git a/.github/workflows/healthchecks_azure_queuestorage_cd_preview.yml b/.github/workflows/healthchecks_azure_queuestorage_cd_preview.yml new file mode 100644 index 0000000000..ecdab3e731 --- /dev/null +++ b/.github/workflows/healthchecks_azure_queuestorage_cd_preview.yml @@ -0,0 +1,17 @@ +name: HealthChecks Azure Queue Storage Preview CD + +on: + push: + tags: + - preview-azurequeuestorage-* + - 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.Azure.Storage.Queues/HealthChecks.Azure.Storage.Queues.csproj + PACKAGE_NAME: AspNetCore.HealthChecks.Azure.Storage.Queues \ No newline at end of file diff --git a/.github/workflows/healthchecks_azure_queuestorage_ci.yml b/.github/workflows/healthchecks_azure_queuestorage_ci.yml new file mode 100644 index 0000000000..3644d83ca0 --- /dev/null +++ b/.github/workflows/healthchecks_azure_queuestorage_ci.yml @@ -0,0 +1,37 @@ +name: HealthChecks Azure Queue Storage CI + +on: + workflow_dispatch: + push: + branches: [ master ] + paths: + - src/HealthChecks.Azure.Storage.Queues/** + - test/HealthChecks.Azure.Storage.Queues.Tests/** + - test/_SHARED/** + - .github/workflows/healthchecks_azure_queuestorage_ci.yml + - .github/workflows/reusable_ci_workflow.yml + - Directory.Build.props + - Directory.Build.targets + tags-ignore: + - release-* + - preview-* + + pull_request: + branches: [ master ] + paths: + - src/HealthChecks.Azure.Storage.Queues/** + - test/HealthChecks.Azure.Storage.Queues.Tests/** + - test/_SHARED/** + - .github/workflows/healthchecks_azure_queuestorage_ci.yml + - .github/workflows/reusable_ci_workflow.yml + - Directory.Build.props + - Directory.Build.targets + +jobs: + build: + uses: ./.github/workflows/reusable_ci_workflow.yml + with: + PROJECT_PATH: ./src/HealthChecks.Azure.Storage.Queues/HealthChecks.Azure.Storage.Queues.csproj + TEST_PROJECT_PATH: ./test/HealthChecks.Azure.Storage.Queues.Tests/HealthChecks.Azure.Storage.Queues.Tests.csproj + CODECOV_FLAGS: AzureQueueStorage + diff --git a/.github/workflows/healthchecks_azure_tables_cd.yml b/.github/workflows/healthchecks_azure_tables_cd.yml new file mode 100644 index 0000000000..d97361aefe --- /dev/null +++ b/.github/workflows/healthchecks_azure_tables_cd.yml @@ -0,0 +1,16 @@ +name: HealthChecks Azure Table Storage CD + +on: + push: + tags: + - release-azuretablestorage-* + - release-all-* + +jobs: + build: + uses: ./.github/workflows/reusable_cd_workflow.yml + secrets: inherit + with: + BUILD_CONFIG: Release + PROJECT_PATH: ./src/HealthChecks.Azure.Data.Tables/HealthChecks.Azure.Data.Tables.csproj + PACKAGE_NAME: AspNetCore.HealthChecks.Azure.Data.Tables \ No newline at end of file diff --git a/.github/workflows/healthchecks_azure_tables_cd_preview.yml b/.github/workflows/healthchecks_azure_tables_cd_preview.yml new file mode 100644 index 0000000000..95d8f1963d --- /dev/null +++ b/.github/workflows/healthchecks_azure_tables_cd_preview.yml @@ -0,0 +1,17 @@ +name: HealthChecks Azure Table Storage Preview CD + +on: + push: + tags: + - preview-azuretablestorage-* + - 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.Azure.Data.Tables/HealthChecks.Azure.Data.Tables.csproj + PACKAGE_NAME: AspNetCore.HealthChecks.Azure.Data.Tables \ No newline at end of file diff --git a/.github/workflows/healthchecks_azure_tables_ci.yml b/.github/workflows/healthchecks_azure_tables_ci.yml new file mode 100644 index 0000000000..03ed88f192 --- /dev/null +++ b/.github/workflows/healthchecks_azure_tables_ci.yml @@ -0,0 +1,37 @@ +name: HealthChecks Azure Table Storage CI + +on: + workflow_dispatch: + push: + branches: [ master ] + paths: + - src/HealthChecks.Azure.Data.Tables/** + - test/HealthChecks.Azure.Data.Tables.Tests/** + - test/_SHARED/** + - .github/workflows/healthchecks_azure_tables_ci.yml + - .github/workflows/reusable_ci_workflow.yml + - Directory.Build.props + - Directory.Build.targets + tags-ignore: + - release-* + - preview-* + + pull_request: + branches: [ master ] + paths: + - src/HealthChecks.Azure.Data.Tables/** + - test/HealthChecks.Azure.Data.Tables.Tests/** + - test/_SHARED/** + - .github/workflows/healthchecks_azure_tables_ci.yml + - .github/workflows/reusable_ci_workflow.yml + - Directory.Build.props + - Directory.Build.targets + +jobs: + build: + uses: ./.github/workflows/reusable_ci_workflow.yml + with: + PROJECT_PATH: ./src/HealthChecks.Azure.Data.Tables/HealthChecks.Azure.Data.Tables.csproj + TEST_PROJECT_PATH: ./test/HealthChecks.Azure.Data.Tables.Tests/HealthChecks.Azure.Data.Tables.Tests.csproj + CODECOV_FLAGS: AzureTableStorage + diff --git a/.github/workflows/healthchecks_azureeventhubs_cd.yml b/.github/workflows/healthchecks_azureeventhubs_cd.yml new file mode 100644 index 0000000000..658375c5c7 --- /dev/null +++ b/.github/workflows/healthchecks_azureeventhubs_cd.yml @@ -0,0 +1,16 @@ +name: HealthChecks Azure EventHubs CD + +on: + push: + tags: + - release-azureeventhubs-* + - release-all-* + +jobs: + build: + uses: ./.github/workflows/reusable_cd_workflow.yml + secrets: inherit + with: + BUILD_CONFIG: Release + PROJECT_PATH: ./src/HealthChecks.Azure.Messaging.EventHubs/HealthChecks.Azure.Messaging.EventHubs.csproj + PACKAGE_NAME: HealthChecks.Azure.Messaging.EventHubs \ No newline at end of file diff --git a/.github/workflows/healthchecks_azureeventhubs_cd_preview.yml b/.github/workflows/healthchecks_azureeventhubs_cd_preview.yml new file mode 100644 index 0000000000..9f4e67f0d6 --- /dev/null +++ b/.github/workflows/healthchecks_azureeventhubs_cd_preview.yml @@ -0,0 +1,17 @@ +name: HealthChecks Azure EventHubs Preview CD + +on: + push: + tags: + - preview-azureeventhubs-* + - 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.Azure.Messaging.EventHubs/HealthChecks.Azure.Messaging.EventHubs.csproj + PACKAGE_NAME: AspNetCore.HealthChecks.Azure.Messaging.EventHubs \ No newline at end of file diff --git a/.github/workflows/healthchecks_azureeventhubs_ci.yml b/.github/workflows/healthchecks_azureeventhubs_ci.yml new file mode 100644 index 0000000000..bbfbcd6708 --- /dev/null +++ b/.github/workflows/healthchecks_azureeventhubs_ci.yml @@ -0,0 +1,37 @@ +name: HealthChecks Azure EventHubs CI + +on: + workflow_dispatch: + push: + branches: [ master ] + paths: + - src/HealthChecks.Azure.Messaging.EventHubs/** + - test/HealthChecks.Azure.Messaging.EventHubs.Tests/** + - test/_SHARED/** + - .github/workflows/healthchecks_azureeventhubs_ci.yml + - .github/workflows/reusable_ci_workflow.yml + - Directory.Build.props + - Directory.Build.targets + tags-ignore: + - release-* + - preview-* + + pull_request: + branches: [ master ] + paths: + - src/HealthChecks.Azure.Messaging.EventHubs/** + - test/HealthChecks.Azure.Messaging.EventHubs.Tests/** + - test/_SHARED/** + - .github/workflows/healthchecks_azureeventhubs_ci.yml + - .github/workflows/reusable_ci_workflow.yml + - Directory.Build.props + - Directory.Build.targets + +jobs: + build: + uses: ./.github/workflows/reusable_ci_workflow.yml + with: + PROJECT_PATH: ./src/HealthChecks.Azure.Messaging.EventHubs/HealthChecks.Azure.Messaging.EventHubs.csproj + TEST_PROJECT_PATH: ./test/HealthChecks.Azure.Messaging.EventHubs.Tests/HealthChecks.Azure.Messaging.EventHubs.Tests.csproj + CODECOV_FLAGS: AzureEventHubs + diff --git a/.github/workflows/healthchecks_azurestorage_cd.yml b/.github/workflows/healthchecks_azurestorage_cd.yml deleted file mode 100644 index 9f5541708e..0000000000 --- a/.github/workflows/healthchecks_azurestorage_cd.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: HealthChecks AzureStorage DB CD - -on: - push: - tags: - - release-azurestorage-* - - 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.AzureStorage/HealthChecks.AzureStorage.csproj - - name: Build - run: dotnet build --no-restore ./src/HealthChecks.AzureStorage/HealthChecks.AzureStorage.csproj -c $BUILD_CONFIG - - name: Pack - run: dotnet pack --no-build ./src/HealthChecks.AzureStorage/HealthChecks.AzureStorage.csproj -c $BUILD_CONFIG -o ./artifacts - - name: Publish - run: dotnet nuget push ./artifacts/AspNetCore.HealthChecks.AzureStorage.*.nupkg -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json --skip-duplicate diff --git a/.github/workflows/healthchecks_azurestorage_cd_preview.yml b/.github/workflows/healthchecks_azurestorage_cd_preview.yml deleted file mode 100644 index 08b32f880a..0000000000 --- a/.github/workflows/healthchecks_azurestorage_cd_preview.yml +++ /dev/null @@ -1,30 +0,0 @@ -name: HealthChecks AzureStorage DB Preview CD - -on: - push: - tags: - - preview-azurestorage-* - - preview-all-* - -jobs: - build: - env: - BUILD_CONFIG: Release - VERSION_SUFFIX: rc2.${{ github.run_number }} - 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.AzureStorage/HealthChecks.AzureStorage.csproj - - name: Build - run: dotnet build --no-restore ./src/HealthChecks.AzureStorage/HealthChecks.AzureStorage.csproj -c $BUILD_CONFIG - - name: Pack - run: dotnet pack --no-build ./src/HealthChecks.AzureStorage/HealthChecks.AzureStorage.csproj --version-suffix $VERSION_SUFFIX -c $BUILD_CONFIG -o ./artifacts - - name: Publish - run: dotnet nuget push ./artifacts/AspNetCore.HealthChecks.AzureStorage.*.nupkg -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json --skip-duplicate diff --git a/.github/workflows/healthchecks_azurestorage_ci.yml b/.github/workflows/healthchecks_azurestorage_ci.yml deleted file mode 100644 index 37ebd241d7..0000000000 --- a/.github/workflows/healthchecks_azurestorage_ci.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: HealthChecks AzureStorage DB CI - -on: - workflow_dispatch: - push: - branches: [ master ] - paths: - - src/HealthChecks.AzureStorage/** - - test/HealthChecks.AzureStorage.Tests/** - - test/_SHARED/** - - .github/workflows/healthchecks_azurestorage_ci.yml - - Directory.Build.props - - Directory.Build.targets - tags-ignore: - - release-* - - preview-* - - pull_request: - branches: [ master ] - paths: - - src/HealthChecks.AzureStorage/** - - test/HealthChecks.AzureStorage.Tests/** - - test/_SHARED/** - - .github/workflows/healthchecks_azurestorage_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.AzureStorage/HealthChecks.AzureStorage.csproj && - dotnet restore ./test/HealthChecks.AzureStorage.Tests/HealthChecks.AzureStorage.Tests.csproj - - name: Check formatting - run: | - dotnet format --no-restore --verify-no-changes --severity warn ./src/HealthChecks.AzureStorage/HealthChecks.AzureStorage.csproj || (echo "Run 'dotnet format' to fix issues" && exit 1) && - dotnet format --no-restore --verify-no-changes --severity warn ./test/HealthChecks.AzureStorage.Tests/HealthChecks.AzureStorage.Tests.csproj || (echo "Run 'dotnet format' to fix issues" && exit 1) - - name: Build - run: | - dotnet build --no-restore ./src/HealthChecks.AzureStorage/HealthChecks.AzureStorage.csproj - dotnet build --no-restore ./test/HealthChecks.AzureStorage.Tests/HealthChecks.AzureStorage.Tests.csproj - - name: Test - run: > - dotnet test - ./test/HealthChecks.AzureStorage.Tests/HealthChecks.AzureStorage.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: AzureStorage - directory: .coverage diff --git a/.github/workflows/healthchecks_cosmosdb_cd.yml b/.github/workflows/healthchecks_cosmosdb_cd.yml index f8552a1601..4ceb4e4622 100644 --- a/.github/workflows/healthchecks_cosmosdb_cd.yml +++ b/.github/workflows/healthchecks_cosmosdb_cd.yml @@ -8,22 +8,9 @@ on: jobs: build: - env: + uses: ./.github/workflows/reusable_cd_workflow.yml + secrets: inherit + with: 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.CosmosDb/HealthChecks.CosmosDb.csproj - - name: Build - run: dotnet build --no-restore ./src/HealthChecks.CosmosDb/HealthChecks.CosmosDb.csproj -c $BUILD_CONFIG - - name: Pack - run: dotnet pack --no-build ./src/HealthChecks.CosmosDb/HealthChecks.CosmosDb.csproj -c $BUILD_CONFIG -o ./artifacts - - name: Publish - run: dotnet nuget push ./artifacts/AspNetCore.HealthChecks.CosmosDb.*.nupkg -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json --skip-duplicate + PROJECT_PATH: ./src/HealthChecks.CosmosDb/HealthChecks.CosmosDb.csproj + PACKAGE_NAME: AspNetCore.HealthChecks.CosmosDb \ No newline at end of file diff --git a/.github/workflows/healthchecks_cosmosdb_cd_preview.yml b/.github/workflows/healthchecks_cosmosdb_cd_preview.yml index de3feca56f..ea4001ea03 100644 --- a/.github/workflows/healthchecks_cosmosdb_cd_preview.yml +++ b/.github/workflows/healthchecks_cosmosdb_cd_preview.yml @@ -8,23 +8,10 @@ on: jobs: build: - env: + uses: ./.github/workflows/reusable_cd_preview_workflow.yml + secrets: inherit + with: BUILD_CONFIG: Release - VERSION_SUFFIX: rc2.${{ github.run_number }} - 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.CosmosDb/HealthChecks.CosmosDb.csproj - - name: Build - run: dotnet build --no-restore ./src/HealthChecks.CosmosDb/HealthChecks.CosmosDb.csproj -c $BUILD_CONFIG - - name: Pack - run: dotnet pack --no-build ./src/HealthChecks.CosmosDb/HealthChecks.CosmosDb.csproj --version-suffix $VERSION_SUFFIX -c $BUILD_CONFIG -o ./artifacts - - name: Publish - run: dotnet nuget push ./artifacts/AspNetCore.HealthChecks.CosmosDb.*.nupkg -k ${{secrets.NUGET_API_KEY}} -s https://api.nuget.org/v3/index.json --skip-duplicate + VERSION_SUFFIX_PREFIX: rc2 + PROJECT_PATH: ./src/HealthChecks.CosmosDb/HealthChecks.CosmosDb.csproj + PACKAGE_NAME: AspNetCore.HealthChecks.CosmosDb \ No newline at end of file diff --git a/.github/workflows/healthchecks_cosmosdb_ci.yml b/.github/workflows/healthchecks_cosmosdb_ci.yml index 95c2e8e4ad..598925c199 100644 --- a/.github/workflows/healthchecks_cosmosdb_ci.yml +++ b/.github/workflows/healthchecks_cosmosdb_ci.yml @@ -27,39 +27,8 @@ on: 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.CosmosDb/HealthChecks.CosmosDb.csproj && - dotnet restore ./test/HealthChecks.CosmosDb.Tests/HealthChecks.CosmosDb.Tests.csproj - - name: Check formatting - run: | - dotnet format --no-restore --verify-no-changes --severity warn ./src/HealthChecks.CosmosDb/HealthChecks.CosmosDb.csproj || (echo "Run 'dotnet format' to fix issues" && exit 1) && - dotnet format --no-restore --verify-no-changes --severity warn ./test/HealthChecks.CosmosDb.Tests/HealthChecks.CosmosDb.Tests.csproj || (echo "Run 'dotnet format' to fix issues" && exit 1) - - name: Build - run: | - dotnet build --no-restore ./src/HealthChecks.CosmosDb/HealthChecks.CosmosDb.csproj && - dotnet build --no-restore ./test/HealthChecks.CosmosDb.Tests/HealthChecks.CosmosDb.Tests.csproj - - name: Test - run: > - dotnet test - ./test/HealthChecks.CosmosDb.Tests/HealthChecks.CosmosDb.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: CosmosDb - directory: .coverage + uses: ./.github/workflows/reusable_ci_workflow.yml + with: + PROJECT_PATH: ./src/HealthChecks.CosmosDb/HealthChecks.CosmosDb.csproj + TEST_PROJECT_PATH: ./test/HealthChecks.CosmosDb.Tests/HealthChecks.CosmosDb.Tests.csproj + CODECOV_FLAGS: CosmosDb \ No newline at end of file diff --git a/AspNetCore.Diagnostics.HealthChecks.sln b/AspNetCore.Diagnostics.HealthChecks.sln index baf683de9b..34381a9559 100644 --- a/AspNetCore.Diagnostics.HealthChecks.sln +++ b/AspNetCore.Diagnostics.HealthChecks.sln @@ -42,10 +42,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Network", "src EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.DocumentDb", "src\HealthChecks.DocumentDb\HealthChecks.DocumentDb.csproj", "{F42DB8D6-65CE-4C7B-A1CB-560DDA468F93}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.AzureStorage", "src\HealthChecks.AzureStorage\HealthChecks.AzureStorage.csproj", "{E7A1DD9B-B7B1-450D-9736-331EE85649E1}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.AzureServiceBus", "src\HealthChecks.AzureServiceBus\HealthChecks.AzureServiceBus.csproj", "{4F45BB95-CB91-406D-B8A4-01E2830CC451}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.UI", "src\HealthChecks.UI\HealthChecks.UI.csproj", "{6AE01EB5-86D4-4603-B798-26C7DB63AEB3}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{092533AB-7505-4EDC-8932-D40BF575D0D2}" @@ -199,12 +195,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".Solution Items", ".Solutio README.md = README.md EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.AzureServiceBus.Tests", "test\HealthChecks.AzureServiceBus.Tests\HealthChecks.AzureServiceBus.Tests.csproj", "{80835FF3-C984-4BCE-B047-7985B42F6B0E}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.AzureKeyVault.Tests", "test\HealthChecks.AzureKeyVault.Tests\HealthChecks.AzureKeyVault.Tests.csproj", "{CAA0DB8F-9759-436D-A4E7-2061C0125B06}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.AzureStorage.Tests", "test\HealthChecks.AzureStorage.Tests\HealthChecks.AzureStorage.Tests.csproj", "{6BA3E850-92EC-4F0F-BF53-D3F01EE6A120}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Azure.IoTHub.Tests", "test\HealthChecks.Azure.IoTHub.Tests\HealthChecks.Azure.IoTHub.Tests.csproj", "{C825E756-F1E0-4AE9-9814-B8A112B1CAA9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Aws.S3.Tests", "test\HealthChecks.Aws.S3.Tests\HealthChecks.Aws.S3.Tests.csproj", "{62B73D6A-076D-414B-9B4E-D6C3FF38E786}" @@ -247,9 +239,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 +275,35 @@ 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("{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("{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.Azure.Storage.Blobs", "src\HealthChecks.Azure.Storage.Blobs\HealthChecks.Azure.Storage.Blobs.csproj", "{35994A03-ABFD-4016-865E-907CCA6B0175}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Azure.Storage.Queues", "src\HealthChecks.Azure.Storage.Queues\HealthChecks.Azure.Storage.Queues.csproj", "{D51E2882-48E2-4384-A729-4FB627C6DB91}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Azure.Storage.Files.Shares", "src\HealthChecks.Azure.Storage.Files.Shares\HealthChecks.Azure.Storage.Files.Shares.csproj", "{94031EF0-8262-46BE-9CF0-4E357CAE27AE}" 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.AzureServiceBus", "src\HealthChecks.AzureServiceBus\HealthChecks.AzureServiceBus.csproj", "{C84C0A78-B520-4B21-95D1-9113A6B46611}" 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.Messaging.EventHubs", "src\HealthChecks.Azure.Messaging.EventHubs\HealthChecks.Azure.Messaging.EventHubs.csproj", "{87F760F2-C265-4898-8B9F-2C78532BC321}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Azure.Data.Tables", "src\HealthChecks.Azure.Data.Tables\HealthChecks.Azure.Data.Tables.csproj", "{B58D3765-3BB8-4FB4-9F0D-CC9A5EF07DF1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Azure.Storage.Blobs.Tests", "test\HealthChecks.Azure.Storage.Blobs.Tests\HealthChecks.Azure.Storage.Blobs.Tests.csproj", "{786230EB-BF05-4B85-910C-72906A924A17}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Azure.Storage.Queues.Tests", "test\HealthChecks.Azure.Storage.Queues.Tests\HealthChecks.Azure.Storage.Queues.Tests.csproj", "{5265E8E8-92B7-4123-BAF3-7B9A0E893785}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Azure.Storage.Files.Shares.Tests", "test\HealthChecks.Azure.Storage.Files.Shares.Tests\HealthChecks.Azure.Storage.Files.Shares.Tests.csproj", "{A6BD9977-E12E-4309-B0AA-A755C04E525B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Azure.Data.Tables.Tests", "test\HealthChecks.Azure.Data.Tables.Tests\HealthChecks.Azure.Data.Tables.Tests.csproj", "{2C02BEDF-FFFA-4747-920A-A1ED6CFFC21A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.Azure.Messaging.EventHubs.Tests", "test\HealthChecks.Azure.Messaging.EventHubs.Tests\HealthChecks.Azure.Messaging.EventHubs.Tests.csproj", "{09160C0F-BB5E-4DF2-AF44-E859E8EDE6BD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HealthChecks.AzureServiceBus.Tests", "test\HealthChecks.AzureServiceBus.Tests\HealthChecks.AzureServiceBus.Tests.csproj", "{3B812989-2C4E-4FCE-B3A0-EF9C00A9B3A5}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -343,14 +359,6 @@ Global {F42DB8D6-65CE-4C7B-A1CB-560DDA468F93}.Debug|Any CPU.Build.0 = Debug|Any CPU {F42DB8D6-65CE-4C7B-A1CB-560DDA468F93}.Release|Any CPU.ActiveCfg = Release|Any CPU {F42DB8D6-65CE-4C7B-A1CB-560DDA468F93}.Release|Any CPU.Build.0 = Release|Any CPU - {E7A1DD9B-B7B1-450D-9736-331EE85649E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E7A1DD9B-B7B1-450D-9736-331EE85649E1}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E7A1DD9B-B7B1-450D-9736-331EE85649E1}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E7A1DD9B-B7B1-450D-9736-331EE85649E1}.Release|Any CPU.Build.0 = Release|Any CPU - {4F45BB95-CB91-406D-B8A4-01E2830CC451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4F45BB95-CB91-406D-B8A4-01E2830CC451}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4F45BB95-CB91-406D-B8A4-01E2830CC451}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4F45BB95-CB91-406D-B8A4-01E2830CC451}.Release|Any CPU.Build.0 = Release|Any CPU {6AE01EB5-86D4-4603-B798-26C7DB63AEB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6AE01EB5-86D4-4603-B798-26C7DB63AEB3}.Debug|Any CPU.Build.0 = Debug|Any CPU {6AE01EB5-86D4-4603-B798-26C7DB63AEB3}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -627,18 +635,10 @@ Global {4E8DA856-FC10-4A18-BDFB-7C604F17D1EE}.Debug|Any CPU.Build.0 = Debug|Any CPU {4E8DA856-FC10-4A18-BDFB-7C604F17D1EE}.Release|Any CPU.ActiveCfg = Release|Any CPU {4E8DA856-FC10-4A18-BDFB-7C604F17D1EE}.Release|Any CPU.Build.0 = Release|Any CPU - {80835FF3-C984-4BCE-B047-7985B42F6B0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {80835FF3-C984-4BCE-B047-7985B42F6B0E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {80835FF3-C984-4BCE-B047-7985B42F6B0E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {80835FF3-C984-4BCE-B047-7985B42F6B0E}.Release|Any CPU.Build.0 = Release|Any CPU {CAA0DB8F-9759-436D-A4E7-2061C0125B06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CAA0DB8F-9759-436D-A4E7-2061C0125B06}.Debug|Any CPU.Build.0 = Debug|Any CPU {CAA0DB8F-9759-436D-A4E7-2061C0125B06}.Release|Any CPU.ActiveCfg = Release|Any CPU {CAA0DB8F-9759-436D-A4E7-2061C0125B06}.Release|Any CPU.Build.0 = Release|Any CPU - {6BA3E850-92EC-4F0F-BF53-D3F01EE6A120}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6BA3E850-92EC-4F0F-BF53-D3F01EE6A120}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6BA3E850-92EC-4F0F-BF53-D3F01EE6A120}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6BA3E850-92EC-4F0F-BF53-D3F01EE6A120}.Release|Any CPU.Build.0 = Release|Any CPU {C825E756-F1E0-4AE9-9814-B8A112B1CAA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C825E756-F1E0-4AE9-9814-B8A112B1CAA9}.Debug|Any CPU.Build.0 = Debug|Any CPU {C825E756-F1E0-4AE9-9814-B8A112B1CAA9}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -719,18 +719,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 +807,54 @@ 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 + {35994A03-ABFD-4016-865E-907CCA6B0175}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {35994A03-ABFD-4016-865E-907CCA6B0175}.Debug|Any CPU.Build.0 = Debug|Any CPU + {35994A03-ABFD-4016-865E-907CCA6B0175}.Release|Any CPU.ActiveCfg = Release|Any CPU + {35994A03-ABFD-4016-865E-907CCA6B0175}.Release|Any CPU.Build.0 = Release|Any CPU + {D51E2882-48E2-4384-A729-4FB627C6DB91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D51E2882-48E2-4384-A729-4FB627C6DB91}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D51E2882-48E2-4384-A729-4FB627C6DB91}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D51E2882-48E2-4384-A729-4FB627C6DB91}.Release|Any CPU.Build.0 = Release|Any CPU + {94031EF0-8262-46BE-9CF0-4E357CAE27AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {94031EF0-8262-46BE-9CF0-4E357CAE27AE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {94031EF0-8262-46BE-9CF0-4E357CAE27AE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {94031EF0-8262-46BE-9CF0-4E357CAE27AE}.Release|Any CPU.Build.0 = Release|Any CPU + {C84C0A78-B520-4B21-95D1-9113A6B46611}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C84C0A78-B520-4B21-95D1-9113A6B46611}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C84C0A78-B520-4B21-95D1-9113A6B46611}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C84C0A78-B520-4B21-95D1-9113A6B46611}.Release|Any CPU.Build.0 = Release|Any CPU + {87F760F2-C265-4898-8B9F-2C78532BC321}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {87F760F2-C265-4898-8B9F-2C78532BC321}.Debug|Any CPU.Build.0 = Debug|Any CPU + {87F760F2-C265-4898-8B9F-2C78532BC321}.Release|Any CPU.ActiveCfg = Release|Any CPU + {87F760F2-C265-4898-8B9F-2C78532BC321}.Release|Any CPU.Build.0 = Release|Any CPU + {B58D3765-3BB8-4FB4-9F0D-CC9A5EF07DF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B58D3765-3BB8-4FB4-9F0D-CC9A5EF07DF1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B58D3765-3BB8-4FB4-9F0D-CC9A5EF07DF1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B58D3765-3BB8-4FB4-9F0D-CC9A5EF07DF1}.Release|Any CPU.Build.0 = Release|Any CPU + {786230EB-BF05-4B85-910C-72906A924A17}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {786230EB-BF05-4B85-910C-72906A924A17}.Debug|Any CPU.Build.0 = Debug|Any CPU + {786230EB-BF05-4B85-910C-72906A924A17}.Release|Any CPU.ActiveCfg = Release|Any CPU + {786230EB-BF05-4B85-910C-72906A924A17}.Release|Any CPU.Build.0 = Release|Any CPU + {5265E8E8-92B7-4123-BAF3-7B9A0E893785}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5265E8E8-92B7-4123-BAF3-7B9A0E893785}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5265E8E8-92B7-4123-BAF3-7B9A0E893785}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5265E8E8-92B7-4123-BAF3-7B9A0E893785}.Release|Any CPU.Build.0 = Release|Any CPU + {A6BD9977-E12E-4309-B0AA-A755C04E525B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A6BD9977-E12E-4309-B0AA-A755C04E525B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6BD9977-E12E-4309-B0AA-A755C04E525B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6BD9977-E12E-4309-B0AA-A755C04E525B}.Release|Any CPU.Build.0 = Release|Any CPU + {2C02BEDF-FFFA-4747-920A-A1ED6CFFC21A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2C02BEDF-FFFA-4747-920A-A1ED6CFFC21A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2C02BEDF-FFFA-4747-920A-A1ED6CFFC21A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2C02BEDF-FFFA-4747-920A-A1ED6CFFC21A}.Release|Any CPU.Build.0 = Release|Any CPU + {09160C0F-BB5E-4DF2-AF44-E859E8EDE6BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09160C0F-BB5E-4DF2-AF44-E859E8EDE6BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09160C0F-BB5E-4DF2-AF44-E859E8EDE6BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09160C0F-BB5E-4DF2-AF44-E859E8EDE6BD}.Release|Any CPU.Build.0 = Release|Any CPU + {3B812989-2C4E-4FCE-B3A0-EF9C00A9B3A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3B812989-2C4E-4FCE-B3A0-EF9C00A9B3A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B812989-2C4E-4FCE-B3A0-EF9C00A9B3A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3B812989-2C4E-4FCE-B3A0-EF9C00A9B3A5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -824,8 +872,6 @@ Global {E6AF5AD6-618A-491D-B8BB-F8EF56C6B403} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} {46A58C98-B38F-486C-83BA-3772A217A24E} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} {F42DB8D6-65CE-4C7B-A1CB-560DDA468F93} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} - {E7A1DD9B-B7B1-450D-9736-331EE85649E1} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} - {4F45BB95-CB91-406D-B8A4-01E2830CC451} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} {6AE01EB5-86D4-4603-B798-26C7DB63AEB3} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} {7C8F7A48-2FF9-4CF4-AAAC-142053E34FC0} = {092533AB-7505-4EDC-8932-D40BF575D0D2} {EEF1E206-DEE3-45F2-A753-73D2FFFF8EDA} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} @@ -895,9 +941,7 @@ Global {74921A32-8C36-4E74-B593-887FFEC1AF19} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} {8B853DD2-0B83-4898-906C-F34D1AD844F9} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} {4E8DA856-FC10-4A18-BDFB-7C604F17D1EE} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} - {80835FF3-C984-4BCE-B047-7985B42F6B0E} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} {CAA0DB8F-9759-436D-A4E7-2061C0125B06} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} - {6BA3E850-92EC-4F0F-BF53-D3F01EE6A120} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} {C825E756-F1E0-4AE9-9814-B8A112B1CAA9} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} {62B73D6A-076D-414B-9B4E-D6C3FF38E786} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} {B67AF15E-698D-44E6-A58C-2BC7CCF62CBE} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} @@ -918,9 +962,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 +984,18 @@ 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} + {35994A03-ABFD-4016-865E-907CCA6B0175} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} + {D51E2882-48E2-4384-A729-4FB627C6DB91} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} + {94031EF0-8262-46BE-9CF0-4E357CAE27AE} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} + {C84C0A78-B520-4B21-95D1-9113A6B46611} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} + {87F760F2-C265-4898-8B9F-2C78532BC321} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} + {B58D3765-3BB8-4FB4-9F0D-CC9A5EF07DF1} = {2A3FD988-2BB8-43CF-B3A2-B70E648259D4} + {786230EB-BF05-4B85-910C-72906A924A17} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} + {5265E8E8-92B7-4123-BAF3-7B9A0E893785} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} + {A6BD9977-E12E-4309-B0AA-A755C04E525B} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} + {2C02BEDF-FFFA-4747-920A-A1ED6CFFC21A} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} + {09160C0F-BB5E-4DF2-AF44-E859E8EDE6BD} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} + {3B812989-2C4E-4FCE-B3A0-EF9C00A9B3A5} = {FF4414C2-8863-4ADA-8A1D-4B9F25C361FE} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {2B8C62A1-11B6-469F-874C-A02443256568} diff --git a/Directory.Build.props b/Directory.Build.props index 20faae2c23..d9959f8f0e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -32,10 +32,6 @@ $(WarningsNotAsErrors);IDE0053;IDE0060 - - - - @@ -61,6 +57,7 @@ + diff --git a/build/versions.props b/build/versions.props index c6857f2661..758ad003c2 100644 --- a/build/versions.props +++ b/build/versions.props @@ -11,11 +11,16 @@ 7.0.0 7.0.0 7.0.0 - 7.2.0 - 7.0.0 + 7.0.0 + 7.0.1 + 7.0.0 + 7.2.1 + 7.0.0 + 7.0.0 + 7.0.0 7.0.0 7.0.0 - 7.0.0 + 7.0.1 7.0.0 7.1.0 7.0.0 diff --git a/samples/HealthChecks.Sample/HealthChecks.Sample.csproj b/samples/HealthChecks.Sample/HealthChecks.Sample.csproj index a84e9904d9..a483e8c2bd 100644 --- a/samples/HealthChecks.Sample/HealthChecks.Sample.csproj +++ b/samples/HealthChecks.Sample/HealthChecks.Sample.csproj @@ -13,8 +13,6 @@ - - diff --git a/src/HealthChecks.CosmosDb/TableServiceHealthCheck.cs b/src/HealthChecks.Azure.Data.Tables/AzureTableServiceHealthCheck.cs similarity index 55% rename from src/HealthChecks.CosmosDb/TableServiceHealthCheck.cs rename to src/HealthChecks.Azure.Data.Tables/AzureTableServiceHealthCheck.cs index 69c4cb3620..0df08e046a 100644 --- a/src/HealthChecks.CosmosDb/TableServiceHealthCheck.cs +++ b/src/HealthChecks.Azure.Data.Tables/AzureTableServiceHealthCheck.cs @@ -1,67 +1,60 @@ -using Azure.Core; -using Azure.Data.Tables; -using Microsoft.Extensions.Diagnostics.HealthChecks; - -namespace HealthChecks.CosmosDb; - -public class TableServiceHealthCheck : IHealthCheck -{ - private readonly TableServiceClient _tableServiceClient; - private readonly TableServiceHealthCheckOptions _options; - - public TableServiceHealthCheck(string connectionString, string? tableName) - : this( - ClientCache.GetOrAdd(connectionString, k => new TableServiceClient(k)), - new TableServiceHealthCheckOptions { TableName = tableName }) - { } - - public TableServiceHealthCheck(Uri endpoint, TableSharedKeyCredential credentials, string? tableName) - : this( - ClientCache.GetOrAdd(endpoint?.ToString()!, _ => new TableServiceClient(endpoint, credentials)), - new TableServiceHealthCheckOptions { TableName = tableName }) - { } - - public TableServiceHealthCheck(Uri endpoint, TokenCredential tokenCredential, string? tableName) - : this( - ClientCache.GetOrAdd(endpoint?.ToString()!, _ => new TableServiceClient(endpoint, tokenCredential)), - new TableServiceHealthCheckOptions { TableName = tableName }) - { } - - public TableServiceHealthCheck(TableServiceClient tableServiceClient, TableServiceHealthCheckOptions options) - { - _tableServiceClient = Guard.ThrowIfNull(tableServiceClient); - _options = Guard.ThrowIfNull(options); - } - - /// - public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) - { - try - { - // Note: TableServiceClient.GetPropertiesAsync() cannot be used with only the role assignment - // "Storage Table Data Contributor," so TableServiceClient.QueryAsync() and - // TableClient.QueryAsync() are used instead to probe service health. - await _tableServiceClient - .QueryAsync(filter: "false", cancellationToken: cancellationToken) - .GetAsyncEnumerator(cancellationToken) - .MoveNextAsync() - .ConfigureAwait(false); - - if (!string.IsNullOrEmpty(_options.TableName)) - { - var tableClient = _tableServiceClient.GetTableClient(_options.TableName); - await tableClient - .QueryAsync(filter: "false", cancellationToken: cancellationToken) - .GetAsyncEnumerator(cancellationToken) - .MoveNextAsync() - .ConfigureAwait(false); - } - - return HealthCheckResult.Healthy(); - } - catch (Exception ex) - { - return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); - } - } -} +using Azure.Data.Tables; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace HealthChecks.Azure.Data.Tables; + +/// +/// Azure Tables health check. +/// +public sealed class AzureTableServiceHealthCheck : IHealthCheck +{ + private readonly TableServiceClient _tableServiceClient; + private readonly AzureTableServiceHealthCheckOptions _options; + + /// + /// Creates new instance of Azure Tables health check. + /// + /// + /// The used to perform Azure Tables operations. + /// Azure SDK recommends treating clients as singletons , + /// so this should be the exact same instance used by other parts of the application. + /// + /// Optional settings used by the health check. + public AzureTableServiceHealthCheck(TableServiceClient tableServiceClient, AzureTableServiceHealthCheckOptions? options) + { + _tableServiceClient = Guard.ThrowIfNull(tableServiceClient); + _options = options ?? new(); + } + + /// + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try + { + // Note: TableServiceClient.GetPropertiesAsync() cannot be used with only the role assignment + // "Storage Table Data Contributor," so TableServiceClient.QueryAsync() and + // TableClient.QueryAsync() are used instead to probe service health. + await _tableServiceClient + .QueryAsync(filter: "false", cancellationToken: cancellationToken) + .GetAsyncEnumerator(cancellationToken) + .MoveNextAsync() + .ConfigureAwait(false); + + if (!string.IsNullOrEmpty(_options.TableName)) + { + var tableClient = _tableServiceClient.GetTableClient(_options.TableName); + await tableClient + .QueryAsync(filter: "false", cancellationToken: cancellationToken) + .GetAsyncEnumerator(cancellationToken) + .MoveNextAsync() + .ConfigureAwait(false); + } + + return HealthCheckResult.Healthy(); + } + catch (Exception ex) + { + return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); + } + } +} diff --git a/src/HealthChecks.CosmosDb/TableServiceHealthCheckOptions.cs b/src/HealthChecks.Azure.Data.Tables/AzureTableServiceHealthCheckOptions.cs similarity index 70% rename from src/HealthChecks.CosmosDb/TableServiceHealthCheckOptions.cs rename to src/HealthChecks.Azure.Data.Tables/AzureTableServiceHealthCheckOptions.cs index afa83d85c5..f9c64ec2f7 100644 --- a/src/HealthChecks.CosmosDb/TableServiceHealthCheckOptions.cs +++ b/src/HealthChecks.Azure.Data.Tables/AzureTableServiceHealthCheckOptions.cs @@ -1,10 +1,10 @@ -namespace HealthChecks.CosmosDb; +namespace HealthChecks.Azure.Data.Tables; /// /// Represents a collection of settings that configure an -/// Azure Storage Table Service health check. +/// Azure Storage Table Service health check. /// -public sealed class TableServiceHealthCheckOptions +public sealed class AzureTableServiceHealthCheckOptions { /// /// Gets or sets the name of the Azure Storage table whose health should be checked. diff --git a/src/HealthChecks.Azure.Data.Tables/DependencyInjection/AzureTablesServiceHealthChecksBuilderExtensions.cs b/src/HealthChecks.Azure.Data.Tables/DependencyInjection/AzureTablesServiceHealthChecksBuilderExtensions.cs new file mode 100644 index 0000000000..1e6c17cab5 --- /dev/null +++ b/src/HealthChecks.Azure.Data.Tables/DependencyInjection/AzureTablesServiceHealthChecksBuilderExtensions.cs @@ -0,0 +1,52 @@ +using Azure.Data.Tables; +using HealthChecks.Azure.Data.Tables; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace Microsoft.Extensions.DependencyInjection; + +/// +/// Extension methods to configure . +/// +public static class AzureTablesServiceHealthChecksBuilderExtensions +{ + private const string HEALTH_CHECK_NAME = "azure_tables"; + + /// + /// Add a health check for Azure Tables Service by registering for given . + /// + /// The to add to. + /// + /// An optional factory to obtain instance. + /// When not provided, is simply resolved from . + /// + /// + /// An optional factory to obtain used by the health check. + /// When not provided, defaults are used. + /// + /// The health check name. Optional. If null the name 'azure_tables' will be used. + /// + /// 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. + /// The specified . + public static IHealthChecksBuilder AddAzureTable( + this IHealthChecksBuilder builder, + Func? clientFactory = default, + Func? optionsFactory = default, + string? healthCheckName = HEALTH_CHECK_NAME, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + return builder.Add(new HealthCheckRegistration( + string.IsNullOrEmpty(healthCheckName) ? HEALTH_CHECK_NAME : healthCheckName!, + sp => new AzureTableServiceHealthCheck( + tableServiceClient: clientFactory?.Invoke(sp) ?? sp.GetRequiredService(), + options: optionsFactory?.Invoke(sp)), + failureStatus, + tags, + timeout)); + } +} diff --git a/src/HealthChecks.Azure.Data.Tables/HealthChecks.Azure.Data.Tables.csproj b/src/HealthChecks.Azure.Data.Tables/HealthChecks.Azure.Data.Tables.csproj new file mode 100644 index 0000000000..af2440ca2c --- /dev/null +++ b/src/HealthChecks.Azure.Data.Tables/HealthChecks.Azure.Data.Tables.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + $(PackageTags);Azure;Tables + HealthChecks.Azure.Data.Tables is the health check package for Azure Tables. + $(HealthCheckAzureDataTables) + + + + + + + + diff --git a/src/HealthChecks.Azure.Data.Tables/README.md b/src/HealthChecks.Azure.Data.Tables/README.md new file mode 100644 index 0000000000..79607c831f --- /dev/null +++ b/src/HealthChecks.Azure.Data.Tables/README.md @@ -0,0 +1,43 @@ +## Azure Tables Health Check + +This health check verifies the ability to communicate with [Azure Tables](https://azure.microsoft.com/en-us/products/storage/tables/). It uses the provided [TableServiceClient](https://learn.microsoft.com/dotnet/api/azure.data.tables.tableserviceclient). + +### Defaults + +By default, the `TableServiceClient` instance is resolved from service provider. `AzureTableServiceHealthCheckOptions` does not provide any specific container name, so the health check fetches just first container. + +```csharp +void Configure(IHealthChecksBuilder builder) +{ + builder.Services.AddSingleton(sp => new TableServiceClient(new Uri("azure-table-storage-uri"), new DefaultAzureCredential())); + builder.AddHealthChecks().AddAzureTable(); +} +``` + +### Customization + +You can additionally add the following parameters: + +- `clientFactory`: A factory method to provide `TableServiceClient` instance. +- `optionsFactory`: A factory method to provide `AzureTableServiceHealthCheckOptions` instance. It allows to specify the table name. +- `healthCheckName`: The health check name. The default is `azure_tables`. +- `failureStatus`: The `HealthStatus` that should be reported when the health check fails. Default is `HealthStatus.Unhealthy`. +- `tags`: A list of tags that can be used to filter sets of health checks. +- `timeout`: A `System.TimeSpan` representing the timeout of the check. + +```csharp +void Configure(IHealthChecksBuilder builder) +{ + builder.Services.AddSingleton(sp => new TableServiceClient(new Uri("azure-table-storage-uri"), new DefaultAzureCredential())); + builder.AddHealthChecks().AddAzureTable( + optionsFactory: sp => new AzureTableServiceHealthCheckOptions() + { + TableName = "demo" + }); +} +``` + +### Breaking changes + +In the prior releases, `TableServiceHealthCheck` was a part of `HealthChecks.CosmosDb` package. It had a dependency on not just `Azure.Data.Tables`, but also `Microsoft.Azure.Cosmos`. The packages have been split to avoid bringing unnecessary dependencies. Moreover, `TableServiceHealthCheck` was letting the users specify how `TableServiceClient` should be created (from raw connection string or from endpoint and managed identity credentials), at a cost of maintaining an internal, static client instances cache. Now the type does not create client instances nor maintain an internal cache and **it's the caller responsibility to provide the instance of `TableServiceClient`** (please see [#2040](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/issues/2040) for more details). Since Azure SDK recommends treating clients as singletons and client instances can be expensive to create, it's recommended to register a singleton factory method for Azure SDK clients. So the clients are created only when needed and once per whole application lifetime. + diff --git a/src/HealthChecks.Azure.KeyVault.Secrets/AzureKeyVaultSecretsHealthCheck.cs b/src/HealthChecks.Azure.KeyVault.Secrets/AzureKeyVaultSecretsHealthCheck.cs index 9b3d9164ee..b7788c8584 100644 --- a/src/HealthChecks.Azure.KeyVault.Secrets/AzureKeyVaultSecretsHealthCheck.cs +++ b/src/HealthChecks.Azure.KeyVault.Secrets/AzureKeyVaultSecretsHealthCheck.cs @@ -10,7 +10,7 @@ namespace HealthChecks.Azure.KeyVault.Secrets; public sealed class AzureKeyVaultSecretsHealthCheck : IHealthCheck { private readonly SecretClient _secretClient; - private readonly AzureKeyVaultSecretOptions _options; + private readonly AzureKeyVaultSecretsHealthCheckOptions _options; /// /// Creates new instance of Azure Key Vault Secrets health check. @@ -20,18 +20,18 @@ public sealed class AzureKeyVaultSecretsHealthCheck : IHealthCheck /// Azure SDK recommends treating clients as singletons , /// so this should be the exact same instance used by other parts of the application. /// - /// The settings used by the health check. + /// Optional settings used by the health check. /// - /// It uses the provided to get given secret via + /// It uses the provided to get given secret via /// method. - /// When the secret is not found, it will try to create it if is set to true. - /// When the secret is not found, but is false, it returns status, + /// When the secret is not found, it will try to create it if is set to true. + /// When the secret is not found, but is false, it returns status, /// as the connection to the service itself can be made. /// - public AzureKeyVaultSecretsHealthCheck(SecretClient secretClient, AzureKeyVaultSecretOptions options) + public AzureKeyVaultSecretsHealthCheck(SecretClient secretClient, AzureKeyVaultSecretsHealthCheckOptions? options = default) { _secretClient = Guard.ThrowIfNull(secretClient); - _options = Guard.ThrowIfNull(options); + _options = options ?? new AzureKeyVaultSecretsHealthCheckOptions(); } /// diff --git a/src/HealthChecks.Azure.KeyVault.Secrets/AzureKeyVaultSecretOptions.cs b/src/HealthChecks.Azure.KeyVault.Secrets/AzureKeyVaultSecretsHealthCheckOptions.cs similarity index 85% rename from src/HealthChecks.Azure.KeyVault.Secrets/AzureKeyVaultSecretOptions.cs rename to src/HealthChecks.Azure.KeyVault.Secrets/AzureKeyVaultSecretsHealthCheckOptions.cs index c85d880dbf..c37a9ad424 100644 --- a/src/HealthChecks.Azure.KeyVault.Secrets/AzureKeyVaultSecretOptions.cs +++ b/src/HealthChecks.Azure.KeyVault.Secrets/AzureKeyVaultSecretsHealthCheckOptions.cs @@ -2,7 +2,10 @@ namespace HealthChecks.Azure.KeyVault.Secrets; -public sealed class AzureKeyVaultSecretOptions +/// +/// Settings for . +/// +public sealed class AzureKeyVaultSecretsHealthCheckOptions { private string _secretName = nameof(AzureKeyVaultSecretsHealthCheck); diff --git a/src/HealthChecks.Azure.KeyVault.Secrets/DependencyInjection/AzureKeyVaultHealthChecksBuilderExtensions.cs b/src/HealthChecks.Azure.KeyVault.Secrets/DependencyInjection/AzureKeyVaultHealthChecksBuilderExtensions.cs index c278dc483a..209cdf1969 100644 --- a/src/HealthChecks.Azure.KeyVault.Secrets/DependencyInjection/AzureKeyVaultHealthChecksBuilderExtensions.cs +++ b/src/HealthChecks.Azure.KeyVault.Secrets/DependencyInjection/AzureKeyVaultHealthChecksBuilderExtensions.cs @@ -14,26 +14,28 @@ public static class AzureKeyVaultHealthChecksBuilderExtensions /// /// Add a health check for Azure Key Vault Secrets by registering for given . /// - /// + /// The to add to. + /// /// An optional factory to obtain instance. /// When not provided, is simply resolved from . /// - /// - /// An optional factory to obtain used by the health check. - /// When not provided, defaults are used. - /// The health check healthCheckName. Optional. If null the type healthCheckName 'azure_key_vault_secret' will be used. - /// + /// + /// An optional factory to obtain used by the health check. + /// When not provided, defaults are used. + /// + /// The health check name. Optional. If null the name 'azure_key_vault_secret' will be used. + /// /// 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. - /// The specified . + /// A list of tags that can be used to filter sets of health checks. Optional. + /// An optional representing the timeout of the check. + /// The specified . public static IHealthChecksBuilder AddAzureKeyVaultSecrets( this IHealthChecksBuilder builder, - Func? secretClientFactory = default, - Func? optionsFactory = default, - string? healthCheckName = default, + Func? clientFactory = default, + Func? optionsFactory = default, + string? healthCheckName = HEALTH_CHECK_NAME, HealthStatus? failureStatus = default, IEnumerable? tags = default, TimeSpan? timeout = default) @@ -41,8 +43,8 @@ public static IHealthChecksBuilder AddAzureKeyVaultSecrets( return builder.Add(new HealthCheckRegistration( string.IsNullOrEmpty(healthCheckName) ? HEALTH_CHECK_NAME : healthCheckName!, sp => new AzureKeyVaultSecretsHealthCheck( - secretClient: secretClientFactory?.Invoke(sp) ?? sp.GetRequiredService(), - options: optionsFactory?.Invoke(sp) ?? new AzureKeyVaultSecretOptions()), + secretClient: clientFactory?.Invoke(sp) ?? sp.GetRequiredService(), + options: optionsFactory?.Invoke(sp)), failureStatus, tags, timeout)); diff --git a/src/HealthChecks.Azure.KeyVault.Secrets/HealthChecks.Azure.KeyVault.Secrets.csproj b/src/HealthChecks.Azure.KeyVault.Secrets/HealthChecks.Azure.KeyVault.Secrets.csproj index fd4f77bce2..d8aa0bdd46 100644 --- a/src/HealthChecks.Azure.KeyVault.Secrets/HealthChecks.Azure.KeyVault.Secrets.csproj +++ b/src/HealthChecks.Azure.KeyVault.Secrets/HealthChecks.Azure.KeyVault.Secrets.csproj @@ -4,7 +4,7 @@ netstandard2.0 $(PackageTags);Azure Key Vault;Secrets HealthChecks.Azure.KeyVault.Secrets is the health check package for Azure Key Vault secrets - $(HealthCheckKeyVault) + $(HealthCheckKeyVaultSecrets) diff --git a/src/HealthChecks.Azure.KeyVault.Secrets/README.md b/src/HealthChecks.Azure.KeyVault.Secrets/README.md index d1ac81476a..94dd53c4ca 100644 --- a/src/HealthChecks.Azure.KeyVault.Secrets/README.md +++ b/src/HealthChecks.Azure.KeyVault.Secrets/README.md @@ -4,13 +4,13 @@ This health check verifies the ability to communicate with [Azure Key Vault Secr ### Defaults -By default, the `SecretClient` instance is resolved from service provider. `AzureKeyVaultSecretOptions` by default uses "AzureKeyVaultSecretsHealthCheck" secret name and does not try to create the secret when it's not found. +By default, the `SecretClient` instance is resolved from service provider. `AzureKeyVaultSecretsHealthCheckOptions` by default uses "AzureKeyVaultSecretsHealthCheck" secret name and does not try to create the secret when it's not found. ```csharp -public void Configure(IHealthChecksBuilder builder) +void Configure(IHealthChecksBuilder builder) { builder.Services.AddSingleton(sp => new SecretClient(new Uri("azure-key-vault-uri"), new DefaultAzureCredential())); - builder.AddAzureKeyVaultSecrets(); + builder.AddHealthChecks().AddAzureKeyVaultSecrets(); } ``` @@ -18,19 +18,19 @@ public void Configure(IHealthChecksBuilder builder) You can additionally add the following parameters: -- `secretClientFactory`: A factory method to provide `SecretClient` instance. -- `optionsFactory`: A factory method to provide `AzureKeyVaultSecretOptions` instance. It allows to specify the secret name and whether the secret should be created when it's not found. +- `clientFactory`: A factory method to provide `SecretClient` instance. +- `optionsFactory`: A factory method to provide `AzureKeyVaultSecretsHealthCheckOptions` instance. It allows to specify the secret name and whether the secret should be created when it's not found. - `healthCheckName`: The health check name. The default is `azure_key_vault_secret`. - `failureStatus`: The `HealthStatus` that should be reported when the health check fails. Default is `HealthStatus.Unhealthy`. - `tags`: A list of tags that can be used to filter sets of health checks. - `timeout`: A `System.TimeSpan` representing the timeout of the check. ```csharp -public void Configure(IHealthChecksBuilder builder) +void Configure(IHealthChecksBuilder builder) { builder.Services.AddSingleton(sp => new SecretClient(new Uri("azure-key-vault-uri"), new DefaultAzureCredential())); - builder.AddAzureKeyVaultSecrets( - optionsFactory: sp => new AzureKeyVaultSecretOptions() + builder.AddHealthChecks().AddAzureKeyVaultSecrets( + optionsFactory: sp => new AzureKeyVaultSecretsHealthCheckOptions() { SecretName = "demo" }); @@ -41,6 +41,6 @@ public void Configure(IHealthChecksBuilder builder) When the secret is not found, the secret client throws `RequestFailedException`. The health check catches it, but it's expensive in terms of performance. -That is why it's recommended to create the secret before using the health check. It can be done by using `AzureKeyVaultSecretOptions.CreateWhenNotFound`, but it requires secret set permissions. Such permissions should not be assigned just for the purpose of using this health check! +That is why it's recommended to create the secret before using the health check. It can be done by using `AzureKeyVaultSecretsHealthCheckOptions.CreateWhenNotFound`, but it requires secret set permissions. Such permissions should not be assigned just for the purpose of using this health check! For more information about credentials types please see [Azure TokenCredentials](https://docs.microsoft.com/dotnet/api/overview/azure/identity-readme) diff --git a/src/HealthChecks.Azure.Messaging.EventHubs/AzureEventHubHealthCheck.cs b/src/HealthChecks.Azure.Messaging.EventHubs/AzureEventHubHealthCheck.cs new file mode 100644 index 0000000000..44f4fce334 --- /dev/null +++ b/src/HealthChecks.Azure.Messaging.EventHubs/AzureEventHubHealthCheck.cs @@ -0,0 +1,29 @@ +using Azure.Messaging.EventHubs.Producer; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace HealthChecks.Azure.Messaging.EventHubs; + +public sealed class AzureEventHubHealthCheck : IHealthCheck +{ + private readonly EventHubProducerClient _client; + + public AzureEventHubHealthCheck(EventHubProducerClient client) + { + _client = Guard.ThrowIfNull(client); + } + + /// + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try + { + _ = await _client.GetEventHubPropertiesAsync(cancellationToken).ConfigureAwait(false); + + return HealthCheckResult.Healthy(); + } + catch (Exception ex) + { + return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); + } + } +} diff --git a/src/HealthChecks.Azure.Messaging.EventHubs/DependencyInjection/AzureEventHubHealthChecksBuilderExtensions.cs b/src/HealthChecks.Azure.Messaging.EventHubs/DependencyInjection/AzureEventHubHealthChecksBuilderExtensions.cs new file mode 100644 index 0000000000..96fbc34900 --- /dev/null +++ b/src/HealthChecks.Azure.Messaging.EventHubs/DependencyInjection/AzureEventHubHealthChecksBuilderExtensions.cs @@ -0,0 +1,45 @@ +using Azure.Messaging.EventHubs.Producer; +using HealthChecks.Azure.Messaging.EventHubs; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace Microsoft.Extensions.DependencyInjection; + +/// +/// Extension methods to configure . +/// +public static class AzureEventHubHealthChecksBuilderExtensions +{ + private const string HEALTH_CHECK_NAME = "azure_event_hub"; + + /// + /// Add a health check for Azure Event Hub by registering for given . + /// + /// The to add to. + /// + /// An optional factory to obtain instance. + /// When not provided, is simply resolved from . + /// + /// The health check name. Optional. If null the name 'azure_event_hub' will be used. + /// + /// 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. + /// The specified . + public static IHealthChecksBuilder AddAzureEventHub( + this IHealthChecksBuilder builder, + Func? clientFactory = default, + string? healthCheckName = HEALTH_CHECK_NAME, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + return builder.Add(new HealthCheckRegistration( + string.IsNullOrEmpty(healthCheckName) ? HEALTH_CHECK_NAME : healthCheckName!, + sp => new AzureEventHubHealthCheck(clientFactory?.Invoke(sp) ?? sp.GetRequiredService()), + failureStatus, + tags, + timeout)); + } +} diff --git a/src/HealthChecks.Azure.Messaging.EventHubs/HealthChecks.Azure.Messaging.EventHubs.csproj b/src/HealthChecks.Azure.Messaging.EventHubs/HealthChecks.Azure.Messaging.EventHubs.csproj new file mode 100644 index 0000000000..3950bb925b --- /dev/null +++ b/src/HealthChecks.Azure.Messaging.EventHubs/HealthChecks.Azure.Messaging.EventHubs.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + $(PackageTags);Azure;EventHub + HealthChecks.Azure.Messaging.EventHubs is the health check package for Azure Event Hubs. + $(HealthCheckAzureMessagingEventsHubs) + + + + + + + + diff --git a/src/HealthChecks.Azure.Messaging.EventHubs/README.md b/src/HealthChecks.Azure.Messaging.EventHubs/README.md new file mode 100644 index 0000000000..92bcf362aa --- /dev/null +++ b/src/HealthChecks.Azure.Messaging.EventHubs/README.md @@ -0,0 +1,41 @@ +## Azure Event Hubs Health Check + +This health check verifies the ability to communicate with [Azure Event Hubs](https://azure.microsoft.com/services/event-hubs/). It uses the provided [EventHubProducerClient](https://learn.microsoft.com/dotnet/api/azure.messaging.eventhubs.producer.eventhubproducerclient) to get event hub properties. + +### Defaults + +By default, the `EventHubProducerClient` instance is resolved from service provider. + +```csharp +void Configure(IHealthChecksBuilder builder) +{ + builder.Services.AddSingleton(sp => new EventHubProducerClient("fullyQualifiedNamespace", "eventHubName", new DefaultAzureCredential())); + builder.AddHealthChecks().AddAzureEventHub(); +} +``` + +### Customization + +You can additionally add the following parameters: + +- `clientFactory`: A factory method to provide `EventHubProducerClient` instance. This can be very useful when you need more than one `EventHubProducerClient` instance in your app (please see the example below that uses keyed DI introduced in .NET 8). +- `failureStatus`: The `HealthStatus` that should be reported when the health check fails. Default is `HealthStatus.Unhealthy`. +- `tags`: A list of tags that can be used to filter sets of health checks. +- `timeout`: A `System.TimeSpan` representing the timeout of the check. + +```csharp +void Configure(IHealthChecksBuilder builder) +{ + builder.Services + .AddKeyedSingleton(serviceKey: "eventHubName1", (serviceProvider, serviceKey) => new EventHubProducerClient("fullyQualifiedNamespace", "eventHubName1", new DefaultAzureCredential())) + .AddKeyedSingleton(serviceKey: "eventHubName2", (serviceProvider, serviceKey) => new EventHubProducerClient("fullyQualifiedNamespace", "eventHubName2", new DefaultAzureCredential())) + .AddHealthChecks() + .AddAzureKeyVaultSecrets(clientFactory: serviceProvider => serviceProvider.GetRequiredKeyedService("eventHubName1"), healthCheckName: "event_hub_1") + .AddAzureKeyVaultSecrets(clientFactory: serviceProvider => serviceProvider.GetRequiredKeyedService("eventHubName2"), healthCheckName: "event_hub_2"); + +} +``` + +### Breaking changes + +In the prior releases, `AzureEventHubHealthCheck` was a part of `HealthChecks.AzureServiceBus` package. It had a dependency on not just `Azure.Messaging.EventHubs`, but also `Azure.Messaging.ServiceBus`. The packages have been split to avoid bringing unnecessary dependencies. Moreover, `AzureEventHubHealthCheck` was letting the users specify how `EventHubProducerClient` should be created (from raw connection string or from fully qualified namespace and managed identity credentials), at a cost of maintaining an internal, static client instances cache. Now the type does not create client instances nor maintain an internal cache and **it's the caller responsibility to provide the instance of `EventHubProducerClient`** (please see [#2040](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/issues/2040) for more details). Since Azure SDK recommends treating clients as singletons and client instances can be expensive to create, it's recommended to register a singleton factory method for Azure SDK clients. So the clients are created only when needed and once per whole application lifetime. diff --git a/src/HealthChecks.AzureStorage/AzureBlobStorageHealthCheck.cs b/src/HealthChecks.Azure.Storage.Blobs/AzureBlobStorageHealthCheck.cs similarity index 61% rename from src/HealthChecks.AzureStorage/AzureBlobStorageHealthCheck.cs rename to src/HealthChecks.Azure.Storage.Blobs/AzureBlobStorageHealthCheck.cs index f5504a1a3b..e84cee0668 100644 --- a/src/HealthChecks.AzureStorage/AzureBlobStorageHealthCheck.cs +++ b/src/HealthChecks.Azure.Storage.Blobs/AzureBlobStorageHealthCheck.cs @@ -1,58 +1,57 @@ -using Azure.Core; -using Azure.Storage.Blobs; -using Microsoft.Extensions.Diagnostics.HealthChecks; - -namespace HealthChecks.AzureStorage; - -public class AzureBlobStorageHealthCheck : IHealthCheck -{ - private readonly BlobServiceClient _blobServiceClient; - private readonly AzureBlobStorageHealthCheckOptions _options; - - public AzureBlobStorageHealthCheck(string connectionString, string? containerName = default, BlobClientOptions? clientOptions = default) - : this( - ClientCache.GetOrAdd(connectionString, k => new BlobServiceClient(k, clientOptions)), - new AzureBlobStorageHealthCheckOptions { ContainerName = containerName }) - { } - - public AzureBlobStorageHealthCheck(Uri blobServiceUri, TokenCredential credential, string? containerName = default, BlobClientOptions? clientOptions = default) - : this( - ClientCache.GetOrAdd(blobServiceUri?.ToString()!, _ => new BlobServiceClient(blobServiceUri, credential, clientOptions)), - new AzureBlobStorageHealthCheckOptions { ContainerName = containerName }) - { } - - public AzureBlobStorageHealthCheck(BlobServiceClient blobServiceClient, AzureBlobStorageHealthCheckOptions options) - { - _blobServiceClient = Guard.ThrowIfNull(blobServiceClient); - _options = Guard.ThrowIfNull(options); - } - - /// - public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) - { - try - { - // Note: BlobServiceClient.GetPropertiesAsync() cannot be used with only the role assignment - // "Storage Blob Data Contributor," so BlobServiceClient.GetBlobContainersAsync() is used instead to probe service health. - // However, BlobContainerClient.GetPropertiesAsync() does have sufficient permissions. - await _blobServiceClient - .GetBlobContainersAsync(cancellationToken: cancellationToken) - .AsPages(pageSizeHint: 1) - .GetAsyncEnumerator(cancellationToken) - .MoveNextAsync() - .ConfigureAwait(false); - - if (!string.IsNullOrEmpty(_options.ContainerName)) - { - var containerClient = _blobServiceClient.GetBlobContainerClient(_options.ContainerName); - await containerClient.GetPropertiesAsync(cancellationToken: cancellationToken).ConfigureAwait(false); - } - - return HealthCheckResult.Healthy(); - } - catch (Exception ex) - { - return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); - } - } -} +using Azure.Storage.Blobs; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace HealthChecks.Azure.Storage.Blobs; + +/// +/// Azure Blob Storage health check. +/// +public sealed class AzureBlobStorageHealthCheck : IHealthCheck +{ + private readonly BlobServiceClient _blobServiceClient; + private readonly AzureBlobStorageHealthCheckOptions _options; + + /// + /// Creates new instance of Azure Blob Storage health check. + /// + /// + /// The used to perform Azure Blob Storage operations. + /// Azure SDK recommends treating clients as singletons , + /// so this should be the exact same instance used by other parts of the application. + /// + /// Optional settings used by the health check. + public AzureBlobStorageHealthCheck(BlobServiceClient blobServiceClient, AzureBlobStorageHealthCheckOptions? options = default) + { + _blobServiceClient = Guard.ThrowIfNull(blobServiceClient); + _options = options ?? new AzureBlobStorageHealthCheckOptions(); + } + + /// + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try + { + // Note: BlobServiceClient.GetPropertiesAsync() cannot be used with only the role assignment + // "Storage Blob Data Contributor," so BlobServiceClient.GetBlobContainersAsync() is used instead to probe service health. + // However, BlobContainerClient.GetPropertiesAsync() does have sufficient permissions. + await _blobServiceClient + .GetBlobContainersAsync(cancellationToken: cancellationToken) + .AsPages(pageSizeHint: 1) + .GetAsyncEnumerator(cancellationToken) + .MoveNextAsync() + .ConfigureAwait(false); + + if (!string.IsNullOrEmpty(_options.ContainerName)) + { + var containerClient = _blobServiceClient.GetBlobContainerClient(_options.ContainerName); + await containerClient.GetPropertiesAsync(cancellationToken: cancellationToken).ConfigureAwait(false); + } + + return HealthCheckResult.Healthy(); + } + catch (Exception ex) + { + return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); + } + } +} diff --git a/src/HealthChecks.AzureStorage/AzureBlobStorageHealthCheckOptions.cs b/src/HealthChecks.Azure.Storage.Blobs/AzureBlobStorageHealthCheckOptions.cs similarity index 93% rename from src/HealthChecks.AzureStorage/AzureBlobStorageHealthCheckOptions.cs rename to src/HealthChecks.Azure.Storage.Blobs/AzureBlobStorageHealthCheckOptions.cs index 8875f07621..612189821a 100644 --- a/src/HealthChecks.AzureStorage/AzureBlobStorageHealthCheckOptions.cs +++ b/src/HealthChecks.Azure.Storage.Blobs/AzureBlobStorageHealthCheckOptions.cs @@ -1,4 +1,4 @@ -namespace HealthChecks.AzureStorage; +namespace HealthChecks.Azure.Storage.Blobs; /// /// Represents a collection of settings that configure an diff --git a/src/HealthChecks.Azure.Storage.Blobs/DependencyInjection/AzureBlobStorageHealthChecksBuilderExtensions.cs b/src/HealthChecks.Azure.Storage.Blobs/DependencyInjection/AzureBlobStorageHealthChecksBuilderExtensions.cs new file mode 100644 index 0000000000..2ef2fffe4c --- /dev/null +++ b/src/HealthChecks.Azure.Storage.Blobs/DependencyInjection/AzureBlobStorageHealthChecksBuilderExtensions.cs @@ -0,0 +1,52 @@ +using Azure.Storage.Blobs; +using HealthChecks.Azure.Storage.Blobs; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace Microsoft.Extensions.DependencyInjection; + +/// +/// Extension methods to configure . +/// +public static class AzureBlobStorageHealthChecksBuilderExtensions +{ + private const string HEALTH_CHECK_NAME = "azure_blob_storage"; + + /// + /// Add a health check for Azure Blob Storage by registering for given . + /// + /// The to add to. + /// + /// An optional factory to obtain instance. + /// When not provided, is simply resolved from . + /// + /// + /// An optional factory to obtain used by the health check. + /// When not provided, defaults are used. + /// + /// The health check name. Optional. If null the name 'azure_blob_storage' will be used. + /// + /// 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. + /// The specified . + public static IHealthChecksBuilder AddAzureBlobStorage( + this IHealthChecksBuilder builder, + Func? clientFactory = default, + Func? optionsFactory = default, + string? healthCheckName = HEALTH_CHECK_NAME, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + return builder.Add(new HealthCheckRegistration( + string.IsNullOrEmpty(healthCheckName) ? HEALTH_CHECK_NAME : healthCheckName!, + sp => new AzureBlobStorageHealthCheck( + blobServiceClient: clientFactory?.Invoke(sp) ?? sp.GetRequiredService(), + options: optionsFactory?.Invoke(sp)), + failureStatus, + tags, + timeout)); + } +} diff --git a/src/HealthChecks.Azure.Storage.Blobs/HealthChecks.Azure.Storage.Blobs.csproj b/src/HealthChecks.Azure.Storage.Blobs/HealthChecks.Azure.Storage.Blobs.csproj new file mode 100644 index 0000000000..97cf7cf611 --- /dev/null +++ b/src/HealthChecks.Azure.Storage.Blobs/HealthChecks.Azure.Storage.Blobs.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + $(PackageTags);Azure;AzureStorage + HealthChecks.Azure.Storage.Blobs is the health check package for Blobs. + $(HealthCheckAzureStorageBlobs) + + + + + + + + diff --git a/src/HealthChecks.Azure.Storage.Blobs/README.md b/src/HealthChecks.Azure.Storage.Blobs/README.md new file mode 100644 index 0000000000..0dfde59389 --- /dev/null +++ b/src/HealthChecks.Azure.Storage.Blobs/README.md @@ -0,0 +1,43 @@ +## Azure Blob Storage Health Check + +This health check verifies the ability to communicate with [Azure Blob Storage](https://azure.microsoft.com/en-us/products/storage/blobs/). It uses the provided [BlobServiceClient](https://learn.microsoft.com/dotnet/api/azure.storage.blobs.blobserviceclient) to get first or configured blob container. + +### Defaults + +By default, the `BlobServiceClient` instance is resolved from service provider. `AzureBlobStorageHealthCheckOptions` does not provide any specific container name, so the health check fetches just first container. + +```csharp +void Configure(IHealthChecksBuilder builder) +{ + builder.Services.AddSingleton(sp => new BlobServiceClient(new Uri("azure-blob-storage-uri"), new DefaultAzureCredential())); + builder.AddHealthChecks().AddAzureBlobStorage(); +} +``` + +### Customization + +You can additionally add the following parameters: + +- `clientFactory`: A factory method to provide `BlobServiceClient` instance. +- `optionsFactory`: A factory method to provide `AzureBlobStorageHealthCheckOptions` instance. It allows to specify the container name. +- `healthCheckName`: The health check name. The default is `azure_blob_storage`. +- `failureStatus`: The `HealthStatus` that should be reported when the health check fails. Default is `HealthStatus.Unhealthy`. +- `tags`: A list of tags that can be used to filter sets of health checks. +- `timeout`: A `System.TimeSpan` representing the timeout of the check. + +```csharp +void Configure(IHealthChecksBuilder builder) +{ + builder.Services.AddSingleton(sp => new BlobServiceClient(new Uri("azure-blob-storage-uri"), new DefaultAzureCredential())); + builder.AddHealthChecks().AddAzureBlobStorage( + optionsFactory: sp => new AzureBlobStorageHealthCheckOptions() + { + ContainerName = "demo" + }); +} +``` + +### Breaking changes + +In the prior releases, `AzureBlobStorageHealthCheck` was a part of `HealthChecks.AzureStorage` package. It had a dependency on not just `Azure.Storage.Blobs`, but also `Azure.Storage.Queues` and `Azure.Storage.Files.Shares`. The packages have been split to avoid bringing unnecessary dependencies. Moreover, `AzureBlobStorageHealthCheck` was letting the users specify how `BlobServiceClient` should be created (from raw connection string or from endpoint uri and managed identity credentials), at a cost of maintaining an internal, static client instances cache. Now the type does not create client instances nor maintain an internal cache and **it's the caller responsibility to provide the instance of `BlobServiceClient`** (please see [#2040](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/issues/2040) for more details). Since Azure SDK recommends treating clients as singletons and client instances can be expensive to create, it's recommended to register a singleton factory method for Azure SDK clients. So the clients are created only when needed and once per whole application lifetime. + diff --git a/src/HealthChecks.AzureStorage/AzureFileShareHealthCheck.cs b/src/HealthChecks.Azure.Storage.Files.Shares/AzureFileShareHealthCheck.cs similarity index 77% rename from src/HealthChecks.AzureStorage/AzureFileShareHealthCheck.cs rename to src/HealthChecks.Azure.Storage.Files.Shares/AzureFileShareHealthCheck.cs index 23325fd5dc..cb8472322d 100644 --- a/src/HealthChecks.AzureStorage/AzureFileShareHealthCheck.cs +++ b/src/HealthChecks.Azure.Storage.Files.Shares/AzureFileShareHealthCheck.cs @@ -1,23 +1,20 @@ using Azure.Storage.Files.Shares; using Microsoft.Extensions.Diagnostics.HealthChecks; -namespace HealthChecks.AzureStorage; +namespace HealthChecks.Azure.Storage.Files.Shares; -public class AzureFileShareHealthCheck : IHealthCheck +/// +/// Azure Files health check. +/// +public sealed class AzureFileShareHealthCheck : IHealthCheck { private readonly ShareServiceClient _shareServiceClient; private readonly AzureFileShareHealthCheckOptions _options; - public AzureFileShareHealthCheck(string connectionString, string? shareName = default) - : this( - ClientCache.GetOrAdd(connectionString, _ => new ShareServiceClient(connectionString)), - new AzureFileShareHealthCheckOptions { ShareName = shareName }) - { } - - public AzureFileShareHealthCheck(ShareServiceClient shareServiceClient, AzureFileShareHealthCheckOptions options) + public AzureFileShareHealthCheck(ShareServiceClient shareServiceClient, AzureFileShareHealthCheckOptions? options) { _shareServiceClient = Guard.ThrowIfNull(shareServiceClient); - _options = Guard.ThrowIfNull(options); + _options = options ?? new(); } /// diff --git a/src/HealthChecks.AzureStorage/AzureFileShareHealthCheckOptions.cs b/src/HealthChecks.Azure.Storage.Files.Shares/AzureFileShareHealthCheckOptions.cs similarity index 92% rename from src/HealthChecks.AzureStorage/AzureFileShareHealthCheckOptions.cs rename to src/HealthChecks.Azure.Storage.Files.Shares/AzureFileShareHealthCheckOptions.cs index d8fc138eb3..22fc703848 100644 --- a/src/HealthChecks.AzureStorage/AzureFileShareHealthCheckOptions.cs +++ b/src/HealthChecks.Azure.Storage.Files.Shares/AzureFileShareHealthCheckOptions.cs @@ -1,4 +1,4 @@ -namespace HealthChecks.AzureStorage; +namespace HealthChecks.Azure.Storage.Files.Shares; /// /// Represents a collection of settings that configure an diff --git a/src/HealthChecks.Azure.Storage.Files.Shares/DependencyInjection/AzureQueueStorageHealthChecksBuilderExtensions.cs b/src/HealthChecks.Azure.Storage.Files.Shares/DependencyInjection/AzureQueueStorageHealthChecksBuilderExtensions.cs new file mode 100644 index 0000000000..dabdd56481 --- /dev/null +++ b/src/HealthChecks.Azure.Storage.Files.Shares/DependencyInjection/AzureQueueStorageHealthChecksBuilderExtensions.cs @@ -0,0 +1,52 @@ +using Azure.Storage.Files.Shares; +using HealthChecks.Azure.Storage.Files.Shares; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace Microsoft.Extensions.DependencyInjection; + +/// +/// Extension methods to configure . +/// +public static class AzureFileShareStorageHealthChecksBuilderExtensions +{ + private const string HEALTH_CHECK_NAME = "azure_file_share"; + + /// + /// Add a health check for Azure Files by registering for given . + /// + /// The to add to. + /// + /// An optional factory to obtain instance. + /// When not provided, is simply resolved from . + /// + /// + /// An optional factory to obtain used by the health check. + /// When not provided, defaults are used. + /// + /// The health check name. Optional. If null the name 'azure_file_share' will be used. + /// + /// 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. + /// The specified . + public static IHealthChecksBuilder AddAzureFileShare( + this IHealthChecksBuilder builder, + Func? clientFactory = default, + Func? optionsFactory = default, + string? healthCheckName = HEALTH_CHECK_NAME, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + return builder.Add(new HealthCheckRegistration( + string.IsNullOrEmpty(healthCheckName) ? HEALTH_CHECK_NAME : healthCheckName!, + sp => new AzureFileShareHealthCheck( + shareServiceClient: clientFactory?.Invoke(sp) ?? sp.GetRequiredService(), + options: optionsFactory?.Invoke(sp)), + failureStatus, + tags, + timeout)); + } +} diff --git a/src/HealthChecks.AzureStorage/HealthChecks.AzureStorage.csproj b/src/HealthChecks.Azure.Storage.Files.Shares/HealthChecks.Azure.Storage.Files.Shares.csproj similarity index 55% rename from src/HealthChecks.AzureStorage/HealthChecks.AzureStorage.csproj rename to src/HealthChecks.Azure.Storage.Files.Shares/HealthChecks.Azure.Storage.Files.Shares.csproj index e84c5f359b..9cab99a4be 100644 --- a/src/HealthChecks.AzureStorage/HealthChecks.AzureStorage.csproj +++ b/src/HealthChecks.Azure.Storage.Files.Shares/HealthChecks.Azure.Storage.Files.Shares.csproj @@ -3,13 +3,11 @@ netstandard2.0 $(PackageTags);Azure;AzureStorage - HealthChecks.AzureStorage is the health check package for Blobs, Tables and Queues. - $(HealthCheckAzureStorage) + HealthChecks.Azure.Storage.Files.Shares is the health check package for Azure File Shares. + $(HealthCheckAzureStorageFilesShares) - - diff --git a/src/HealthChecks.Azure.Storage.Files.Shares/README.md b/src/HealthChecks.Azure.Storage.Files.Shares/README.md new file mode 100644 index 0000000000..771c223304 --- /dev/null +++ b/src/HealthChecks.Azure.Storage.Files.Shares/README.md @@ -0,0 +1,42 @@ +## Azure File Storage Health Check + +This health check verifies the ability to communicate with [Azure File Storage](https://azure.microsoft.com/en-us/products/storage/files/). It uses the provided [ShareServiceClient](https://learn.microsoft.com/dotnet/api/azure.storage.files.shares.shareserviceclient) to get first share or configured share properties. + +### Defaults + +By default, the `ShareServiceClient` instance is resolved from service provider. `AzureFileShareHealthCheckOptions` does not provide any specific share name, so the health check fetches just first share. + +```csharp +void Configure(IHealthChecksBuilder builder) +{ + builder.Services.AddSingleton(sp => new ShareServiceClient(new Uri("azure-file-share-storage-uri"), new DefaultAzureCredential())); + builder.AddHealthChecks().AddAzureFileShare(); +} +``` + +### Customization + +You can additionally add the following parameters: + +- `clientFactory`: A factory method to provide `ShareServiceClient` instance. +- `optionsFactory`: A factory method to provide `AzureFileShareHealthCheckOptions` instance. It allows to specify the share name. +- `healthCheckName`: The health check name. The default is `azure_file_share`. +- `failureStatus`: The `HealthStatus` that should be reported when the health check fails. Default is `HealthStatus.Unhealthy`. +- `tags`: A list of tags that can be used to filter sets of health checks. +- `timeout`: A `System.TimeSpan` representing the timeout of the check. + +```csharp +void Configure(IHealthChecksBuilder builder) +{ + builder.Services.AddSingleton(sp => new ShareServiceClient(new Uri("azure-file-share-storage-uri"), new DefaultAzureCredential())); + builder.AddHealthChecks().AddAzureFileShare( + optionsFactory: sp => new AzureFileShareHealthCheckOptions() + { + ShareName = "demo" + }); +} +``` + +### Breaking changes + +In the prior releases, `AzureFileShareHealthCheck` was a part of `HealthChecks.AzureStorage` package. It had a dependency on not just `Azure.Storage.Files.Shares`, but also `Azure.Storage.Queues` and `Azure.Storage.Blobs`. The packages have been split to avoid bringing unnecessary dependencies. Moreover, `AzureFileShareHealthCheck` was letting the users specify how `ShareServiceClient` should be created (from raw connection string), at a cost of maintaining an internal, static client instances cache. Now the type does not create client instances nor maintain an internal cache and **it's the caller responsibility to provide the instance of `ShareServiceClient`** (please see [#2040](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/issues/2040) for more details). Since Azure SDK recommends treating clients as singletons and client instances can be expensive to create, it's recommended to register a singleton factory method for Azure SDK clients. So the clients are created only when needed and once per whole application lifetime. diff --git a/src/HealthChecks.AzureStorage/AzureQueueStorageHealthCheck.cs b/src/HealthChecks.Azure.Storage.Queues/AzureQueueStorageHealthCheck.cs similarity index 64% rename from src/HealthChecks.AzureStorage/AzureQueueStorageHealthCheck.cs rename to src/HealthChecks.Azure.Storage.Queues/AzureQueueStorageHealthCheck.cs index a94205db6f..3201cd6c5d 100644 --- a/src/HealthChecks.AzureStorage/AzureQueueStorageHealthCheck.cs +++ b/src/HealthChecks.Azure.Storage.Queues/AzureQueueStorageHealthCheck.cs @@ -1,58 +1,57 @@ -using Azure.Core; -using Azure.Storage.Queues; -using Microsoft.Extensions.Diagnostics.HealthChecks; - -namespace HealthChecks.AzureStorage; - -public class AzureQueueStorageHealthCheck : IHealthCheck -{ - private readonly QueueServiceClient _queueServiceClient; - private readonly AzureQueueStorageHealthCheckOptions _options; - - public AzureQueueStorageHealthCheck(string connectionString, string? queueName = default) - : this( - ClientCache.GetOrAdd(connectionString, k => new QueueServiceClient(k)), - new AzureQueueStorageHealthCheckOptions { QueueName = queueName }) - { } - - public AzureQueueStorageHealthCheck(Uri queueServiceUri, TokenCredential credential, string? queueName = default) - : this( - ClientCache.GetOrAdd(queueServiceUri?.ToString()!, _ => new QueueServiceClient(queueServiceUri, credential)), - new AzureQueueStorageHealthCheckOptions { QueueName = queueName }) - { } - - public AzureQueueStorageHealthCheck(QueueServiceClient queueServiceClient, AzureQueueStorageHealthCheckOptions options) - { - _queueServiceClient = Guard.ThrowIfNull(queueServiceClient); - _options = Guard.ThrowIfNull(options); - } - - /// - public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) - { - try - { - // Note: QueueServiceClient.GetPropertiesAsync() cannot be used with only the role assignment - // "Storage Queue Data Contributor," so QueueServiceClient.GetQueuesAsync() is used instead to probe service health. - // However, QueueClient.GetPropertiesAsync() does have sufficient permissions. - await _queueServiceClient - .GetQueuesAsync(cancellationToken: cancellationToken) - .AsPages(pageSizeHint: 1) - .GetAsyncEnumerator(cancellationToken) - .MoveNextAsync() - .ConfigureAwait(false); - - if (!string.IsNullOrEmpty(_options.QueueName)) - { - var queueClient = _queueServiceClient.GetQueueClient(_options.QueueName); - await queueClient.GetPropertiesAsync(cancellationToken).ConfigureAwait(false); - } - - return HealthCheckResult.Healthy(); - } - catch (Exception ex) - { - return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); - } - } -} +using Azure.Storage.Queues; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace HealthChecks.Azure.Storage.Queues; + +/// +/// Azure Queue Storage health check. +/// +public sealed class AzureQueueStorageHealthCheck : IHealthCheck +{ + private readonly QueueServiceClient _queueServiceClient; + private readonly AzureQueueStorageHealthCheckOptions _options; + + /// + /// Creates new instance of Azure Queue Storage health check. + /// + /// + /// The used to perform Azure Queue Storage operations. + /// Azure SDK recommends treating clients as singletons , + /// so this should be the exact same instance used by other parts of the application. + /// + /// Optional settings used by the health check. + public AzureQueueStorageHealthCheck(QueueServiceClient queueServiceClient, AzureQueueStorageHealthCheckOptions? options = default) + { + _queueServiceClient = Guard.ThrowIfNull(queueServiceClient); + _options = options ?? new(); + } + + /// + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try + { + // Note: QueueServiceClient.GetPropertiesAsync() cannot be used with only the role assignment + // "Storage Queue Data Contributor," so QueueServiceClient.GetQueuesAsync() is used instead to probe service health. + // However, QueueClient.GetPropertiesAsync() does have sufficient permissions. + await _queueServiceClient + .GetQueuesAsync(cancellationToken: cancellationToken) + .AsPages(pageSizeHint: 1) + .GetAsyncEnumerator(cancellationToken) + .MoveNextAsync() + .ConfigureAwait(false); + + if (!string.IsNullOrEmpty(_options.QueueName)) + { + var queueClient = _queueServiceClient.GetQueueClient(_options.QueueName); + await queueClient.GetPropertiesAsync(cancellationToken).ConfigureAwait(false); + } + + return HealthCheckResult.Healthy(); + } + catch (Exception ex) + { + return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); + } + } +} diff --git a/src/HealthChecks.AzureStorage/AzureQueueStorageHealthCheckOptions.cs b/src/HealthChecks.Azure.Storage.Queues/AzureQueueStorageHealthCheckOptions.cs similarity index 92% rename from src/HealthChecks.AzureStorage/AzureQueueStorageHealthCheckOptions.cs rename to src/HealthChecks.Azure.Storage.Queues/AzureQueueStorageHealthCheckOptions.cs index 08d91cd115..5a97230105 100644 --- a/src/HealthChecks.AzureStorage/AzureQueueStorageHealthCheckOptions.cs +++ b/src/HealthChecks.Azure.Storage.Queues/AzureQueueStorageHealthCheckOptions.cs @@ -1,4 +1,4 @@ -namespace HealthChecks.AzureStorage; +namespace HealthChecks.Azure.Storage.Queues; /// /// Represents a collection of settings that configure an diff --git a/src/HealthChecks.Azure.Storage.Queues/DependencyInjection/AzureQueueStorageHealthChecksBuilderExtensions.cs b/src/HealthChecks.Azure.Storage.Queues/DependencyInjection/AzureQueueStorageHealthChecksBuilderExtensions.cs new file mode 100644 index 0000000000..76fcf4c417 --- /dev/null +++ b/src/HealthChecks.Azure.Storage.Queues/DependencyInjection/AzureQueueStorageHealthChecksBuilderExtensions.cs @@ -0,0 +1,52 @@ +using Azure.Storage.Queues; +using HealthChecks.Azure.Storage.Queues; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace Microsoft.Extensions.DependencyInjection; + +/// +/// Extension methods to configure . +/// +public static class AzureQueueStorageHealthChecksBuilderExtensions +{ + private const string HEALTH_CHECK_NAME = "azure_queue_storage"; + + /// + /// Add a health check for Azure Queue Storage by registering for given . + /// + /// The to add to. + /// + /// An optional factory to obtain instance. + /// When not provided, is simply resolved from . + /// + /// + /// An optional factory to obtain used by the health check. + /// When not provided, defaults are used. + /// + /// The health check name. Optional. If null the name 'azure_queue_storage' will be used. + /// + /// 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. + /// The specified . + public static IHealthChecksBuilder AddAzureQueueStorage( + this IHealthChecksBuilder builder, + Func? clientFactory = default, + Func? optionsFactory = default, + string? healthCheckName = HEALTH_CHECK_NAME, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + return builder.Add(new HealthCheckRegistration( + string.IsNullOrEmpty(healthCheckName) ? HEALTH_CHECK_NAME : healthCheckName!, + sp => new AzureQueueStorageHealthCheck( + queueServiceClient: clientFactory?.Invoke(sp) ?? sp.GetRequiredService(), + options: optionsFactory?.Invoke(sp)), + failureStatus, + tags, + timeout)); + } +} diff --git a/src/HealthChecks.Azure.Storage.Queues/HealthChecks.Azure.Storage.Queues.csproj b/src/HealthChecks.Azure.Storage.Queues/HealthChecks.Azure.Storage.Queues.csproj new file mode 100644 index 0000000000..7c94ee5ca6 --- /dev/null +++ b/src/HealthChecks.Azure.Storage.Queues/HealthChecks.Azure.Storage.Queues.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.0 + $(PackageTags);Azure;AzureStorage + HealthChecks.Azure.Storage.Queues is the health check package for Azure Storage Queues. + $(HealthCheckAzureStorageQueues) + + + + + + + + diff --git a/src/HealthChecks.Azure.Storage.Queues/README.md b/src/HealthChecks.Azure.Storage.Queues/README.md new file mode 100644 index 0000000000..48ecbe1c0b --- /dev/null +++ b/src/HealthChecks.Azure.Storage.Queues/README.md @@ -0,0 +1,43 @@ +## Azure Queue Storage Health Check + +This health check verifies the ability to communicate with [Azure Queue Storage](https://azure.microsoft.com/en-us/products/storage/queues/). It uses the provided [QueueServiceClient](https://learn.microsoft.com/dotnet/api/azure.storage.queues.queueserviceclient) to get first queue or configured queues properties. + +### Defaults + +By default, the `QueueServiceClient` instance is resolved from service provider. `AzureQueueStorageHealthCheckOptions` does not provide any specific queue name, so the health check fetches just first queue. + +```csharp +void Configure(IHealthChecksBuilder builder) +{ + builder.Services.AddSingleton(sp => new QueueServiceClient(new Uri("azure-queue-storage-uri"), new DefaultAzureCredential())); + builder.AddHealthChecks().AddAzureQueueStorage(); +} +``` + +### Customization + +You can additionally add the following parameters: + +- `clientFactory`: A factory method to provide `QueueServiceClient` instance. +- `optionsFactory`: A factory method to provide `AzureQueueStorageHealthCheckOptions` instance. It allows to specify the queue name. +- `healthCheckName`: The health check name. The default is `azure_queue_storage`. +- `failureStatus`: The `HealthStatus` that should be reported when the health check fails. Default is `HealthStatus.Unhealthy`. +- `tags`: A list of tags that can be used to filter sets of health checks. +- `timeout`: A `System.TimeSpan` representing the timeout of the check. + +```csharp +void Configure(IHealthChecksBuilder builder) +{ + builder.Services.AddSingleton(sp => new QueueServiceClient(new Uri("azure-queue-storage-uri"), new DefaultAzureCredential())); + builder.AddHealthChecks().AddAzureQueueStorage( + optionsFactory: sp => new AzureQueueStorageHealthCheckOptions() + { + QueueName = "demo" + }); +} +``` + +### Breaking changes + +In the prior releases, `AzureQueueStorageHealthCheck` was a part of `HealthChecks.AzureStorage` package. It had a dependency on not just `Azure.Storage.Queues`, but also `Azure.Storage.Files.Shares` and `Azure.Storage.Blobs`. The packages have been split to avoid bringing unnecessary dependencies. Moreover, `AzureQueueStorageHealthCheck` was letting the users specify how `QueueServiceClient` should be created (from raw connection string or an endpoint with managed identity credentials), at a cost of maintaining an internal, static client instances cache. Now the type does not create client instances nor maintain an internal cache and **it's the caller responsibility to provide the instance of `ShareServiceClient`** (please see [#2040](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/issues/2040) for more details). Since Azure SDK recommends treating clients as singletons and client instances can be expensive to create, it's recommended to register a singleton factory method for Azure SDK clients. So the clients are created only when needed and once per whole application lifetime. + diff --git a/src/HealthChecks.AzureServiceBus/AzureEventHubHealthCheck.cs b/src/HealthChecks.AzureServiceBus/AzureEventHubHealthCheck.cs deleted file mode 100644 index 004bd2d8d2..0000000000 --- a/src/HealthChecks.AzureServiceBus/AzureEventHubHealthCheck.cs +++ /dev/null @@ -1,101 +0,0 @@ -using Azure.Messaging.EventHubs; -using Azure.Messaging.EventHubs.Producer; -using HealthChecks.AzureServiceBus.Configuration; -using Microsoft.Extensions.Diagnostics.HealthChecks; - -namespace HealthChecks.AzureServiceBus; - -public class AzureEventHubHealthCheck : IHealthCheck -{ - private const string ENTITY_PATH_SEGMENT = "EntityPath="; - private readonly AzureEventHubHealthCheckOptions _options; - - private string? _connectionKey; - - private string ConnectionKey => _connectionKey ??= _options.ConnectionString is null - ? $"{_options.FullyQualifiedNamespace}_{_options.EventHubName}" - : GetFullConnectionString(); - - public AzureEventHubHealthCheck(AzureEventHubHealthCheckOptions options) - { - _options = options; - - if (!string.IsNullOrWhiteSpace(options.ConnectionString)) - { - Guard.ThrowIfNull(options.EventHubName, true); - return; - } - - if (options.Credential is not null) - { - Guard.ThrowIfNull(options.FullyQualifiedNamespace, true); - Guard.ThrowIfNull(options.EventHubName, true); - return; - } - - if (options.Connection is not null) - { - _connectionKey = $"{options.Connection.FullyQualifiedNamespace}_{options.Connection.EventHubName}"; - return; - } - - throw new ArgumentException("A connection string, TokenCredential or EventHubConnection must be set!", - nameof(options)); - } - - /// - public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) - { - try - { - var client = await ClientCache.GetOrAddAsyncDisposableAsync(ConnectionKey, _ => CreateClient(context)).ConfigureAwait(false); - - _ = await client.GetEventHubPropertiesAsync(cancellationToken).ConfigureAwait(false); - - return HealthCheckResult.Healthy(); - } - catch (Exception ex) - { - return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); - } - } - - private EventHubProducerClient CreateClient(HealthCheckContext context) - { - var clientOptions = CreateClientOptions(context); - - if (_options.ConnectionString is not null) - return new EventHubProducerClient(GetFullConnectionString(), clientOptions); - - if (_options.Connection is not null) - return new EventHubProducerClient(_options.Connection, clientOptions); - - return new EventHubProducerClient(_options.FullyQualifiedNamespace, _options.EventHubName, _options.Credential, clientOptions); - } - - private string GetFullConnectionString() - { - string connectionString = _options.ConnectionString!; - - if (!connectionString.Contains(ENTITY_PATH_SEGMENT)) - connectionString = $"{connectionString};{ENTITY_PATH_SEGMENT}{_options.EventHubName}"; - return connectionString; - } - - private static EventHubProducerClientOptions CreateClientOptions(HealthCheckContext context) => new() - { - ConnectionOptions = CreateConnectionOptions(context) - }; - - private static EventHubConnectionOptions CreateConnectionOptions(HealthCheckContext context) - { - EventHubConnectionOptions options = new(); - - if (context.Registration.Timeout.TotalMilliseconds > 0) - { - options.ConnectionIdleTimeout = context.Registration.Timeout; - } - - return options; - } -} diff --git a/src/HealthChecks.AzureServiceBus/AzureServiceBusQueueHealthCheck.cs b/src/HealthChecks.AzureServiceBus/AzureServiceBusQueueHealthCheck.cs index cf5379533a..aeb694c0c7 100644 --- a/src/HealthChecks.AzureServiceBus/AzureServiceBusQueueHealthCheck.cs +++ b/src/HealthChecks.AzureServiceBus/AzureServiceBusQueueHealthCheck.cs @@ -1,57 +1,57 @@ -using HealthChecks.AzureServiceBus.Configuration; -using Microsoft.Extensions.Diagnostics.HealthChecks; - -namespace HealthChecks.AzureServiceBus; - -public class AzureServiceBusQueueHealthCheck : AzureServiceBusHealthCheck, IHealthCheck -{ - private readonly string _queueKey; - - public AzureServiceBusQueueHealthCheck(AzureServiceBusQueueHealthCheckOptions options, ServiceBusClientProvider clientProvider) - : base(options, clientProvider) - { - Guard.ThrowIfNull(options.QueueName, true); - - _queueKey = $"{nameof(AzureServiceBusQueueHealthCheck)}_{ConnectionKey}_{Options.QueueName}"; - } - - public AzureServiceBusQueueHealthCheck(AzureServiceBusQueueHealthCheckOptions options) - : this(options, new ServiceBusClientProvider()) - { } - - /// - public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) - { - try - { - if (Options.UsePeekMode) - await CheckWithReceiver().ConfigureAwait(false); - else - await CheckWithManagement().ConfigureAwait(false); - - return HealthCheckResult.Healthy(); - } - catch (Exception ex) - { - return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); - } - - async Task CheckWithReceiver() - { - var client = await ClientCache.GetOrAddAsyncDisposableAsync(ConnectionKey, _ => CreateClient()).ConfigureAwait(false); - var receiver = await ClientCache.GetOrAddAsyncDisposableAsync( - _queueKey, - _ => client.CreateReceiver(Options.QueueName)) - .ConfigureAwait(false); - - await receiver.PeekMessageAsync(cancellationToken: cancellationToken).ConfigureAwait(false); - } - - Task CheckWithManagement() - { - var managementClient = ClientCache.GetOrAdd(ConnectionKey, _ => CreateManagementClient()); - - return managementClient.GetQueueRuntimePropertiesAsync(Options.QueueName, cancellationToken); - } - } -} +using HealthChecks.AzureServiceBus.Configuration; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace HealthChecks.AzureServiceBus; + +public class AzureServiceBusQueueHealthCheck : AzureServiceBusHealthCheck, IHealthCheck +{ + private readonly string _queueKey; + + public AzureServiceBusQueueHealthCheck(AzureServiceBusQueueHealthCheckOptions options, ServiceBusClientProvider clientProvider) + : base(options, clientProvider) + { + Guard.ThrowIfNull(options.QueueName, true); + + _queueKey = $"{nameof(AzureServiceBusQueueHealthCheck)}_{ConnectionKey}_{Options.QueueName}"; + } + + public AzureServiceBusQueueHealthCheck(AzureServiceBusQueueHealthCheckOptions options) + : this(options, new ServiceBusClientProvider()) + { } + + /// + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try + { + if (Options.UsePeekMode) + await CheckWithReceiver().ConfigureAwait(false); + else + await CheckWithManagement().ConfigureAwait(false); + + return HealthCheckResult.Healthy(); + } + catch (Exception ex) + { + return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); + } + + async Task CheckWithReceiver() + { + var client = await ClientCache.GetOrAddAsyncDisposableAsync(ConnectionKey, _ => CreateClient()).ConfigureAwait(false); + var receiver = await ClientCache.GetOrAddAsyncDisposableAsync( + _queueKey, + _ => client.CreateReceiver(Options.QueueName)) + .ConfigureAwait(false); + + await receiver.PeekMessageAsync(cancellationToken: cancellationToken).ConfigureAwait(false); + } + + Task CheckWithManagement() + { + var managementClient = ClientCache.GetOrAdd(ConnectionKey, _ => CreateManagementClient()); + + return managementClient.GetQueueRuntimePropertiesAsync(Options.QueueName, cancellationToken); + } + } +} diff --git a/src/HealthChecks.AzureServiceBus/AzureServiceBusQueueMessageCountThresholdHealthCheck.cs b/src/HealthChecks.AzureServiceBus/AzureServiceBusQueueMessageCountThresholdHealthCheck.cs index 6dc6384088..0de71d5868 100644 --- a/src/HealthChecks.AzureServiceBus/AzureServiceBusQueueMessageCountThresholdHealthCheck.cs +++ b/src/HealthChecks.AzureServiceBus/AzureServiceBusQueueMessageCountThresholdHealthCheck.cs @@ -1,83 +1,83 @@ -using HealthChecks.AzureServiceBus.Configuration; -using Microsoft.Extensions.Diagnostics.HealthChecks; - -namespace HealthChecks.AzureServiceBus; - -public class AzureServiceBusQueueMessageCountThresholdHealthCheck : AzureServiceBusHealthCheck, IHealthCheck -{ - private readonly string _queueName; - private readonly AzureServiceBusQueueMessagesCountThreshold? _activeMessagesThreshold; - private readonly AzureServiceBusQueueMessagesCountThreshold? _deadLetterMessagesThreshold; - - public AzureServiceBusQueueMessageCountThresholdHealthCheck(AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions options, ServiceBusClientProvider clientProvider) - : base(options, clientProvider) - { - _queueName = Guard.ThrowIfNull(options.QueueName); - _activeMessagesThreshold = options.ActiveMessages; - _deadLetterMessagesThreshold = options.DeadLetterMessages; - } - - public AzureServiceBusQueueMessageCountThresholdHealthCheck(AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions options) - : this(options, new ServiceBusClientProvider()) - { } - - /// - public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) - { - try - { - var managementClient = ClientCache.GetOrAdd(ConnectionKey, _ => CreateManagementClient()); - - var properties = await managementClient.GetQueueRuntimePropertiesAsync(_queueName, cancellationToken).ConfigureAwait(false); - - var activeQueueHealthStatus = CheckHealthStatus( - properties.Value.ActiveMessageCount, - _activeMessagesThreshold, - "queue"); - - if (activeQueueHealthStatus.Status != HealthStatus.Healthy) - { - return activeQueueHealthStatus; - } - - var deadLetterQueueHealthStatus = CheckHealthStatus( - properties.Value.DeadLetterMessageCount, - _deadLetterMessagesThreshold, - "dead letter queue"); - - if (deadLetterQueueHealthStatus.Status != HealthStatus.Healthy) - { - return deadLetterQueueHealthStatus; - } - - return HealthCheckResult.Healthy(); - } - catch (Exception ex) - { - return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); - } - } - - private HealthCheckResult CheckHealthStatus( - long messagesCount, - AzureServiceBusQueueMessagesCountThreshold? threshold, - string queueType) - { - if (threshold is null) - { - return HealthCheckResult.Healthy(); - } - - if (messagesCount >= threshold.Value.UnhealthyThreshold) - { - return HealthCheckResult.Unhealthy($"Message in {queueType} {_queueName} exceeded the amount of messages allowed for the unhealthy threshold {threshold.Value.UnhealthyThreshold}/{messagesCount}"); - } - - if (messagesCount >= threshold.Value.DegradedThreshold) - { - return HealthCheckResult.Degraded($"Message in {queueType} {_queueName} exceeded the amount of messages allowed for the degraded threshold {threshold.Value.DegradedThreshold}/{messagesCount}"); - } - - return HealthCheckResult.Healthy(); - } -} +using HealthChecks.AzureServiceBus.Configuration; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace HealthChecks.AzureServiceBus; + +public class AzureServiceBusQueueMessageCountThresholdHealthCheck : AzureServiceBusHealthCheck, IHealthCheck +{ + private readonly string _queueName; + private readonly AzureServiceBusQueueMessagesCountThreshold? _activeMessagesThreshold; + private readonly AzureServiceBusQueueMessagesCountThreshold? _deadLetterMessagesThreshold; + + public AzureServiceBusQueueMessageCountThresholdHealthCheck(AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions options, ServiceBusClientProvider clientProvider) + : base(options, clientProvider) + { + _queueName = Guard.ThrowIfNull(options.QueueName); + _activeMessagesThreshold = options.ActiveMessages; + _deadLetterMessagesThreshold = options.DeadLetterMessages; + } + + public AzureServiceBusQueueMessageCountThresholdHealthCheck(AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions options) + : this(options, new ServiceBusClientProvider()) + { } + + /// + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try + { + var managementClient = ClientCache.GetOrAdd(ConnectionKey, _ => CreateManagementClient()); + + var properties = await managementClient.GetQueueRuntimePropertiesAsync(_queueName, cancellationToken).ConfigureAwait(false); + + var activeQueueHealthStatus = CheckHealthStatus( + properties.Value.ActiveMessageCount, + _activeMessagesThreshold, + "queue"); + + if (activeQueueHealthStatus.Status != HealthStatus.Healthy) + { + return activeQueueHealthStatus; + } + + var deadLetterQueueHealthStatus = CheckHealthStatus( + properties.Value.DeadLetterMessageCount, + _deadLetterMessagesThreshold, + "dead letter queue"); + + if (deadLetterQueueHealthStatus.Status != HealthStatus.Healthy) + { + return deadLetterQueueHealthStatus; + } + + return HealthCheckResult.Healthy(); + } + catch (Exception ex) + { + return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); + } + } + + private HealthCheckResult CheckHealthStatus( + long messagesCount, + AzureServiceBusQueueMessagesCountThreshold? threshold, + string queueType) + { + if (threshold is null) + { + return HealthCheckResult.Healthy(); + } + + if (messagesCount >= threshold.Value.UnhealthyThreshold) + { + return HealthCheckResult.Unhealthy($"Message in {queueType} {_queueName} exceeded the amount of messages allowed for the unhealthy threshold {threshold.Value.UnhealthyThreshold}/{messagesCount}"); + } + + if (messagesCount >= threshold.Value.DegradedThreshold) + { + return HealthCheckResult.Degraded($"Message in {queueType} {_queueName} exceeded the amount of messages allowed for the degraded threshold {threshold.Value.DegradedThreshold}/{messagesCount}"); + } + + return HealthCheckResult.Healthy(); + } +} diff --git a/src/HealthChecks.AzureServiceBus/AzureServiceBusTopicHealthCheck.cs b/src/HealthChecks.AzureServiceBus/AzureServiceBusTopicHealthCheck.cs index 70497aaabb..42c8398d9c 100644 --- a/src/HealthChecks.AzureServiceBus/AzureServiceBusTopicHealthCheck.cs +++ b/src/HealthChecks.AzureServiceBus/AzureServiceBusTopicHealthCheck.cs @@ -1,35 +1,35 @@ -using HealthChecks.AzureServiceBus.Configuration; -using Microsoft.Extensions.Diagnostics.HealthChecks; - -namespace HealthChecks.AzureServiceBus; - -public class AzureServiceBusTopicHealthCheck : AzureServiceBusHealthCheck, IHealthCheck -{ - public AzureServiceBusTopicHealthCheck(AzureServiceBusTopicHealthCheckOptions options, ServiceBusClientProvider clientProvider) - : base(options, clientProvider) - { - Guard.ThrowIfNull(options.TopicName, true); - } - - public AzureServiceBusTopicHealthCheck(AzureServiceBusTopicHealthCheckOptions options) - : this(options, new ServiceBusClientProvider()) - { } - - /// - public async Task CheckHealthAsync(HealthCheckContext context, - CancellationToken cancellationToken = default) - { - try - { - var managementClient = ClientCache.GetOrAdd(ConnectionKey, _ => CreateManagementClient()); - - _ = await managementClient.GetTopicRuntimePropertiesAsync(Options.TopicName, cancellationToken).ConfigureAwait(false); - - return HealthCheckResult.Healthy(); - } - catch (Exception ex) - { - return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); - } - } -} +using HealthChecks.AzureServiceBus.Configuration; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace HealthChecks.AzureServiceBus; + +public class AzureServiceBusTopicHealthCheck : AzureServiceBusHealthCheck, IHealthCheck +{ + public AzureServiceBusTopicHealthCheck(AzureServiceBusTopicHealthCheckOptions options, ServiceBusClientProvider clientProvider) + : base(options, clientProvider) + { + Guard.ThrowIfNull(options.TopicName, true); + } + + public AzureServiceBusTopicHealthCheck(AzureServiceBusTopicHealthCheckOptions options) + : this(options, new ServiceBusClientProvider()) + { } + + /// + public async Task CheckHealthAsync(HealthCheckContext context, + CancellationToken cancellationToken = default) + { + try + { + var managementClient = ClientCache.GetOrAdd(ConnectionKey, _ => CreateManagementClient()); + + _ = await managementClient.GetTopicRuntimePropertiesAsync(Options.TopicName, cancellationToken).ConfigureAwait(false); + + return HealthCheckResult.Healthy(); + } + catch (Exception ex) + { + return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); + } + } +} diff --git a/src/ClientCache.cs b/src/HealthChecks.AzureServiceBus/ClientCache.cs similarity index 100% rename from src/ClientCache.cs rename to src/HealthChecks.AzureServiceBus/ClientCache.cs diff --git a/src/HealthChecks.AzureServiceBus/Configuration/AzureEventHubHealthCheckOptions.cs b/src/HealthChecks.AzureServiceBus/Configuration/AzureEventHubHealthCheckOptions.cs deleted file mode 100644 index e99f28d002..0000000000 --- a/src/HealthChecks.AzureServiceBus/Configuration/AzureEventHubHealthCheckOptions.cs +++ /dev/null @@ -1,41 +0,0 @@ -using Azure.Core; -using Azure.Messaging.EventHubs; - -namespace HealthChecks.AzureServiceBus.Configuration; - -/// -/// Configuration options for . -/// -public class AzureEventHubHealthCheckOptions -{ - /// - /// The azure event hub connection string. - /// - public string? ConnectionString { get; set; } - - /// - /// The azure event hub name. - /// - public string? EventHubName { get; set; } - - /// - /// The azure event hub fully qualified namespace. - /// - /// - /// Must be used in conjunction with the property. - /// - public string? FullyQualifiedNamespace { get; set; } - - /// - /// The token credential for authentication. - /// - /// - /// Must be used in conjunction with the property. - /// - public TokenCredential? Credential { get; set; } - - /// - /// The event hub connection to use for authenticating and connecting. - /// - public EventHubConnection? Connection { get; set; } -} diff --git a/src/HealthChecks.AzureServiceBus/Configuration/AzureServiceBusQueueMessagesCountThreshold.cs b/src/HealthChecks.AzureServiceBus/Configuration/AzureServiceBusQueueMessagesCountThreshold.cs index 7943bfbf11..1130385f1e 100644 --- a/src/HealthChecks.AzureServiceBus/Configuration/AzureServiceBusQueueMessagesCountThreshold.cs +++ b/src/HealthChecks.AzureServiceBus/Configuration/AzureServiceBusQueueMessagesCountThreshold.cs @@ -1,23 +1,23 @@ -using Microsoft.Extensions.Diagnostics.HealthChecks; - -namespace HealthChecks.AzureServiceBus.Configuration; - -/// -/// Threshold configuration options for . -/// -public struct AzureServiceBusQueueMessagesCountThreshold -{ - /// - /// Number of active/dead letter Service Bus messages in the queue before message health check returned . - /// - public int DegradedThreshold { get; set; } = 5; - - /// - /// Number of active/dead letter Service Bus messages in the queue before message health check returned . - /// - public int UnhealthyThreshold { get; set; } = 10; - +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace HealthChecks.AzureServiceBus.Configuration; + +/// +/// Threshold configuration options for . +/// +public struct AzureServiceBusQueueMessagesCountThreshold +{ + /// + /// Number of active/dead letter Service Bus messages in the queue before message health check returned . + /// + public int DegradedThreshold { get; set; } = 5; + + /// + /// Number of active/dead letter Service Bus messages in the queue before message health check returned . + /// + public int UnhealthyThreshold { get; set; } = 10; + public AzureServiceBusQueueMessagesCountThreshold() { - } -} + } +} diff --git a/src/HealthChecks.AzureServiceBus/Configuration/AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions.cs b/src/HealthChecks.AzureServiceBus/Configuration/AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions.cs index f31432f2cb..1b0adeba91 100644 --- a/src/HealthChecks.AzureServiceBus/Configuration/AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions.cs +++ b/src/HealthChecks.AzureServiceBus/Configuration/AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions.cs @@ -1,22 +1,22 @@ -namespace HealthChecks.AzureServiceBus.Configuration; - -/// -/// Configuration options for . -/// -public class AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions : AzureServiceBusQueueHealthCheckOptions -{ - /// - /// Threshold configuration for active messages queue. - /// - public AzureServiceBusQueueMessagesCountThreshold? ActiveMessages { get; set; } - - /// - /// Threshold configuration for dead letter messages queue. - /// - public AzureServiceBusQueueMessagesCountThreshold? DeadLetterMessages { get; set; } - - public AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions(string queueName) - : base(queueName) - { - } -} +namespace HealthChecks.AzureServiceBus.Configuration; + +/// +/// Configuration options for . +/// +public class AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions : AzureServiceBusQueueHealthCheckOptions +{ + /// + /// Threshold configuration for active messages queue. + /// + public AzureServiceBusQueueMessagesCountThreshold? ActiveMessages { get; set; } + + /// + /// Threshold configuration for dead letter messages queue. + /// + public AzureServiceBusQueueMessagesCountThreshold? DeadLetterMessages { get; set; } + + public AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions(string queueName) + : base(queueName) + { + } +} diff --git a/src/HealthChecks.AzureServiceBus/DependencyInjection/AzureServiceBusHealthCheckBuilderExtensions.cs b/src/HealthChecks.AzureServiceBus/DependencyInjection/AzureServiceBusHealthCheckBuilderExtensions.cs index 6a05ce25bc..3654757160 100644 --- a/src/HealthChecks.AzureServiceBus/DependencyInjection/AzureServiceBusHealthCheckBuilderExtensions.cs +++ b/src/HealthChecks.AzureServiceBus/DependencyInjection/AzureServiceBusHealthCheckBuilderExtensions.cs @@ -1,814 +1,609 @@ -using Azure.Core; -using Azure.Messaging.EventHubs; -using HealthChecks.AzureServiceBus; -using HealthChecks.AzureServiceBus.Configuration; -using Microsoft.Extensions.Diagnostics.HealthChecks; - -namespace Microsoft.Extensions.DependencyInjection; - -/// -/// Extension methods to configure , -/// , , -/// , , -/// . -/// -public static class AzureServiceBusHealthCheckBuilderExtensions -{ - private const string AZUREEVENTHUB_NAME = "azureeventhub"; - private const string AZUREQUEUE_NAME = "azurequeue"; - private const string AZURETOPIC_NAME = "azuretopic"; - private const string AZURESUBSCRIPTION_NAME = "azuresubscription"; - private const string AZUREQUEUETHRESHOLD_NAME = "azurequeuethreshold"; - - /// - /// Add a health check for specified Azure Event Hub. - /// - /// The . - /// The azure event hub connection string. - /// The azure event hub name. - /// An optional action to allow additional Azure Event Hub configuration. - /// The health check name. Optional. If null the type name 'azureeventhub' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureEventHub( - this IHealthChecksBuilder builder, - string connectionString, - string eventHubName, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) => - builder.AddAzureEventHub( - _ => connectionString, - _ => eventHubName, - configure, - name, - failureStatus, - tags, - timeout); - - /// - /// Add a health check for specified Azure Event Hub. - /// - /// The . - /// A factory to build the azure event hub connection string. - /// A factory to build the azure event hub name. - /// An optional action to allow additional Azure Event Hub configuration. - /// The health check name. Optional. If null the type name 'azureeventhub' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureEventHub( - this IHealthChecksBuilder builder, - Func connectionStringFactory, - Func eventHubNameFactory, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - Guard.ThrowIfNull(connectionStringFactory); - Guard.ThrowIfNull(eventHubNameFactory); - - return builder.Add(new HealthCheckRegistration( - name ?? AZUREEVENTHUB_NAME, - sp => - { - var options = new AzureEventHubHealthCheckOptions - { - ConnectionString = connectionStringFactory(sp), - EventHubName = eventHubNameFactory(sp) - }; - - configure?.Invoke(options); - return new AzureEventHubHealthCheck(options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for specified Azure Event Hub. - /// - /// The . - /// The azure event hub fully qualified namespace. - /// The azure event hub name. - /// The token credential for authentication. - /// An optional action to allow additional Azure Event Hub configuration. - /// The health check name. Optional. If null the type name 'azureeventhub' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureEventHub( - this IHealthChecksBuilder builder, - string fullyQualifiedNamespace, - string eventHubName, - TokenCredential tokenCredential, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) => - builder.AddAzureEventHub( - _ => fullyQualifiedNamespace, - _ => eventHubName, - _ => tokenCredential, - configure, - name, - failureStatus, - tags, - timeout); - - /// - /// Add a health check for specified Azure Event Hub. - /// - /// The . - /// A factory to build the azure event hub fully qualified namespace. - /// A factory to build the azure event hub name. - /// A factory to build the token credential for authentication. - /// An optional action to allow additional Azure Event Hub configuration. - /// The health check name. Optional. If null the type name 'azureeventhub' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureEventHub( - this IHealthChecksBuilder builder, - Func fullyQualifiedNamespaceFactory, - Func eventHubNameFactory, - Func tokenCredentialFactory, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - Guard.ThrowIfNull(fullyQualifiedNamespaceFactory); - Guard.ThrowIfNull(eventHubNameFactory); - Guard.ThrowIfNull(tokenCredentialFactory); - - return builder.Add(new HealthCheckRegistration( - name ?? AZUREEVENTHUB_NAME, - sp => - { - var options = new AzureEventHubHealthCheckOptions - { - FullyQualifiedNamespace = fullyQualifiedNamespaceFactory(sp), - EventHubName = eventHubNameFactory(sp), - Credential = tokenCredentialFactory(sp) - }; - - configure?.Invoke(options); - return new AzureEventHubHealthCheck(options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for specified Azure Event Hub. - /// - /// The . - /// The event hub connection factory used to create a event hub connection for this health check. - /// An optional action to allow additional Azure Event Hub configuration. - /// The health check name. Optional. If null the type name 'azureeventhub' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureEventHub( - this IHealthChecksBuilder builder, - Func eventHubConnectionFactory, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - Guard.ThrowIfNull(eventHubConnectionFactory); - - return builder.Add(new HealthCheckRegistration( - name ?? AZUREEVENTHUB_NAME, - sp => - { - var options = new AzureEventHubHealthCheckOptions { Connection = eventHubConnectionFactory(sp) }; - configure?.Invoke(options); - return new AzureEventHubHealthCheck(options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for specified Azure Service Bus Queue. - /// - /// The . - /// The azure service bus connection string to be used. - /// The name of the queue to check. - /// An optional action to allow additional Azure Service Bus configuration. - /// The health check name. Optional. If null the type name 'azurequeue' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureServiceBusQueue( - this IHealthChecksBuilder builder, - string connectionString, - string queueName, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) => - builder.AddAzureServiceBusQueue( - _ => connectionString, - _ => queueName, - configure, - name, - failureStatus, - tags, - timeout); - - /// - /// Add a health check for specified Azure Service Bus Queue. - /// - /// The . - /// A factory to build the azure service bus connection string to be used. - /// A factory to build the queue name to check. - /// An optional action to allow additional Azure Service Bus configuration. - /// The health check name. Optional. If null the type name 'azurequeue' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureServiceBusQueue( - this IHealthChecksBuilder builder, - Func connectionStringFactory, - Func queueNameFactory, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - Guard.ThrowIfNull(connectionStringFactory); - Guard.ThrowIfNull(queueNameFactory); - - return builder.Add(new HealthCheckRegistration( - name ?? AZUREQUEUE_NAME, - sp => - { - var options = new AzureServiceBusQueueHealthCheckOptions(queueNameFactory(sp)) - { - ConnectionString = connectionStringFactory(sp) - }; - - configure?.Invoke(options); - return new AzureServiceBusQueueHealthCheck(options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for specified Azure Service Bus Queue. - /// - /// The . - /// The azure service bus fully qualified namespace to be used, format sb://myservicebus.servicebus.windows.net/. - /// The name of the queue to check. - /// The token credential for authentication. - /// An optional action to allow additional Azure Service Bus configuration. - /// The health check name. Optional. If null the type name 'azurequeue' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureServiceBusQueue( - this IHealthChecksBuilder builder, - string fullyQualifiedNamespace, - string queueName, - TokenCredential tokenCredential, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) => - builder.AddAzureServiceBusQueue( - _ => fullyQualifiedNamespace, - _ => queueName, - _ => tokenCredential, - configure, - name, - failureStatus, - tags, - timeout); - - /// - /// Add a health check for specified Azure Service Bus Queue. - /// - /// The . - /// A factory to build the azure service bus fully qualified namespace to be used, format sb://myservicebus.servicebus.windows.net/. - /// A factory to build the name of the queue to check. - /// A factory to build the token credential for authentication. - /// An optional action to allow additional Azure Service Bus configuration. - /// The health check name. Optional. If null the type name 'azurequeue' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureServiceBusQueue( - this IHealthChecksBuilder builder, - Func fullyQualifiedNamespaceFactory, - Func queueNameFactory, - Func tokenCredentialFactory, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - Guard.ThrowIfNull(fullyQualifiedNamespaceFactory); - Guard.ThrowIfNull(queueNameFactory); - Guard.ThrowIfNull(tokenCredentialFactory); - - return builder.Add(new HealthCheckRegistration( - name ?? AZUREQUEUE_NAME, - sp => - { - var options = new AzureServiceBusQueueHealthCheckOptions(queueNameFactory(sp)) - { - FullyQualifiedNamespace = fullyQualifiedNamespaceFactory(sp), - Credential = tokenCredentialFactory(sp) - }; - - configure?.Invoke(options); - return new AzureServiceBusQueueHealthCheck(options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for specified Azure Service Bus Queue active or dead letter messages threshold. - /// - /// The . - /// The azure service bus connection string to be used. - /// The name of the queue to check. - /// The health check name. Optional. If null the type name 'azurequeuethreshold' will be used for the name. - /// An optional action to allow additional Azure Service Bus configuration. - /// - /// 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. - /// The . - public static IHealthChecksBuilder AddAzureServiceBusQueueMessageCountThreshold( - this IHealthChecksBuilder builder, - string connectionString, - string queueName, - string? name = default, - Action? configure = null, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - Guard.ThrowIfNull(connectionString); - Guard.ThrowIfNull(queueName); - - var options = new AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions(queueName) - { - ConnectionString = connectionString, - }; - - configure?.Invoke(options); - - return builder.Add(new HealthCheckRegistration( - name ?? AZUREQUEUETHRESHOLD_NAME, - sp => new AzureServiceBusQueueMessageCountThresholdHealthCheck(options), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for specified Azure Service Bus Queue active or dead letter messages threshold. - /// - /// The . - /// The azure service bus endpoint to be used, format sb://myservicebus.servicebus.windows.net/. - /// The name of the queue to check. - /// The token credential for authentication. - /// An optional action to allow additional Azure Service Bus configuration. - /// The health check name. Optional. If null the type name 'azurequeuethreshold' 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. - /// The . - public static IHealthChecksBuilder AddAzureServiceBusQueueMessageCountThreshold( - this IHealthChecksBuilder builder, - string endpoint, - string queueName, - TokenCredential tokenCredential, - Action? configure = null, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - Guard.ThrowIfNull(endpoint); - Guard.ThrowIfNull(queueName); - Guard.ThrowIfNull(tokenCredential); - - var options = new AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions(queueName) - { - FullyQualifiedNamespace = endpoint, - Credential = tokenCredential, - }; - - configure?.Invoke(options); - - return builder.Add(new HealthCheckRegistration( - name ?? AZUREQUEUETHRESHOLD_NAME, - sp => new AzureServiceBusQueueMessageCountThresholdHealthCheck(options), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Service Bus Topic. - /// - /// The . - /// The Azure ServiceBus connection string to be used. - /// The name of the topic to check. - /// An optional action to allow additional Azure Service Bus configuration. - /// The health check name. Optional. If null the type name 'azuretopic' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureServiceBusTopic( - this IHealthChecksBuilder builder, - string connectionString, - string topicName, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) => - builder.AddAzureServiceBusTopic( - _ => connectionString, - _ => topicName, - configure, - name, - failureStatus, - tags, - timeout); - - /// - /// Add a health check for Azure Service Bus Topic. - /// - /// The . - /// A factory to build the Azure ServiceBus connection string to be used. - /// A factory to build the name of the topic to check. - /// An optional action to allow additional Azure Service Bus configuration. - /// The health check name. Optional. If null the type name 'azuretopic' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureServiceBusTopic( - this IHealthChecksBuilder builder, - Func connectionStringFactory, - Func topicNameFactory, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - Guard.ThrowIfNull(connectionStringFactory); - Guard.ThrowIfNull(topicNameFactory); - - return builder.Add(new HealthCheckRegistration( - name ?? AZURETOPIC_NAME, - sp => - { - var options = new AzureServiceBusTopicHealthCheckOptions(topicNameFactory(sp)) - { - ConnectionString = connectionStringFactory(sp) - }; - - configure?.Invoke(options); - return new AzureServiceBusTopicHealthCheck(options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Service Bus Topic. - /// - /// The . - /// The azure service bus fully qualified namespace to be used, format sb://myservicebus.servicebus.windows.net/. - /// The name of the topic to check. - /// The token credential for authentication. - /// The health check name. Optional. If null the type name 'azuretopic' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureServiceBusTopic( - this IHealthChecksBuilder builder, - string fullyQualifiedNamespace, - string topicName, - TokenCredential tokenCredential, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) => - builder.AddAzureServiceBusTopic( - _ => fullyQualifiedNamespace, - _ => topicName, - _ => tokenCredential, - configure: null, - name, - failureStatus, - tags, - timeout); - - /// - /// Add a health check for Azure Service Bus Topic. - /// - /// The . - /// A factory to build the azure service bus fully qualified namespace to be used, format sb://myservicebus.servicebus.windows.net/. - /// A factory to build the name of the topic to check. - /// A factory to build the token credential for authentication. - /// An optional action to allow additional Azure Service Bus configuration. - /// The health check name. Optional. If null the type name 'azuretopic' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureServiceBusTopic( - this IHealthChecksBuilder builder, - Func fullyQualifiedNamespaceFactory, - Func topicNameFactory, - Func tokenCredentialFactory, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - Guard.ThrowIfNull(fullyQualifiedNamespaceFactory); - Guard.ThrowIfNull(topicNameFactory); - Guard.ThrowIfNull(tokenCredentialFactory); - - return builder.Add(new HealthCheckRegistration( - name ?? AZURETOPIC_NAME, - sp => - { - var options = new AzureServiceBusTopicHealthCheckOptions(topicNameFactory(sp)) - { - FullyQualifiedNamespace = fullyQualifiedNamespaceFactory(sp), - Credential = tokenCredentialFactory(sp) - }; - - configure?.Invoke(options); - return new AzureServiceBusTopicHealthCheck(options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Service Bus Subscription. - /// - /// The . - /// The Azure ServiceBus connection string to be used. - /// The name of the topic to check. - /// The subscription name of the topic subscription to check. - /// An optional action to allow additional Azure Service Bus configuration. - /// The health check name. Optional. If null the type name 'azuretopic' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureServiceBusSubscription( - this IHealthChecksBuilder builder, - string connectionString, - string topicName, - string subscriptionName, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) => - builder.AddAzureServiceBusSubscription( - _ => connectionString, - _ => topicName, - _ => subscriptionName, - configure, - name, - failureStatus, - tags, - timeout); - - /// - /// Add a health check for Azure Service Bus Subscription. - /// - /// The . - /// A factory to build the Azure ServiceBus connection string to be used. - /// A factory to build the name of the topic to check. - /// A factory to build the subscription name of the topic subscription to check. - /// An optional action to allow additional Azure Service Bus configuration. - /// The health check name. Optional. If null the type name 'azuretopic' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureServiceBusSubscription( - this IHealthChecksBuilder builder, - Func connectionStringFactory, - Func topicNameFactory, - Func subscriptionNameFactory, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - Guard.ThrowIfNull(connectionStringFactory); - Guard.ThrowIfNull(topicNameFactory); - Guard.ThrowIfNull(subscriptionNameFactory); - - return builder.Add(new HealthCheckRegistration( - name ?? AZURESUBSCRIPTION_NAME, - sp => - { - var options = new AzureServiceBusSubscriptionHealthCheckHealthCheckOptions(topicNameFactory(sp), subscriptionNameFactory(sp)) - { - ConnectionString = connectionStringFactory(sp) - }; - - configure?.Invoke(options); - return new AzureServiceBusSubscriptionHealthCheck(options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Service Bus Subscription. - /// - /// The . - /// The azure service bus fully qualified namespace to be used, format sb://myservicebus.servicebus.windows.net/. - /// The name of the topic to check. - /// The subscription name of the topic subscription to check. - /// The token credential for authentication. - /// An optional action to allow additional Azure Service Bus configuration. - /// The health check name. Optional. If null the type name 'azuretopic' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureServiceBusSubscription( - this IHealthChecksBuilder builder, - string fullyQualifiedNamespace, - string topicName, - string subscriptionName, - TokenCredential tokenCredential, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) => - builder.AddAzureServiceBusSubscription( - _ => fullyQualifiedNamespace, - _ => topicName, - _ => subscriptionName, - _ => tokenCredential, - configure, - name, - failureStatus, - tags, - timeout); - - /// - /// Add a health check for Azure Service Bus Subscription. - /// - /// The . - /// A factory to build the azure service bus fully qualified namespace to be used, format sb://myservicebus.servicebus.windows.net/. - /// A factory to build the name of the topic to check. - /// A factory to build the subscription name of the topic subscription to check. - /// A factory to build the token credential for authentication. - /// An optional action to allow additional Azure Service Bus configuration. - /// The health check name. Optional. If null the type name 'azuretopic' 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. - /// The specified . - public static IHealthChecksBuilder AddAzureServiceBusSubscription( - this IHealthChecksBuilder builder, - Func fullyQualifiedNamespaceFactory, - Func topicNameFactory, - Func subscriptionNameFactory, - Func tokenCredentialFactory, - Action? configure = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - Guard.ThrowIfNull(fullyQualifiedNamespaceFactory); - Guard.ThrowIfNull(topicNameFactory); - Guard.ThrowIfNull(subscriptionNameFactory); - Guard.ThrowIfNull(tokenCredentialFactory); - - return builder.Add(new HealthCheckRegistration( - name ?? AZURESUBSCRIPTION_NAME, - sp => - { - var options = new AzureServiceBusSubscriptionHealthCheckHealthCheckOptions(topicNameFactory(sp), subscriptionNameFactory(sp)) - { - FullyQualifiedNamespace = fullyQualifiedNamespaceFactory(sp), - Credential = tokenCredentialFactory(sp) - }; - - configure?.Invoke(options); - return new AzureServiceBusSubscriptionHealthCheck(options); - }, - failureStatus, - tags, - timeout)); - } -} +using Azure.Core; +using HealthChecks.AzureServiceBus; +using HealthChecks.AzureServiceBus.Configuration; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace Microsoft.Extensions.DependencyInjection; + +/// +/// Extension methods to configure +/// , , +/// , , +/// . +/// +public static class AzureServiceBusHealthCheckBuilderExtensions +{ + private const string AZUREQUEUE_NAME = "azurequeue"; + private const string AZURETOPIC_NAME = "azuretopic"; + private const string AZURESUBSCRIPTION_NAME = "azuresubscription"; + private const string AZUREQUEUETHRESHOLD_NAME = "azurequeuethreshold"; + + /// + /// Add a health check for specified Azure Service Bus Queue. + /// + /// The . + /// The azure service bus connection string to be used. + /// The name of the queue to check. + /// An optional action to allow additional Azure Service Bus configuration. + /// The health check name. Optional. If null the type name 'azurequeue' 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. + /// The specified . + public static IHealthChecksBuilder AddAzureServiceBusQueue( + this IHealthChecksBuilder builder, + string connectionString, + string queueName, + Action? configure = default, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) => + builder.AddAzureServiceBusQueue( + _ => connectionString, + _ => queueName, + configure, + name, + failureStatus, + tags, + timeout); + + /// + /// Add a health check for specified Azure Service Bus Queue. + /// + /// The . + /// A factory to build the azure service bus connection string to be used. + /// A factory to build the queue name to check. + /// An optional action to allow additional Azure Service Bus configuration. + /// The health check name. Optional. If null the type name 'azurequeue' 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. + /// The specified . + public static IHealthChecksBuilder AddAzureServiceBusQueue( + this IHealthChecksBuilder builder, + Func connectionStringFactory, + Func queueNameFactory, + Action? configure = default, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + Guard.ThrowIfNull(connectionStringFactory); + Guard.ThrowIfNull(queueNameFactory); + + return builder.Add(new HealthCheckRegistration( + name ?? AZUREQUEUE_NAME, + sp => + { + var options = new AzureServiceBusQueueHealthCheckOptions(queueNameFactory(sp)) + { + ConnectionString = connectionStringFactory(sp) + }; + + configure?.Invoke(options); + return new AzureServiceBusQueueHealthCheck(options); + }, + failureStatus, + tags, + timeout)); + } + + /// + /// Add a health check for specified Azure Service Bus Queue. + /// + /// The . + /// The azure service bus fully qualified namespace to be used, format sb://myservicebus.servicebus.windows.net/. + /// The name of the queue to check. + /// The token credential for authentication. + /// An optional action to allow additional Azure Service Bus configuration. + /// The health check name. Optional. If null the type name 'azurequeue' 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. + /// The specified . + public static IHealthChecksBuilder AddAzureServiceBusQueue( + this IHealthChecksBuilder builder, + string fullyQualifiedNamespace, + string queueName, + TokenCredential tokenCredential, + Action? configure = default, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) => + builder.AddAzureServiceBusQueue( + _ => fullyQualifiedNamespace, + _ => queueName, + _ => tokenCredential, + configure, + name, + failureStatus, + tags, + timeout); + + /// + /// Add a health check for specified Azure Service Bus Queue. + /// + /// The . + /// A factory to build the azure service bus fully qualified namespace to be used, format sb://myservicebus.servicebus.windows.net/. + /// A factory to build the name of the queue to check. + /// A factory to build the token credential for authentication. + /// An optional action to allow additional Azure Service Bus configuration. + /// The health check name. Optional. If null the type name 'azurequeue' 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. + /// The specified . + public static IHealthChecksBuilder AddAzureServiceBusQueue( + this IHealthChecksBuilder builder, + Func fullyQualifiedNamespaceFactory, + Func queueNameFactory, + Func tokenCredentialFactory, + Action? configure = default, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + Guard.ThrowIfNull(fullyQualifiedNamespaceFactory); + Guard.ThrowIfNull(queueNameFactory); + Guard.ThrowIfNull(tokenCredentialFactory); + + return builder.Add(new HealthCheckRegistration( + name ?? AZUREQUEUE_NAME, + sp => + { + var options = new AzureServiceBusQueueHealthCheckOptions(queueNameFactory(sp)) + { + FullyQualifiedNamespace = fullyQualifiedNamespaceFactory(sp), + Credential = tokenCredentialFactory(sp) + }; + + configure?.Invoke(options); + return new AzureServiceBusQueueHealthCheck(options); + }, + failureStatus, + tags, + timeout)); + } + + /// + /// Add a health check for specified Azure Service Bus Queue active or dead letter messages threshold. + /// + /// The . + /// The azure service bus connection string to be used. + /// The name of the queue to check. + /// The health check name. Optional. If null the type name 'azurequeuethreshold' will be used for the name. + /// An optional action to allow additional Azure Service Bus configuration. + /// + /// 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. + /// The . + public static IHealthChecksBuilder AddAzureServiceBusQueueMessageCountThreshold( + this IHealthChecksBuilder builder, + string connectionString, + string queueName, + string? name = default, + Action? configure = null, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + Guard.ThrowIfNull(connectionString); + Guard.ThrowIfNull(queueName); + + var options = new AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions(queueName) + { + ConnectionString = connectionString, + }; + + configure?.Invoke(options); + + return builder.Add(new HealthCheckRegistration( + name ?? AZUREQUEUETHRESHOLD_NAME, + sp => new AzureServiceBusQueueMessageCountThresholdHealthCheck(options), + failureStatus, + tags, + timeout)); + } + + /// + /// Add a health check for specified Azure Service Bus Queue active or dead letter messages threshold. + /// + /// The . + /// The azure service bus endpoint to be used, format sb://myservicebus.servicebus.windows.net/. + /// The name of the queue to check. + /// The token credential for authentication. + /// An optional action to allow additional Azure Service Bus configuration. + /// The health check name. Optional. If null the type name 'azurequeuethreshold' 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. + /// The . + public static IHealthChecksBuilder AddAzureServiceBusQueueMessageCountThreshold( + this IHealthChecksBuilder builder, + string endpoint, + string queueName, + TokenCredential tokenCredential, + Action? configure = null, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + Guard.ThrowIfNull(endpoint); + Guard.ThrowIfNull(queueName); + Guard.ThrowIfNull(tokenCredential); + + var options = new AzureServiceBusQueueMessagesCountThresholdHealthCheckOptions(queueName) + { + FullyQualifiedNamespace = endpoint, + Credential = tokenCredential, + }; + + configure?.Invoke(options); + + return builder.Add(new HealthCheckRegistration( + name ?? AZUREQUEUETHRESHOLD_NAME, + sp => new AzureServiceBusQueueMessageCountThresholdHealthCheck(options), + failureStatus, + tags, + timeout)); + } + + /// + /// Add a health check for Azure Service Bus Topic. + /// + /// The . + /// The Azure ServiceBus connection string to be used. + /// The name of the topic to check. + /// An optional action to allow additional Azure Service Bus configuration. + /// The health check name. Optional. If null the type name 'azuretopic' 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. + /// The specified . + public static IHealthChecksBuilder AddAzureServiceBusTopic( + this IHealthChecksBuilder builder, + string connectionString, + string topicName, + Action? configure = default, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) => + builder.AddAzureServiceBusTopic( + _ => connectionString, + _ => topicName, + configure, + name, + failureStatus, + tags, + timeout); + + /// + /// Add a health check for Azure Service Bus Topic. + /// + /// The . + /// A factory to build the Azure ServiceBus connection string to be used. + /// A factory to build the name of the topic to check. + /// An optional action to allow additional Azure Service Bus configuration. + /// The health check name. Optional. If null the type name 'azuretopic' 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. + /// The specified . + public static IHealthChecksBuilder AddAzureServiceBusTopic( + this IHealthChecksBuilder builder, + Func connectionStringFactory, + Func topicNameFactory, + Action? configure = default, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + Guard.ThrowIfNull(connectionStringFactory); + Guard.ThrowIfNull(topicNameFactory); + + return builder.Add(new HealthCheckRegistration( + name ?? AZURETOPIC_NAME, + sp => + { + var options = new AzureServiceBusTopicHealthCheckOptions(topicNameFactory(sp)) + { + ConnectionString = connectionStringFactory(sp) + }; + + configure?.Invoke(options); + return new AzureServiceBusTopicHealthCheck(options); + }, + failureStatus, + tags, + timeout)); + } + + /// + /// Add a health check for Azure Service Bus Topic. + /// + /// The . + /// The azure service bus fully qualified namespace to be used, format sb://myservicebus.servicebus.windows.net/. + /// The name of the topic to check. + /// The token credential for authentication. + /// The health check name. Optional. If null the type name 'azuretopic' 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. + /// The specified . + public static IHealthChecksBuilder AddAzureServiceBusTopic( + this IHealthChecksBuilder builder, + string fullyQualifiedNamespace, + string topicName, + TokenCredential tokenCredential, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) => + builder.AddAzureServiceBusTopic( + _ => fullyQualifiedNamespace, + _ => topicName, + _ => tokenCredential, + configure: null, + name, + failureStatus, + tags, + timeout); + + /// + /// Add a health check for Azure Service Bus Topic. + /// + /// The . + /// A factory to build the azure service bus fully qualified namespace to be used, format sb://myservicebus.servicebus.windows.net/. + /// A factory to build the name of the topic to check. + /// A factory to build the token credential for authentication. + /// An optional action to allow additional Azure Service Bus configuration. + /// The health check name. Optional. If null the type name 'azuretopic' 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. + /// The specified . + public static IHealthChecksBuilder AddAzureServiceBusTopic( + this IHealthChecksBuilder builder, + Func fullyQualifiedNamespaceFactory, + Func topicNameFactory, + Func tokenCredentialFactory, + Action? configure = default, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + Guard.ThrowIfNull(fullyQualifiedNamespaceFactory); + Guard.ThrowIfNull(topicNameFactory); + Guard.ThrowIfNull(tokenCredentialFactory); + + return builder.Add(new HealthCheckRegistration( + name ?? AZURETOPIC_NAME, + sp => + { + var options = new AzureServiceBusTopicHealthCheckOptions(topicNameFactory(sp)) + { + FullyQualifiedNamespace = fullyQualifiedNamespaceFactory(sp), + Credential = tokenCredentialFactory(sp) + }; + + configure?.Invoke(options); + return new AzureServiceBusTopicHealthCheck(options); + }, + failureStatus, + tags, + timeout)); + } + + /// + /// Add a health check for Azure Service Bus Subscription. + /// + /// The . + /// The Azure ServiceBus connection string to be used. + /// The name of the topic to check. + /// The subscription name of the topic subscription to check. + /// An optional action to allow additional Azure Service Bus configuration. + /// The health check name. Optional. If null the type name 'azuretopic' 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. + /// The specified . + public static IHealthChecksBuilder AddAzureServiceBusSubscription( + this IHealthChecksBuilder builder, + string connectionString, + string topicName, + string subscriptionName, + Action? configure = default, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) => + builder.AddAzureServiceBusSubscription( + _ => connectionString, + _ => topicName, + _ => subscriptionName, + configure, + name, + failureStatus, + tags, + timeout); + + /// + /// Add a health check for Azure Service Bus Subscription. + /// + /// The . + /// A factory to build the Azure ServiceBus connection string to be used. + /// A factory to build the name of the topic to check. + /// A factory to build the subscription name of the topic subscription to check. + /// An optional action to allow additional Azure Service Bus configuration. + /// The health check name. Optional. If null the type name 'azuretopic' 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. + /// The specified . + public static IHealthChecksBuilder AddAzureServiceBusSubscription( + this IHealthChecksBuilder builder, + Func connectionStringFactory, + Func topicNameFactory, + Func subscriptionNameFactory, + Action? configure = default, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + Guard.ThrowIfNull(connectionStringFactory); + Guard.ThrowIfNull(topicNameFactory); + Guard.ThrowIfNull(subscriptionNameFactory); + + return builder.Add(new HealthCheckRegistration( + name ?? AZURESUBSCRIPTION_NAME, + sp => + { + var options = new AzureServiceBusSubscriptionHealthCheckHealthCheckOptions(topicNameFactory(sp), subscriptionNameFactory(sp)) + { + ConnectionString = connectionStringFactory(sp) + }; + + configure?.Invoke(options); + return new AzureServiceBusSubscriptionHealthCheck(options); + }, + failureStatus, + tags, + timeout)); + } + + /// + /// Add a health check for Azure Service Bus Subscription. + /// + /// The . + /// The azure service bus fully qualified namespace to be used, format sb://myservicebus.servicebus.windows.net/. + /// The name of the topic to check. + /// The subscription name of the topic subscription to check. + /// The token credential for authentication. + /// An optional action to allow additional Azure Service Bus configuration. + /// The health check name. Optional. If null the type name 'azuretopic' 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. + /// The specified . + public static IHealthChecksBuilder AddAzureServiceBusSubscription( + this IHealthChecksBuilder builder, + string fullyQualifiedNamespace, + string topicName, + string subscriptionName, + TokenCredential tokenCredential, + Action? configure = default, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) => + builder.AddAzureServiceBusSubscription( + _ => fullyQualifiedNamespace, + _ => topicName, + _ => subscriptionName, + _ => tokenCredential, + configure, + name, + failureStatus, + tags, + timeout); + + /// + /// Add a health check for Azure Service Bus Subscription. + /// + /// The . + /// A factory to build the azure service bus fully qualified namespace to be used, format sb://myservicebus.servicebus.windows.net/. + /// A factory to build the name of the topic to check. + /// A factory to build the subscription name of the topic subscription to check. + /// A factory to build the token credential for authentication. + /// An optional action to allow additional Azure Service Bus configuration. + /// The health check name. Optional. If null the type name 'azuretopic' 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. + /// The specified . + public static IHealthChecksBuilder AddAzureServiceBusSubscription( + this IHealthChecksBuilder builder, + Func fullyQualifiedNamespaceFactory, + Func topicNameFactory, + Func subscriptionNameFactory, + Func tokenCredentialFactory, + Action? configure = default, + string? name = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default) + { + Guard.ThrowIfNull(fullyQualifiedNamespaceFactory); + Guard.ThrowIfNull(topicNameFactory); + Guard.ThrowIfNull(subscriptionNameFactory); + Guard.ThrowIfNull(tokenCredentialFactory); + + return builder.Add(new HealthCheckRegistration( + name ?? AZURESUBSCRIPTION_NAME, + sp => + { + var options = new AzureServiceBusSubscriptionHealthCheckHealthCheckOptions(topicNameFactory(sp), subscriptionNameFactory(sp)) + { + FullyQualifiedNamespace = fullyQualifiedNamespaceFactory(sp), + Credential = tokenCredentialFactory(sp) + }; + + configure?.Invoke(options); + return new AzureServiceBusSubscriptionHealthCheck(options); + }, + failureStatus, + tags, + timeout)); + } +} diff --git a/src/HealthChecks.AzureServiceBus/HealthChecks.AzureServiceBus.csproj b/src/HealthChecks.AzureServiceBus/HealthChecks.AzureServiceBus.csproj index 9b5b059eb0..91be97a155 100644 --- a/src/HealthChecks.AzureServiceBus/HealthChecks.AzureServiceBus.csproj +++ b/src/HealthChecks.AzureServiceBus/HealthChecks.AzureServiceBus.csproj @@ -3,12 +3,11 @@ netstandard2.0 $(PackageTags);Azure;ServiceBus;EventHub - HealthChecks.AzureServiceBus is the health check package for Azure EventHub, and Azure Service Bus Queues and Topics. + HealthChecks.AzureServiceBus is the health check package for Azure Service Bus Queues and Topics. $(HealthCheckAzureServiceBus) - diff --git a/src/HealthChecks.AzureStorage/DependencyInjection/AzureStorageHealthCheckBuilderExtensions.cs b/src/HealthChecks.AzureStorage/DependencyInjection/AzureStorageHealthCheckBuilderExtensions.cs deleted file mode 100644 index 93965c5110..0000000000 --- a/src/HealthChecks.AzureStorage/DependencyInjection/AzureStorageHealthCheckBuilderExtensions.cs +++ /dev/null @@ -1,477 +0,0 @@ -using Azure.Core; -using Azure.Storage.Blobs; -using Azure.Storage.Files.Shares; -using Azure.Storage.Queues; -using HealthChecks.AzureStorage; -using Microsoft.Extensions.Diagnostics.HealthChecks; - -namespace Microsoft.Extensions.DependencyInjection; - -/// -/// Extension methods to configure , -/// , . -/// -public static class AzureStorageHealthCheckBuilderExtensions -{ - private const string AZUREBLOB_NAME = "azureblob"; - private const string AZUREFILESHARE_NAME = "azurefileshare"; - private const string AZUREQUEUE_NAME = "azurequeue"; - - /// - /// Add a health check for Azure Blob Storage. - /// - /// The . - /// The Azure Storage connection string to be used. - /// The Azure Storage container name to check if exist. Optional, If then container name check is not executed. - /// Provide the client configuration options to connect with Azure Storage. - /// The health check name. Optional. If the type name 'azureblob' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureBlobStorage( - this IHealthChecksBuilder builder, - string connectionString, - string? containerName = default, - BlobClientOptions? clientOptions = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? AZUREBLOB_NAME, - sp => new AzureBlobStorageHealthCheck(connectionString, containerName, clientOptions), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Blob Storage. - /// - /// The . - /// The Azure Storage Blob service Uri like . - /// The TokenCredentail to use, you can use Azure.Identity with DefaultAzureCredential or other kind of TokenCredential,you can read more on . - /// The Azure Storage container name to check if exist. Optional, If then container name check is not executed. - /// Provide the client configuration options to connect with Azure Storage. - /// The health check name. Optional. If the type name 'azureblob' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureBlobStorage( - this IHealthChecksBuilder builder, - Uri blobServiceUri, - TokenCredential credential, - string? containerName = default, - BlobClientOptions? clientOptions = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? AZUREBLOB_NAME, - sp => new AzureBlobStorageHealthCheck(blobServiceUri, credential, containerName, clientOptions), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Blob Storage. - /// - /// - /// A service must be registered in the service container. - /// - /// The . - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'azureblob' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureBlobStorage( - this IHealthChecksBuilder builder, - Action? configureOptions = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? AZUREBLOB_NAME, - sp => - { - var options = new AzureBlobStorageHealthCheckOptions(); - configureOptions?.Invoke(options); - return new AzureBlobStorageHealthCheck(sp.GetRequiredService(), options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Blob Storage. - /// - /// The . - /// Delegate for creating a . - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'azureblob' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureBlobStorage( - this IHealthChecksBuilder builder, - Func clientFactory, - Action? configureOptions = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? AZUREBLOB_NAME, - sp => - { - var options = new AzureBlobStorageHealthCheckOptions(); - configureOptions?.Invoke(options); - return new AzureBlobStorageHealthCheck(clientFactory(sp), options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Blob Storage. - /// - /// - /// A service must be registered in the service container. For named instances - /// you may use other overload with argument. - /// - /// The . - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'azureblob' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureBlobStorage( - this IHealthChecksBuilder builder, - Action? configureOptions = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? AZUREBLOB_NAME, - sp => - { - var options = new AzureBlobStorageHealthCheckOptions(); - configureOptions?.Invoke(sp, options); - return new AzureBlobStorageHealthCheck(sp.GetRequiredService(), options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Blob Storage. - /// - /// The . - /// Delegate for creating a . - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'azureblob' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureBlobStorage( - this IHealthChecksBuilder builder, - Func clientFactory, - Action? configureOptions = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? AZUREBLOB_NAME, - sp => - { - var options = new AzureBlobStorageHealthCheckOptions(); - configureOptions?.Invoke(sp, options); - return new AzureBlobStorageHealthCheck(clientFactory(sp), options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for an Azure file share. - /// - /// The . - /// The Azure Storage connection string to be used. - /// The name of the Azure file share to check if exist. - /// The health check name. Optional. If the type name 'azurefileshare' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureFileShare( - this IHealthChecksBuilder builder, - string connectionString, - string? shareName = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? AZUREFILESHARE_NAME, - sp => new AzureFileShareHealthCheck(connectionString, shareName), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for an Azure file share. - /// - /// - /// A service must be registered in the service container. - /// - /// The . - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'azurefileshare' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureFileShare( - this IHealthChecksBuilder builder, - Action? configureOptions = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? AZUREFILESHARE_NAME, - sp => - { - var options = new AzureFileShareHealthCheckOptions(); - configureOptions?.Invoke(options); - return new AzureFileShareHealthCheck(sp.GetRequiredService(), options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for an Azure file share. - /// - /// - /// A service must be registered in the service container. - /// - /// The . - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'azurefileshare' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureFileShare( - this IHealthChecksBuilder builder, - Action? configureOptions = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? AZUREFILESHARE_NAME, - sp => - { - var options = new AzureFileShareHealthCheckOptions(); - configureOptions?.Invoke(sp, options); - return new AzureFileShareHealthCheck(sp.GetRequiredService(), options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Queue Storage. - /// - /// The . - /// The Azure Storage connection string to be used. - /// The Azure Storage queue name to check if exist. Optional.If then queue name check is not executed. - /// The health check name. Optional. If the type name 'azurequeue' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureQueueStorage( - this IHealthChecksBuilder builder, - string connectionString, - string? queueName = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? AZUREQUEUE_NAME, - sp => new AzureQueueStorageHealthCheck(connectionString, queueName), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Queue Storage. - /// - /// The . - /// The Azure Queue service Uri like . - /// The TokenCredentail to use, you can use Azure.Identity with DefaultAzureCredential or other kind of TokenCredential,you can read more on . - /// The Azure Storage queue name to check if exist. Optional.If then queue name check is not executed. - /// The health check name. Optional. If the type name 'azurequeue' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureQueueStorage( - this IHealthChecksBuilder builder, - Uri queueServiceUri, - TokenCredential credential, - string? queueName = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? AZUREQUEUE_NAME, - sp => new AzureQueueStorageHealthCheck(queueServiceUri, credential, queueName), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Queue Storage. - /// - /// - /// A service must be registered in the service container. - /// - /// The . - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'azurequeue' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureQueueStorage( - this IHealthChecksBuilder builder, - Action? configureOptions = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? AZUREQUEUE_NAME, - sp => - { - var options = new AzureQueueStorageHealthCheckOptions(); - configureOptions?.Invoke(options); - return new AzureQueueStorageHealthCheck(sp.GetRequiredService(), options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Queue Storage. - /// - /// - /// A service must be registered in the service container. - /// - /// The . - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'azurequeue' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureQueueStorage( - this IHealthChecksBuilder builder, - Action? configureOptions = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? AZUREQUEUE_NAME, - sp => - { - var options = new AzureQueueStorageHealthCheckOptions(); - configureOptions?.Invoke(sp, options); - return new AzureQueueStorageHealthCheck(sp.GetRequiredService(), options); - }, - failureStatus, - tags, - timeout)); - } -} diff --git a/src/HealthChecks.CosmosDb/AzureCosmosDbHealthCheck.cs b/src/HealthChecks.CosmosDb/AzureCosmosDbHealthCheck.cs new file mode 100644 index 0000000000..ec39c0eb25 --- /dev/null +++ b/src/HealthChecks.CosmosDb/AzureCosmosDbHealthCheck.cs @@ -0,0 +1,60 @@ +using Microsoft.Azure.Cosmos; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace HealthChecks.CosmosDb; + +/// +/// Azure Cosmos DB health check. +/// +public sealed class AzureCosmosDbHealthCheck : IHealthCheck +{ + private readonly CosmosClient _cosmosClient; + private readonly AzureCosmosDbHealthCheckOptions _options; + + /// + /// Creates new instance of Azure Cosmos DB health check. + /// + /// + /// The used to perform Azure Cosmos DB operations. + /// Azure SDK recommends treating clients as singletons , + /// so this should be the exact same instance used by other parts of the application. + /// + /// Optional settings used by the health check. + public AzureCosmosDbHealthCheck(CosmosClient cosmosClient, AzureCosmosDbHealthCheckOptions? options) + { + _cosmosClient = Guard.ThrowIfNull(cosmosClient); + _options = options ?? new(); + } + + /// + public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) + { + try + { + await _cosmosClient.ReadAccountAsync().ConfigureAwait(false); + + if (_options.DatabaseId != null) + { + var database = _cosmosClient.GetDatabase(_options.DatabaseId); + await database.ReadAsync(cancellationToken: cancellationToken).ConfigureAwait(false); + + if (_options.ContainerIds != null) + { + foreach (var container in _options.ContainerIds) + { + await database + .GetContainer(container) + .ReadContainerAsync(cancellationToken: cancellationToken) + .ConfigureAwait(false); + } + } + } + + return HealthCheckResult.Healthy(); + } + catch (Exception ex) + { + return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); + } + } +} diff --git a/src/HealthChecks.CosmosDb/CosmosDbHealthCheckOptions.cs b/src/HealthChecks.CosmosDb/AzureCosmosDbHealthCheckOptions.cs similarity index 90% rename from src/HealthChecks.CosmosDb/CosmosDbHealthCheckOptions.cs rename to src/HealthChecks.CosmosDb/AzureCosmosDbHealthCheckOptions.cs index 6ef5547856..4ee77129f7 100644 --- a/src/HealthChecks.CosmosDb/CosmosDbHealthCheckOptions.cs +++ b/src/HealthChecks.CosmosDb/AzureCosmosDbHealthCheckOptions.cs @@ -2,9 +2,9 @@ namespace HealthChecks.CosmosDb; /// /// Represents a collection of settings that configure an -/// Azure Cosmos DB health check. +/// Azure Cosmos DB health check. /// -public sealed class CosmosDbHealthCheckOptions +public sealed class AzureCosmosDbHealthCheckOptions { // TODO: Consider implementing IValidatableObject to ensure ContainerIds are not specified // when DatabaseId is missing. Furthermore, it may be advantageous to use IReadOnlyCollection diff --git a/src/HealthChecks.CosmosDb/CosmosDbHealthCheck.cs b/src/HealthChecks.CosmosDb/CosmosDbHealthCheck.cs deleted file mode 100644 index 02511502b2..0000000000 --- a/src/HealthChecks.CosmosDb/CosmosDbHealthCheck.cs +++ /dev/null @@ -1,77 +0,0 @@ -using Azure.Core; -using Microsoft.Azure.Cosmos; -using Microsoft.Extensions.Diagnostics.HealthChecks; - -namespace HealthChecks.CosmosDb; - -public class CosmosDbHealthCheck : IHealthCheck -{ - private readonly CosmosClient _cosmosClient; - private readonly CosmosDbHealthCheckOptions _options; - - public CosmosDbHealthCheck(string connectionString) - : this(connectionString: connectionString, default, default) - { } - - public CosmosDbHealthCheck(string connectionString, string database) - : this(connectionString, database, default) - { } - - public CosmosDbHealthCheck(string accountEndpoint, TokenCredential tokenCredential, string database) - : this(accountEndpoint, tokenCredential, database, default) - { } - - public CosmosDbHealthCheck(string connectionString, string? database, IEnumerable? containers) - : this( - ClientCache.GetOrAddDisposable(connectionString, k => new CosmosClient(k)), - new CosmosDbHealthCheckOptions { ContainerIds = containers, DatabaseId = database }) - { } - - public CosmosDbHealthCheck(string accountEndpoint, TokenCredential tokenCredential, string? database, IEnumerable? containers) - : this( - ClientCache.GetOrAddDisposable(accountEndpoint, k => new CosmosClient(accountEndpoint, tokenCredential)), - new CosmosDbHealthCheckOptions { ContainerIds = containers, DatabaseId = database }) - { } - - public CosmosDbHealthCheck(CosmosClient cosmosClient) - : this(cosmosClient, new CosmosDbHealthCheckOptions()) - { } - - public CosmosDbHealthCheck(CosmosClient cosmosClient, CosmosDbHealthCheckOptions options) - { - _cosmosClient = Guard.ThrowIfNull(cosmosClient); - _options = Guard.ThrowIfNull(options); - } - - /// - public async Task CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) - { - try - { - await _cosmosClient.ReadAccountAsync().ConfigureAwait(false); - - if (_options.DatabaseId != null) - { - var database = _cosmosClient.GetDatabase(_options.DatabaseId); - await database.ReadAsync(cancellationToken: cancellationToken).ConfigureAwait(false); - - if (_options.ContainerIds != null) - { - foreach (var container in _options.ContainerIds) - { - await database - .GetContainer(container) - .ReadContainerAsync(cancellationToken: cancellationToken) - .ConfigureAwait(false); - } - } - } - - return HealthCheckResult.Healthy(); - } - catch (Exception ex) - { - return new HealthCheckResult(context.Registration.FailureStatus, exception: ex); - } - } -} diff --git a/src/HealthChecks.CosmosDb/DependencyInjection/CosmosDbHealthCheckBuilderExtensions.cs b/src/HealthChecks.CosmosDb/DependencyInjection/CosmosDbHealthCheckBuilderExtensions.cs index 845b063601..6d3ef9d23a 100644 --- a/src/HealthChecks.CosmosDb/DependencyInjection/CosmosDbHealthCheckBuilderExtensions.cs +++ b/src/HealthChecks.CosmosDb/DependencyInjection/CosmosDbHealthCheckBuilderExtensions.cs @@ -1,5 +1,3 @@ -using Azure.Core; -using Azure.Data.Tables; using HealthChecks.CosmosDb; using Microsoft.Azure.Cosmos; using Microsoft.Extensions.Diagnostics.HealthChecks; @@ -7,486 +5,46 @@ namespace Microsoft.Extensions.DependencyInjection; /// -/// Extension methods to configure and . +/// Extension methods to configure . /// public static class CosmosDbHealthCheckBuilderExtensions { - private const string COSMOS_NAME = "cosmosdb"; - private const string TABLE_NAME = "azuretable"; + private const string HEALTH_CHECK_NAME = "azure_cosmosdb"; /// - /// Add a health check for Azure CosmosDb database. + /// Add a health check for Azure Cosmos DB by registering for given . /// - /// The . - /// CosmosDb full connection string. - /// Database to check for existence. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddCosmosDb( - this IHealthChecksBuilder builder, - string connectionString, - string? database = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? COSMOS_NAME, - sp => new CosmosDbHealthCheck(connectionString, database, Enumerable.Empty()), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure CosmosDb database. - /// - /// The . - /// Uri to the CosmosDb account. - /// An instance of to be used for authentication. - /// Database to check for existence. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddCosmosDb( - this IHealthChecksBuilder builder, - string accountEndpoint, - TokenCredential tokenCredential, - string? database = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? COSMOS_NAME, - sp => new CosmosDbHealthCheck(accountEndpoint, tokenCredential, database, Enumerable.Empty()), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure CosmosDb database. - /// - /// - /// A service must be registered in the DI container. - /// - /// The . - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If then - /// the default status of will be reported. + /// The to add to. + /// + /// An optional factory to obtain instance. + /// When not provided, is simply resolved from . /// - /// A list of tags that can be used to filter sets of health checks. Optional. - /// An optional representing the timeout of the check. - /// The specified . - public static IHealthChecksBuilder AddCosmosDb( - this IHealthChecksBuilder builder, - Action? configureOptions = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? COSMOS_NAME, - sp => - { - var options = new CosmosDbHealthCheckOptions(); - configureOptions?.Invoke(options); - return new CosmosDbHealthCheck(sp.GetRequiredService(), options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure CosmosDb database. - /// - /// - /// A service must be registered in the DI container. - /// - /// The . - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If then - /// the default status of will be reported. + /// + /// An optional factory to obtain used by the health check. + /// When not provided, defaults are used. /// - /// A list of tags that can be used to filter sets of health checks. Optional. - /// An optional representing the timeout of the check. - /// The specified . - public static IHealthChecksBuilder AddCosmosDb( - this IHealthChecksBuilder builder, - Action? configureOptions = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? COSMOS_NAME, - sp => - { - var options = new CosmosDbHealthCheckOptions(); - configureOptions?.Invoke(sp, options); - return new CosmosDbHealthCheck(sp.GetRequiredService(), options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure CosmosDb database. - /// - /// The . - /// The instance that will communicate with the database. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddCosmosDb( - this IHealthChecksBuilder builder, - CosmosClient client, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? COSMOS_NAME, - sp => new CosmosDbHealthCheck(client), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure CosmosDb database. - /// - /// The . - /// The instance that will communicate with the database. - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddCosmosDb( - this IHealthChecksBuilder builder, - CosmosClient client, - Action configureOptions, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? COSMOS_NAME, - sp => - { - var options = new CosmosDbHealthCheckOptions(); - configureOptions?.Invoke(options); - return new CosmosDbHealthCheck(client, options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure CosmosDb database. - /// - /// The . - /// The instance that will communicate with the database. - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddCosmosDb( - this IHealthChecksBuilder builder, - CosmosClient client, - Action configureOptions, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? COSMOS_NAME, - sp => - { - var options = new CosmosDbHealthCheckOptions(); - configureOptions?.Invoke(sp, options); - return new CosmosDbHealthCheck(client, options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure CosmosDb database and specified collections. - /// - /// The . - /// CosmosDb full connection string. - /// Database to check for existence. - /// Cosmos DB collections to check for existence. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddCosmosDbCollection( - this IHealthChecksBuilder builder, - string connectionString, - string? database = default, - IEnumerable? collections = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? COSMOS_NAME, - sp => new CosmosDbHealthCheck(connectionString, database, collections), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure CosmosDb database and specified collections using Managed identity. - /// - /// The . - /// Uri to the CosmosDb account. - /// An instance of to be used for authentication. - /// Database to check for existence. - /// Cosmos DB collections to check for existence. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddCosmosDbCollection( - this IHealthChecksBuilder builder, - string accountEndpoint, - TokenCredential tokenCredential, - string? database = default, - IEnumerable? collections = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? COSMOS_NAME, - sp => new CosmosDbHealthCheck(accountEndpoint, tokenCredential, database, collections), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Tables hosted in either Azure storage accounts or Azure Cosmos DB table API. - /// - /// The . - /// The CosmosDB Table or Azure Storage Table connection string. Credentials are included on connectionstring. - /// Table name to check for existence. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureTable( - this IHealthChecksBuilder builder, - string connectionString, - string tableName, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? TABLE_NAME, - sp => new TableServiceHealthCheck(connectionString, tableName), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Tables hosted in either Azure storage accounts or Azure Cosmos DB table API. - /// - /// The . - /// The CosmosDB Table or Azure Storage Table uri endpoint. - /// The table shared key credentials to be used. - /// Table name to check for existence. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureTable( - this IHealthChecksBuilder builder, - Uri endpoint, - TableSharedKeyCredential credentials, - string? tableName, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? TABLE_NAME, - sp => new TableServiceHealthCheck(endpoint, credentials, tableName), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Tables hosted in either Azure storage accounts or Azure Cosmos DB table API. - /// - /// The . - /// The CosmosDB Table or Azure Storage Table uri endpoint. - /// An instance of to be used for authentication. - /// Table name to check for existence. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureTable( - this IHealthChecksBuilder builder, - Uri endpoint, - TokenCredential tokenCredential, - string tableName, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? TABLE_NAME, - sp => new TableServiceHealthCheck(endpoint, tokenCredential, tableName), - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Tables hosted in either Azure storage accounts or Azure Cosmos DB table API. - /// - /// - /// A service must be registered in the DI container. - /// - /// The . - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. - /// - /// The that should be reported when the health check fails. Optional. If 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. - /// The specified . - public static IHealthChecksBuilder AddAzureTable( - this IHealthChecksBuilder builder, - Action? configureOptions = default, - string? name = default, - HealthStatus? failureStatus = default, - IEnumerable? tags = default, - TimeSpan? timeout = default) - { - return builder.Add(new HealthCheckRegistration( - name ?? TABLE_NAME, - sp => - { - var options = new TableServiceHealthCheckOptions(); - configureOptions?.Invoke(options); - return new TableServiceHealthCheck(sp.GetRequiredService(), options); - }, - failureStatus, - tags, - timeout)); - } - - /// - /// Add a health check for Azure Tables hosted in either Azure storage accounts or Azure Cosmos DB table API. - /// - /// - /// A service must be registered in the DI container. - /// - /// The . - /// Delegate for configuring the health check. Optional. - /// The health check name. Optional. If the type name 'cosmosdb' will be used for the name. + /// The health check name. Optional. If null the name 'azure_cosmosdb' will be used. /// - /// The that should be reported when the health check fails. Optional. If then + /// 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. /// The specified . - public static IHealthChecksBuilder AddAzureTable( + public static IHealthChecksBuilder AddAzureCosmosDB( this IHealthChecksBuilder builder, - Action? configureOptions = default, - string? name = default, + Func? clientFactory = default, + Func? optionsFactory = default, + string? healthCheckName = HEALTH_CHECK_NAME, HealthStatus? failureStatus = default, IEnumerable? tags = default, TimeSpan? timeout = default) { return builder.Add(new HealthCheckRegistration( - name ?? TABLE_NAME, - sp => - { - var options = new TableServiceHealthCheckOptions(); - configureOptions?.Invoke(sp, options); - return new TableServiceHealthCheck(sp.GetRequiredService(), options); - }, + string.IsNullOrEmpty(healthCheckName) ? HEALTH_CHECK_NAME : healthCheckName!, + sp => new AzureCosmosDbHealthCheck( + cosmosClient: clientFactory?.Invoke(sp) ?? sp.GetRequiredService(), + options: optionsFactory?.Invoke(sp)), failureStatus, tags, timeout)); diff --git a/src/HealthChecks.CosmosDb/HealthChecks.CosmosDb.csproj b/src/HealthChecks.CosmosDb/HealthChecks.CosmosDb.csproj index a22f793141..db5005b25c 100644 --- a/src/HealthChecks.CosmosDb/HealthChecks.CosmosDb.csproj +++ b/src/HealthChecks.CosmosDb/HealthChecks.CosmosDb.csproj @@ -10,7 +10,6 @@ - diff --git a/src/HealthChecks.CosmosDb/README.md b/src/HealthChecks.CosmosDb/README.md new file mode 100644 index 0000000000..af2b7c35fa --- /dev/null +++ b/src/HealthChecks.CosmosDb/README.md @@ -0,0 +1,52 @@ +## Azure Cosmos DB Health Check + +This health check verifies the ability to communicate with [Azure Cosmos DB](https://azure.microsoft.com/en-us/products/cosmos-db/). It uses the provided [CosmosClient](https://learn.microsoft.com/dotnet/api/microsoft.azure.cosmos.cosmosclient). + +### Defaults + +By default, the `CosmosClient` instance is resolved from service provider. `AzureCosmosDbHealthCheckOptions` does not provide any specific containers or database ids, the health check just calls [CosmosClient.ReadAccountAsync](https://learn.microsoft.com/dotnet/api/microsoft.azure.cosmos.cosmosclient.readaccountasync). + +```csharp +void Configure(IHealthChecksBuilder builder) +{ + builder.Services.AddSingleton(sp => new CosmosClient( + "endpoint-from-portal", + new DefaultAzureCredential())); + builder.AddHealthChecks().AddAzureCosmosDB(); +} +``` + +### Customization + +You can additionally add the following parameters: + +- `clientFactory`: A factory method to provide `CosmosClient` instance. +- `optionsFactory`: A factory method to provide `AzureCosmosDbHealthCheckOptions` instance. It allows to specify the database id and/or container id(s). +- `healthCheckName`: The health check name. The default is `azure_cosmosdb`. +- `failureStatus`: The `HealthStatus` that should be reported when the health check fails. Default is `HealthStatus.Unhealthy`. +- `tags`: A list of tags that can be used to filter sets of health checks. +- `timeout`: A `System.TimeSpan` representing the timeout of the check. + +```csharp +void Configure(IHealthChecksBuilder builder) +{ + builder.Services.AddSingleton(sp => new CosmosClient( + "endpoint-from-portal", + new DefaultAzureCredential(), + new CosmosClientOptions() + { + ApplicationRegion = Regions.EastUS2, + })); + builder.AddHealthChecks().AddAzureCosmosDB( + optionsFactory: sp => new CosmosDbHealthCheckOptions() + { + DatabaseId = "demo" + }); +} +``` + +### Breaking changes + +In the prior releases, `CosmosDbHealthCheck` was a part of `HealthChecks.CosmosDb` package. It had a dependency on not just `Microsoft.Azure.Cosmos`, but also `Azure.Data.Tables`. The packages have been split to avoid bringing unnecessary dependencies. Moreover, `CosmosDbHealthCheck` was letting the users specify how `CosmosClient` should be created (from raw connection string or from endpoint and managed identity credentials), at a cost of maintaining an internal, static client instances cache. Now the type does not create client instances nor maintain an internal cache and **it's the caller responsibility to provide the instance of `CosmosClient`** (please see [#2040](https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/issues/2040) for more details). Since Azure SDK recommends treating clients as singletons and client instances can be expensive to create, it's recommended to register a singleton factory method for Azure SDK clients. So the clients are created only when needed and once per whole application lifetime. + + diff --git a/test/HealthChecks.Azure.Data.Tables.Tests/HealthChecks.Azure.Data.Tables.Tests.csproj b/test/HealthChecks.Azure.Data.Tables.Tests/HealthChecks.Azure.Data.Tables.Tests.csproj new file mode 100644 index 0000000000..da1991f7f3 --- /dev/null +++ b/test/HealthChecks.Azure.Data.Tables.Tests/HealthChecks.Azure.Data.Tables.Tests.csproj @@ -0,0 +1,12 @@ + + + + net6.0;net7.0 + + + + + + + + diff --git a/test/HealthChecks.Azure.Data.Tables.Tests/HealthChecks.Azure.Data.Tables.approved.txt b/test/HealthChecks.Azure.Data.Tables.Tests/HealthChecks.Azure.Data.Tables.approved.txt new file mode 100644 index 0000000000..5c42ac762f --- /dev/null +++ b/test/HealthChecks.Azure.Data.Tables.Tests/HealthChecks.Azure.Data.Tables.approved.txt @@ -0,0 +1,20 @@ +namespace HealthChecks.Azure.Data.Tables +{ + public sealed class AzureTableServiceHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck + { + public AzureTableServiceHealthCheck(Azure.Data.Tables.TableServiceClient tableServiceClient, HealthChecks.Azure.Data.Tables.AzureTableServiceHealthCheckOptions? options) { } + public System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { } + } + public sealed class AzureTableServiceHealthCheckOptions + { + public AzureTableServiceHealthCheckOptions() { } + public string? TableName { get; set; } + } +} +namespace Microsoft.Extensions.DependencyInjection +{ + public static class AzureTablesServiceHealthChecksBuilderExtensions + { + public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureTable(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func? clientFactory = null, System.Func? optionsFactory = null, string? healthCheckName = "azure_tables", Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } + } +} \ No newline at end of file diff --git a/test/HealthChecks.CosmosDb.Tests/TableServiceHealthCheckTests.cs b/test/HealthChecks.Azure.Data.Tables.Tests/TableServiceHealthCheckTests.cs similarity index 94% rename from test/HealthChecks.CosmosDb.Tests/TableServiceHealthCheckTests.cs rename to test/HealthChecks.Azure.Data.Tables.Tests/TableServiceHealthCheckTests.cs index c242f6fac9..4e2c51c835 100644 --- a/test/HealthChecks.CosmosDb.Tests/TableServiceHealthCheckTests.cs +++ b/test/HealthChecks.Azure.Data.Tables.Tests/TableServiceHealthCheckTests.cs @@ -5,7 +5,7 @@ using NSubstitute; using NSubstitute.ExceptionExtensions; -namespace HealthChecks.CosmosDb.Tests; +namespace HealthChecks.Azure.Data.Tables.Tests; public class tableservicehealthcheck_should { @@ -14,16 +14,16 @@ public class tableservicehealthcheck_should private readonly TableServiceClient _tableServiceClient; private readonly TableClient _tableClient; - private readonly TableServiceHealthCheckOptions _options; - private readonly TableServiceHealthCheck _healthCheck; + private readonly AzureTableServiceHealthCheckOptions _options; + private readonly AzureTableServiceHealthCheck _healthCheck; private readonly HealthCheckContext _context; public tableservicehealthcheck_should() { _tableServiceClient = Substitute.For(); _tableClient = Substitute.For(); - _options = new TableServiceHealthCheckOptions(); - _healthCheck = new TableServiceHealthCheck(_tableServiceClient, _options); + _options = new AzureTableServiceHealthCheckOptions(); + _healthCheck = new AzureTableServiceHealthCheck(_tableServiceClient, _options); _context = new HealthCheckContext { Registration = new HealthCheckRegistration(HealthCheckName, _healthCheck, HealthStatus.Unhealthy, null) @@ -186,7 +186,7 @@ public async Task return_unhealthy_when_invoked_from_healthcheckservice() .AddSingleton(_tableServiceClient) .AddLogging() .AddHealthChecks() - .AddAzureTable(o => o.TableName = TableName, name: HealthCheckName) + .AddAzureTable(optionsFactory: _ => new AzureTableServiceHealthCheckOptions() { TableName = TableName }, healthCheckName: HealthCheckName) .Services .BuildServiceProvider(); diff --git a/test/HealthChecks.Azure.Data.Tables.Tests/TablesConformanceTests.cs b/test/HealthChecks.Azure.Data.Tables.Tests/TablesConformanceTests.cs new file mode 100644 index 0000000000..18fcb120ad --- /dev/null +++ b/test/HealthChecks.Azure.Data.Tables.Tests/TablesConformanceTests.cs @@ -0,0 +1,23 @@ +using Azure.Data.Tables; +using Azure.Identity; + +namespace HealthChecks.Azure.Data.Tables.Tests; + +public class TablesConformanceTests : ConformanceTests +{ + protected override IHealthChecksBuilder AddHealthCheck(IHealthChecksBuilder builder, Func? clientFactory = null, Func? optionsFactory = null, string? healthCheckName = null, HealthStatus? failureStatus = null, IEnumerable? tags = null, TimeSpan? timeout = null) + => builder.AddAzureTable(clientFactory, optionsFactory, healthCheckName, failureStatus, tags, timeout); + + protected override TableServiceClient CreateClientForNonExistingEndpoint() + { + TableClientOptions clientOptions = new(); + clientOptions.Retry.MaxRetries = 0; // don't enable retries (test runs few times faster) + return new(new Uri("https://www.thisisnotarealurl.com"), new DefaultAzureCredential(), clientOptions); + } + + protected override AzureTableServiceHealthCheck CreateHealthCheck(TableServiceClient client, AzureTableServiceHealthCheckOptions? options) + => new(client, options); + + protected override AzureTableServiceHealthCheckOptions CreateHealthCheckOptions() + => new(); +} diff --git a/test/HealthChecks.Azure.KeyVault.Secrets.Tests/Functional/AzureKeyVaultSecretOptionsTests.cs b/test/HealthChecks.Azure.KeyVault.Secrets.Tests/Functional/AzureKeyVaultSecretOptionsTests.cs index d4b010184d..e0f857617d 100644 --- a/test/HealthChecks.Azure.KeyVault.Secrets.Tests/Functional/AzureKeyVaultSecretOptionsTests.cs +++ b/test/HealthChecks.Azure.KeyVault.Secrets.Tests/Functional/AzureKeyVaultSecretOptionsTests.cs @@ -7,7 +7,7 @@ public class AzureKeyVaultSecretOptionsTests [Fact] public void SecretNameThrowsArgumentNullExceptionForNull() { - AzureKeyVaultSecretOptions sut = new(); + AzureKeyVaultSecretsHealthCheckOptions sut = new(); ArgumentNullException argumentNullException = Assert.ThrowsAny(() => sut.SecretName = null!); Assert.Equal("SecretName", argumentNullException.ParamName); } @@ -15,7 +15,7 @@ public void SecretNameThrowsArgumentNullExceptionForNull() [Fact] public void SecretNameThrowsArgumentNullExceptionForEmptyString() { - AzureKeyVaultSecretOptions sut = new(); + AzureKeyVaultSecretsHealthCheckOptions sut = new(); ArgumentException argumentException = Assert.ThrowsAny(() => sut.SecretName = string.Empty); Assert.Equal("SecretName", argumentException.ParamName); } diff --git a/test/HealthChecks.Azure.KeyVault.Secrets.Tests/Functional/AzureKeyVaultSecretsHealthCheckTests.cs b/test/HealthChecks.Azure.KeyVault.Secrets.Tests/Functional/AzureKeyVaultSecretsHealthCheckTests.cs deleted file mode 100644 index f196b96b03..0000000000 --- a/test/HealthChecks.Azure.KeyVault.Secrets.Tests/Functional/AzureKeyVaultSecretsHealthCheckTests.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System.Net; -using Azure.Identity; -using Azure.Security.KeyVault.Secrets; -using HealthChecks.Azure.KeyVault.Secrets; - -namespace HealthChecks.AzureKeyVault.Tests.Functional; - -public class AzureKeyVaultSecretsHealthCheckTests -{ - [Fact] - public void CtorThrowsArgumentNullExceptionForNullSecretClient() - { - ArgumentNullException argumentNullException = Assert.ThrowsAny( - () => new AzureKeyVaultSecretsHealthCheck(secretClient: null!, options: new AzureKeyVaultSecretOptions())); - - Assert.Equal("secretClient", argumentNullException.ParamName); - } - - [Fact] - public void CtorThrowsArgumentNullExceptionForNullOptions() - { - ArgumentNullException argumentNullException = Assert.ThrowsAny( - () => new AzureKeyVaultSecretsHealthCheck( - secretClient: new SecretClient(new Uri("https://www.thisisnotarealurl.com"), new DefaultAzureCredential()), - options: null!)); - - Assert.Equal("options", argumentNullException.ParamName); - } - - [Theory] - [InlineData(HealthStatus.Unhealthy)] - [InlineData(HealthStatus.Degraded)] - public async Task ReturnsProvidedFailureStatusWhenConnectionCanNotBeMade(HealthStatus failureStatus) - { - SecretClientOptions clientOptions = new(); - clientOptions.Retry.MaxRetries = 0; // don't enable retries (test runs few times faster) - SecretClient secretClient = new(new Uri("https://www.thisisnotarealurl.com"), new DefaultAzureCredential(), clientOptions); - - var webHostBuilder = new WebHostBuilder() - .ConfigureServices(services => - { - services.AddHealthChecks() - .Add(new HealthCheckRegistration( - name: "azure_key_vault_secrets", - instance: new AzureKeyVaultSecretsHealthCheck(secretClient, new AzureKeyVaultSecretOptions()), - failureStatus: failureStatus, - tags: null)); - }) - .Configure(app => - { - app.UseHealthChecks("/health", new HealthCheckOptions - { - Predicate = _ => true, - }); - }); - - using var server = new TestServer(webHostBuilder); - - using var response = await server.CreateRequest("/health").GetAsync().ConfigureAwait(false); - - response.StatusCode.ShouldBe(failureStatus == HealthStatus.Unhealthy ? HttpStatusCode.ServiceUnavailable : HttpStatusCode.OK); - } -} diff --git a/test/HealthChecks.Azure.KeyVault.Secrets.Tests/HealthChecks.Azure.KeyVault.Secrets.approved.txt b/test/HealthChecks.Azure.KeyVault.Secrets.Tests/HealthChecks.Azure.KeyVault.Secrets.approved.txt index a849bcead7..a2d55e42eb 100644 --- a/test/HealthChecks.Azure.KeyVault.Secrets.Tests/HealthChecks.Azure.KeyVault.Secrets.approved.txt +++ b/test/HealthChecks.Azure.KeyVault.Secrets.Tests/HealthChecks.Azure.KeyVault.Secrets.approved.txt @@ -1,21 +1,21 @@ namespace HealthChecks.Azure.KeyVault.Secrets { - public sealed class AzureKeyVaultSecretOptions - { - public AzureKeyVaultSecretOptions() { } - public bool CreateWhenNotFound { get; set; } - public string SecretName { get; set; } - } public sealed class AzureKeyVaultSecretsHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck { - public AzureKeyVaultSecretsHealthCheck(Azure.Security.KeyVault.Secrets.SecretClient secretClient, HealthChecks.Azure.KeyVault.Secrets.AzureKeyVaultSecretOptions options) { } + public AzureKeyVaultSecretsHealthCheck(Azure.Security.KeyVault.Secrets.SecretClient secretClient, HealthChecks.Azure.KeyVault.Secrets.AzureKeyVaultSecretsHealthCheckOptions? options = null) { } public System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { } } + public sealed class AzureKeyVaultSecretsHealthCheckOptions + { + public AzureKeyVaultSecretsHealthCheckOptions() { } + public bool CreateWhenNotFound { get; set; } + public string SecretName { get; set; } + } } namespace Microsoft.Extensions.DependencyInjection { public static class AzureKeyVaultHealthChecksBuilderExtensions { - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureKeyVaultSecrets(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func? secretClientFactory = null, System.Func? optionsFactory = null, string? healthCheckName = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } + public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureKeyVaultSecrets(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func? clientFactory = null, System.Func? optionsFactory = null, string? healthCheckName = "azure_key_vault_secret", Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } } } \ No newline at end of file diff --git a/test/HealthChecks.Azure.KeyVault.Secrets.Tests/SecretsConformanceTests.cs b/test/HealthChecks.Azure.KeyVault.Secrets.Tests/SecretsConformanceTests.cs new file mode 100644 index 0000000000..e8ca15d49e --- /dev/null +++ b/test/HealthChecks.Azure.KeyVault.Secrets.Tests/SecretsConformanceTests.cs @@ -0,0 +1,23 @@ +using Azure.Identity; +using Azure.Security.KeyVault.Secrets; +using HealthChecks.Azure.KeyVault.Secrets; + +namespace HealthChecks.AzureKeyVault.Tests; + +public class SecretsConformanceTests : ConformanceTests +{ + protected override SecretClient CreateClientForNonExistingEndpoint() + { + SecretClientOptions clientOptions = new(); + clientOptions.Retry.MaxRetries = 0; // don't enable retries (test runs few times faster) + return new(new Uri("https://www.thisisnotarealurl.com"), new DefaultAzureCredential(), clientOptions); + } + + protected override AzureKeyVaultSecretsHealthCheckOptions CreateHealthCheckOptions() => new(); + + protected override AzureKeyVaultSecretsHealthCheck CreateHealthCheck(SecretClient client, AzureKeyVaultSecretsHealthCheckOptions? options) + => new(client, options); + + protected override IHealthChecksBuilder AddHealthCheck(IHealthChecksBuilder builder, Func? clientFactory = null, Func? optionsFactory = null, string? healthCheckName = null, HealthStatus? failureStatus = null, IEnumerable? tags = null, TimeSpan? timeout = null) + => builder.AddAzureKeyVaultSecrets(clientFactory, optionsFactory, healthCheckName, failureStatus, tags, timeout); +} diff --git a/test/HealthChecks.Azure.Messaging.EventHubs.Tests/EventHubsConformanceTests.cs b/test/HealthChecks.Azure.Messaging.EventHubs.Tests/EventHubsConformanceTests.cs new file mode 100644 index 0000000000..d09e71c45f --- /dev/null +++ b/test/HealthChecks.Azure.Messaging.EventHubs.Tests/EventHubsConformanceTests.cs @@ -0,0 +1,24 @@ +using Azure.Identity; +using Azure.Messaging.EventHubs.Producer; + +namespace HealthChecks.Azure.Messaging.EventHubs.Tests; + +public class EventHubsConformanceTests : ConformanceTests +{ + protected override IHealthChecksBuilder AddHealthCheck(IHealthChecksBuilder builder, Func? clientFactory = null, Func? optionsFactory = null, string? healthCheckName = null, HealthStatus? failureStatus = null, IEnumerable? tags = null, TimeSpan? timeout = null) + => builder.AddAzureEventHub(clientFactory, healthCheckName, failureStatus, tags, timeout); + + protected override EventHubProducerClient CreateClientForNonExistingEndpoint() + => new("fullyQualifiedNamespace", "eventHubName", new AzureCliCredential()); + + protected override AzureEventHubHealthCheck CreateHealthCheck(EventHubProducerClient client, UnusedOptions? options) + => new(client); + + protected override UnusedOptions CreateHealthCheckOptions() + => new(); +} + +// AzureEventHubHealthCheck does not use any options, the type exists only to meet ConformanceTests<,,> criteria +public sealed class UnusedOptions +{ +} diff --git a/test/HealthChecks.Azure.Messaging.EventHubs.Tests/HealthChecks.Azure.Messaging.EventHubs.Tests.csproj b/test/HealthChecks.Azure.Messaging.EventHubs.Tests/HealthChecks.Azure.Messaging.EventHubs.Tests.csproj new file mode 100644 index 0000000000..c9ea759210 --- /dev/null +++ b/test/HealthChecks.Azure.Messaging.EventHubs.Tests/HealthChecks.Azure.Messaging.EventHubs.Tests.csproj @@ -0,0 +1,15 @@ + + + + net6.0;net7.0 + + + + + + + + + + + diff --git a/test/HealthChecks.Azure.Messaging.EventHubs.Tests/HealthChecks.Azure.Messaging.EventHubs.approved.txt b/test/HealthChecks.Azure.Messaging.EventHubs.Tests/HealthChecks.Azure.Messaging.EventHubs.approved.txt new file mode 100644 index 0000000000..6eb8437244 --- /dev/null +++ b/test/HealthChecks.Azure.Messaging.EventHubs.Tests/HealthChecks.Azure.Messaging.EventHubs.approved.txt @@ -0,0 +1,15 @@ +namespace HealthChecks.Azure.Messaging.EventHubs +{ + public sealed class AzureEventHubHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck + { + public AzureEventHubHealthCheck(Azure.Messaging.EventHubs.Producer.EventHubProducerClient client) { } + public System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { } + } +} +namespace Microsoft.Extensions.DependencyInjection +{ + public static class AzureEventHubHealthChecksBuilderExtensions + { + public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureEventHub(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func? clientFactory = null, string? healthCheckName = "azure_event_hub", Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } + } +} \ No newline at end of file diff --git a/test/HealthChecks.AzureStorage.Tests/AzureBlobStorageHealthCheckTests.cs b/test/HealthChecks.Azure.Storage.Blobs.Tests/AzureBlobStorageHealthCheckTests.cs similarity index 97% rename from test/HealthChecks.AzureStorage.Tests/AzureBlobStorageHealthCheckTests.cs rename to test/HealthChecks.Azure.Storage.Blobs.Tests/AzureBlobStorageHealthCheckTests.cs index c0881206fd..c6063aab53 100644 --- a/test/HealthChecks.AzureStorage.Tests/AzureBlobStorageHealthCheckTests.cs +++ b/test/HealthChecks.Azure.Storage.Blobs.Tests/AzureBlobStorageHealthCheckTests.cs @@ -5,7 +5,7 @@ using NSubstitute; using NSubstitute.ExceptionExtensions; -namespace HealthChecks.AzureStorage.Tests; +namespace HealthChecks.Azure.Storage.Blobs.Tests; public class azureblobstoragehealthcheck_should { @@ -179,7 +179,7 @@ public async Task return_unhealthy_when_invoked_from_healthcheckservice() .AddSingleton(_blobServiceClient) .AddLogging() .AddHealthChecks() - .AddAzureBlobStorage(o => o.ContainerName = ContainerName, name: HealthCheckName) + .AddAzureBlobStorage(optionsFactory: _ => new AzureBlobStorageHealthCheckOptions() { ContainerName = ContainerName }, healthCheckName: HealthCheckName) .Services .BuildServiceProvider(); diff --git a/test/HealthChecks.Azure.Storage.Blobs.Tests/BlobStorageConformanceTests.cs b/test/HealthChecks.Azure.Storage.Blobs.Tests/BlobStorageConformanceTests.cs new file mode 100644 index 0000000000..9deea73350 --- /dev/null +++ b/test/HealthChecks.Azure.Storage.Blobs.Tests/BlobStorageConformanceTests.cs @@ -0,0 +1,23 @@ +using Azure.Identity; +using Azure.Storage.Blobs; + +namespace HealthChecks.Azure.Storage.Blobs.Tests; + +public class BlobStorageConformanceTests : ConformanceTests +{ + protected override IHealthChecksBuilder AddHealthCheck(IHealthChecksBuilder builder, Func? clientFactory = null, Func? optionsFactory = null, string? healthCheckName = null, HealthStatus? failureStatus = null, IEnumerable? tags = null, TimeSpan? timeout = null) + => builder.AddAzureBlobStorage(clientFactory, optionsFactory, healthCheckName, failureStatus, tags, timeout); + + protected override BlobServiceClient CreateClientForNonExistingEndpoint() + { + BlobClientOptions clientOptions = new(); + clientOptions.Retry.MaxRetries = 0; // don't enable retries (test runs few times faster) + return new(new Uri("https://www.thisisnotarealurl.com"), new DefaultAzureCredential(), clientOptions); + } + + protected override AzureBlobStorageHealthCheck CreateHealthCheck(BlobServiceClient client, AzureBlobStorageHealthCheckOptions? options) + => new(client, options); + + protected override AzureBlobStorageHealthCheckOptions CreateHealthCheckOptions() + => new(); +} diff --git a/test/HealthChecks.Azure.Storage.Blobs.Tests/HealthChecks.Azure.Storage.Blobs.Tests.csproj b/test/HealthChecks.Azure.Storage.Blobs.Tests/HealthChecks.Azure.Storage.Blobs.Tests.csproj new file mode 100644 index 0000000000..b4fdb495ef --- /dev/null +++ b/test/HealthChecks.Azure.Storage.Blobs.Tests/HealthChecks.Azure.Storage.Blobs.Tests.csproj @@ -0,0 +1,12 @@ + + + + net6.0;net7.0 + + + + + + + + diff --git a/test/HealthChecks.Azure.Storage.Blobs.Tests/HealthChecks.Azure.Storage.Blobs.approved.txt b/test/HealthChecks.Azure.Storage.Blobs.Tests/HealthChecks.Azure.Storage.Blobs.approved.txt new file mode 100644 index 0000000000..35f55fee35 --- /dev/null +++ b/test/HealthChecks.Azure.Storage.Blobs.Tests/HealthChecks.Azure.Storage.Blobs.approved.txt @@ -0,0 +1,20 @@ +namespace HealthChecks.Azure.Storage.Blobs +{ + public sealed class AzureBlobStorageHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck + { + public AzureBlobStorageHealthCheck(Azure.Storage.Blobs.BlobServiceClient blobServiceClient, HealthChecks.Azure.Storage.Blobs.AzureBlobStorageHealthCheckOptions? options = null) { } + public System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { } + } + public sealed class AzureBlobStorageHealthCheckOptions + { + public AzureBlobStorageHealthCheckOptions() { } + public string? ContainerName { get; set; } + } +} +namespace Microsoft.Extensions.DependencyInjection +{ + public static class AzureBlobStorageHealthChecksBuilderExtensions + { + public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureBlobStorage(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func? clientFactory = null, System.Func? optionsFactory = null, string? healthCheckName = "azure_blob_storage", Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } + } +} \ No newline at end of file diff --git a/test/HealthChecks.AzureStorage.Tests/AzureFileShareHealthCheckTests.cs b/test/HealthChecks.Azure.Storage.Files.Shares.Tests/AzureFileShareHealthCheckTests.cs similarity index 97% rename from test/HealthChecks.AzureStorage.Tests/AzureFileShareHealthCheckTests.cs rename to test/HealthChecks.Azure.Storage.Files.Shares.Tests/AzureFileShareHealthCheckTests.cs index 671a616b80..6d860fcaa6 100644 --- a/test/HealthChecks.AzureStorage.Tests/AzureFileShareHealthCheckTests.cs +++ b/test/HealthChecks.Azure.Storage.Files.Shares.Tests/AzureFileShareHealthCheckTests.cs @@ -5,7 +5,7 @@ using NSubstitute; using NSubstitute.ExceptionExtensions; -namespace HealthChecks.AzureStorage.Tests; +namespace HealthChecks.Azure.Storage.Files.Shares.Tests; public class azurefilesharehealthcheck_should { @@ -177,7 +177,7 @@ public async Task return_unhealthy_when_invoked_from_healthcheckservice() .AddSingleton(_shareServiceClient) .AddLogging() .AddHealthChecks() - .AddAzureFileShare(o => o.ShareName = ShareName, name: HealthCheckName) + .AddAzureFileShare(optionsFactory: _ => new AzureFileShareHealthCheckOptions() { ShareName = ShareName }, healthCheckName: HealthCheckName) .Services .BuildServiceProvider(); diff --git a/test/HealthChecks.Azure.Storage.Files.Shares.Tests/FileConformanceTests.cs b/test/HealthChecks.Azure.Storage.Files.Shares.Tests/FileConformanceTests.cs new file mode 100644 index 0000000000..84034b9495 --- /dev/null +++ b/test/HealthChecks.Azure.Storage.Files.Shares.Tests/FileConformanceTests.cs @@ -0,0 +1,23 @@ +using Azure.Identity; +using Azure.Storage.Files.Shares; + +namespace HealthChecks.Azure.Storage.Files.Shares.Tests; + +public class FileConformanceTests : ConformanceTests +{ + protected override IHealthChecksBuilder AddHealthCheck(IHealthChecksBuilder builder, Func? clientFactory = null, Func? optionsFactory = null, string? healthCheckName = null, HealthStatus? failureStatus = null, IEnumerable? tags = null, TimeSpan? timeout = null) + => builder.AddAzureFileShare(clientFactory, optionsFactory, healthCheckName, failureStatus, tags, timeout); + + protected override ShareServiceClient CreateClientForNonExistingEndpoint() + { + ShareClientOptions clientOptions = new(); + clientOptions.Retry.MaxRetries = 0; // don't enable retries (test runs few times faster) + return new(new Uri("https://www.thisisnotarealurl.com"), new DefaultAzureCredential(), clientOptions); + } + + protected override AzureFileShareHealthCheck CreateHealthCheck(ShareServiceClient client, AzureFileShareHealthCheckOptions? options) + => new(client, options); + + protected override AzureFileShareHealthCheckOptions CreateHealthCheckOptions() + => new(); +} diff --git a/test/HealthChecks.Azure.Storage.Files.Shares.Tests/HealthChecks.Azure.Storage.Files.Shares.Tests.csproj b/test/HealthChecks.Azure.Storage.Files.Shares.Tests/HealthChecks.Azure.Storage.Files.Shares.Tests.csproj new file mode 100644 index 0000000000..3384e6ef71 --- /dev/null +++ b/test/HealthChecks.Azure.Storage.Files.Shares.Tests/HealthChecks.Azure.Storage.Files.Shares.Tests.csproj @@ -0,0 +1,12 @@ + + + + net6.0;net7.0 + + + + + + + + diff --git a/test/HealthChecks.Azure.Storage.Files.Shares.Tests/HealthChecks.Azure.Storage.Files.Shares.approved.txt b/test/HealthChecks.Azure.Storage.Files.Shares.Tests/HealthChecks.Azure.Storage.Files.Shares.approved.txt new file mode 100644 index 0000000000..37ad8f1f4a --- /dev/null +++ b/test/HealthChecks.Azure.Storage.Files.Shares.Tests/HealthChecks.Azure.Storage.Files.Shares.approved.txt @@ -0,0 +1,20 @@ +namespace HealthChecks.Azure.Storage.Files.Shares +{ + public sealed class AzureFileShareHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck + { + public AzureFileShareHealthCheck(Azure.Storage.Files.Shares.ShareServiceClient shareServiceClient, HealthChecks.Azure.Storage.Files.Shares.AzureFileShareHealthCheckOptions? options) { } + public System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { } + } + public sealed class AzureFileShareHealthCheckOptions + { + public AzureFileShareHealthCheckOptions() { } + public string? ShareName { get; set; } + } +} +namespace Microsoft.Extensions.DependencyInjection +{ + public static class AzureFileShareStorageHealthChecksBuilderExtensions + { + public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureFileShare(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func? clientFactory = null, System.Func? optionsFactory = null, string? healthCheckName = "azure_file_share", Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } + } +} \ No newline at end of file diff --git a/test/HealthChecks.AzureStorage.Tests/AzureQueueStorageHealthCheckTests.cs b/test/HealthChecks.Azure.Storage.Queues.Tests/AzureQueueStorageHealthCheckTests.cs similarity index 97% rename from test/HealthChecks.AzureStorage.Tests/AzureQueueStorageHealthCheckTests.cs rename to test/HealthChecks.Azure.Storage.Queues.Tests/AzureQueueStorageHealthCheckTests.cs index d5c4a67c86..62fc92fd4e 100644 --- a/test/HealthChecks.AzureStorage.Tests/AzureQueueStorageHealthCheckTests.cs +++ b/test/HealthChecks.Azure.Storage.Queues.Tests/AzureQueueStorageHealthCheckTests.cs @@ -5,7 +5,7 @@ using NSubstitute; using NSubstitute.ExceptionExtensions; -namespace HealthChecks.AzureStorage.Tests; +namespace HealthChecks.Azure.Storage.Queues.Tests; public class azurequeuestoragehealthcheck_should { @@ -177,7 +177,7 @@ public async Task return_unhealthy_when_invoked_from_healthcheckservice() .AddSingleton(_queueServiceClient) .AddLogging() .AddHealthChecks() - .AddAzureQueueStorage(o => o.QueueName = QueueName, name: HealthCheckName) + .AddAzureQueueStorage(optionsFactory: _ => new AzureQueueStorageHealthCheckOptions() { QueueName = QueueName }, healthCheckName: HealthCheckName) .Services .BuildServiceProvider(); diff --git a/test/HealthChecks.Azure.Storage.Queues.Tests/HealthChecks.Azure.Storage.Queues.Tests.csproj b/test/HealthChecks.Azure.Storage.Queues.Tests/HealthChecks.Azure.Storage.Queues.Tests.csproj new file mode 100644 index 0000000000..37172fa5c2 --- /dev/null +++ b/test/HealthChecks.Azure.Storage.Queues.Tests/HealthChecks.Azure.Storage.Queues.Tests.csproj @@ -0,0 +1,12 @@ + + + + net6.0;net7.0 + + + + + + + + diff --git a/test/HealthChecks.Azure.Storage.Queues.Tests/HealthChecks.Azure.Storage.Queues.approved.txt b/test/HealthChecks.Azure.Storage.Queues.Tests/HealthChecks.Azure.Storage.Queues.approved.txt new file mode 100644 index 0000000000..3cdad33a89 --- /dev/null +++ b/test/HealthChecks.Azure.Storage.Queues.Tests/HealthChecks.Azure.Storage.Queues.approved.txt @@ -0,0 +1,20 @@ +namespace HealthChecks.Azure.Storage.Queues +{ + public sealed class AzureQueueStorageHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck + { + public AzureQueueStorageHealthCheck(Azure.Storage.Queues.QueueServiceClient queueServiceClient, HealthChecks.Azure.Storage.Queues.AzureQueueStorageHealthCheckOptions? options = null) { } + public System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { } + } + public sealed class AzureQueueStorageHealthCheckOptions + { + public AzureQueueStorageHealthCheckOptions() { } + public string? QueueName { get; set; } + } +} +namespace Microsoft.Extensions.DependencyInjection +{ + public static class AzureQueueStorageHealthChecksBuilderExtensions + { + public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureQueueStorage(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func? clientFactory = null, System.Func? optionsFactory = null, string? healthCheckName = "azure_queue_storage", Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } + } +} \ No newline at end of file diff --git a/test/HealthChecks.Azure.Storage.Queues.Tests/QueueStorageConformanceTests.cs b/test/HealthChecks.Azure.Storage.Queues.Tests/QueueStorageConformanceTests.cs new file mode 100644 index 0000000000..3bd161e063 --- /dev/null +++ b/test/HealthChecks.Azure.Storage.Queues.Tests/QueueStorageConformanceTests.cs @@ -0,0 +1,23 @@ +using Azure.Identity; +using Azure.Storage.Queues; + +namespace HealthChecks.Azure.Storage.Queues.Tests; + +public class QueueStorageConformanceTests : ConformanceTests +{ + protected override IHealthChecksBuilder AddHealthCheck(IHealthChecksBuilder builder, Func? clientFactory = null, Func? optionsFactory = null, string? healthCheckName = null, HealthStatus? failureStatus = null, IEnumerable? tags = null, TimeSpan? timeout = null) + => builder.AddAzureQueueStorage(clientFactory, optionsFactory, healthCheckName, failureStatus, tags, timeout); + + protected override QueueServiceClient CreateClientForNonExistingEndpoint() + { + QueueClientOptions clientOptions = new(); + clientOptions.Retry.MaxRetries = 0; // don't enable retries (test runs few times faster) + return new(new Uri("https://www.thisisnotarealurl.com"), new DefaultAzureCredential(), clientOptions); + } + + protected override AzureQueueStorageHealthCheck CreateHealthCheck(QueueServiceClient client, AzureQueueStorageHealthCheckOptions? options) + => new(client, options); + + protected override AzureQueueStorageHealthCheckOptions CreateHealthCheckOptions() + => new(); +} diff --git a/test/HealthChecks.AzureServiceBus.Tests/DependencyInjection/AzureEventHubRegistrationTests.cs b/test/HealthChecks.AzureServiceBus.Tests/DependencyInjection/AzureEventHubRegistrationTests.cs deleted file mode 100644 index 87ad0681ff..0000000000 --- a/test/HealthChecks.AzureServiceBus.Tests/DependencyInjection/AzureEventHubRegistrationTests.cs +++ /dev/null @@ -1,134 +0,0 @@ -using Azure.Messaging.EventHubs; - -namespace HealthChecks.AzureServiceBus.Tests; - -public class azure_event_hub_registration_should -{ - [Fact] - public void add_health_check_when_properly_configured_using_connectionstring_and_eventhubname() - { - var services = new ServiceCollection(); - services.AddHealthChecks() - .AddAzureEventHub( - "Endpoint=sb://dummynamespace.servicebus.windows.net/;SharedAccessKeyName=DummyAccessKeyName;SharedAccessKey=5dOntTRytoC24opYThisAsit3is2B+OGY1US/fuL3ly=", - "hubName"); - - using var serviceProvider = services.BuildServiceProvider(); - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe("azureeventhub"); - check.ShouldBeOfType(); - } - - [Fact] - public void add_health_check_when_properly_configured_using_eventhubconnectionfactory() - { - Func factory = - _ => new EventHubConnection( - "Endpoint=sb://dummynamespace.servicebus.windows.net/;SharedAccessKeyName=DummyAccessKeyName;SharedAccessKey=5dOntTRytoC24opYThisAsit3is2B+OGY1US/fuL3ly=", - "hubnameconnection"); - - var services = new ServiceCollection(); - services.AddHealthChecks() - .AddAzureEventHub(factory); - - using var serviceProvider = services.BuildServiceProvider(); - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe("azureeventhub"); - check.ShouldBeOfType(); - } - - [Fact] - public void add_named_health_check_when_properly_configured_using_connectionstring_and_eventhubname() - { - var services = new ServiceCollection(); - services.AddHealthChecks() - .AddAzureEventHub( - "Endpoint=sb://dummynamespace.servicebus.windows.net/;SharedAccessKeyName=DummyAccessKeyName;SharedAccessKey=5dOntTRytoC24opYThisAsit3is2B+OGY1US/fuL3ly=", - "hubName", name: "azureeventhubcheck"); - - using var serviceProvider = services.BuildServiceProvider(); - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe("azureeventhubcheck"); - check.ShouldBeOfType(); - } - - [Fact] - public void add_named_health_check_when_properly_configured_using_connectionfactory() - { - Func factory = - _ => new EventHubConnection( - "Endpoint=sb://dummynamespace.servicebus.windows.net/;SharedAccessKeyName=DummyAccessKeyName;SharedAccessKey=5dOntTRytoC24opYThisAsit3is2B+OGY1US/fuL3ly=", - "hubname"); - - var services = new ServiceCollection(); - services.AddHealthChecks() - .AddAzureEventHub(factory, name: "azureeventhubcheck"); - - using var serviceProvider = services.BuildServiceProvider(); - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe("azureeventhubcheck"); - check.ShouldBeOfType(); - } - - [Fact] - public void fail_when_no_health_check_configuration_provided() - { - var services = new ServiceCollection(); - services.AddHealthChecks() - .AddAzureEventHub(string.Empty, string.Empty); - - using var serviceProvider = services.BuildServiceProvider(); - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - - var exception = Should.Throw(() => registration.Factory(serviceProvider)); - exception.ParamName.ShouldBe("options"); - } - - [Fact] - public void add_health_check_using_connection_string_factory_and_event_hub_name_factory_when_properly_configured() - { - bool connectionStringFactoryCalled = false, eventHubNameFactoryCalled = false; - - var services = new ServiceCollection(); - services.AddHealthChecks() - .AddAzureEventHub(_ => - { - connectionStringFactoryCalled = true; - return "Endpoint=sb://dummynamespace.servicebus.windows.net/;SharedAccessKeyName=DummyAccessKeyName;SharedAccessKey=5dOntTRytoC24opYThisAsit3is2B+OGY1US/fuL3ly="; - }, - _ => - { - eventHubNameFactoryCalled = true; - return "hubName"; - }); - - using var serviceProvider = services.BuildServiceProvider(); - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe("azureeventhub"); - check.ShouldBeOfType(); - connectionStringFactoryCalled.ShouldBeTrue(); - eventHubNameFactoryCalled.ShouldBeTrue(); - } -} diff --git a/test/HealthChecks.AzureServiceBus.Tests/DependencyInjection/AzureEventHubUnitWithTokenRegistrationTests.cs b/test/HealthChecks.AzureServiceBus.Tests/DependencyInjection/AzureEventHubUnitWithTokenRegistrationTests.cs deleted file mode 100644 index f30f978462..0000000000 --- a/test/HealthChecks.AzureServiceBus.Tests/DependencyInjection/AzureEventHubUnitWithTokenRegistrationTests.cs +++ /dev/null @@ -1,129 +0,0 @@ -using Azure.Identity; - -namespace HealthChecks.AzureServiceBus.Tests; - -public class azure_event_hub_registration_with_token_should -{ - [Fact] - public void add_health_check_when_properly_configured() - { - var services = new ServiceCollection(); - services.AddHealthChecks() - .AddAzureEventHub("cnn", "eventHubName", new AzureCliCredential()); - - using var serviceProvider = services.BuildServiceProvider(); - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe("azureeventhub"); - check.ShouldBeOfType(); - } - - [Fact] - public void add_health_check_using_factories_when_properly_configured() - { - bool endpointFactoryCalled = false, eventHubNameFactoryCalled = false, tokenCredentialFactoryCalled = false; - - var services = new ServiceCollection(); - services.AddHealthChecks() - .AddAzureEventHub(_ => - { - endpointFactoryCalled = true; - return "cnn"; - }, - _ => - { - eventHubNameFactoryCalled = true; - return "eventHubName"; - }, - _ => - { - tokenCredentialFactoryCalled = true; - return new AzureCliCredential(); - }); - - using var serviceProvider = services.BuildServiceProvider(); - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe("azureeventhub"); - check.ShouldBeOfType(); - endpointFactoryCalled.ShouldBeTrue(); - eventHubNameFactoryCalled.ShouldBeTrue(); - tokenCredentialFactoryCalled.ShouldBeTrue(); - } - - [Fact] - public void add_named_health_check_when_properly_configured() - { - var services = new ServiceCollection(); - services.AddHealthChecks() - .AddAzureEventHub("cnn", "eventHubName", new AzureCliCredential(), name: "azureeventhubcheck"); - - using var serviceProvider = services.BuildServiceProvider(); - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe("azureeventhubcheck"); - check.ShouldBeOfType(); - } - - [Fact] - public void add_named_health_check_using_factories_when_properly_configured() - { - bool endpointFactoryCalled = false, eventHubNameFactoryCalled = false, tokenCredentialFactoryCalled = false; - - var services = new ServiceCollection(); - services.AddHealthChecks() - .AddAzureEventHub(_ => - { - endpointFactoryCalled = true; - return "cnn"; - }, - _ => - { - eventHubNameFactoryCalled = true; - return "eventHubName"; - }, - _ => - { - tokenCredentialFactoryCalled = true; - return new AzureCliCredential(); - }, - name: "azureeventhubcheck"); - - using var serviceProvider = services.BuildServiceProvider(); - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe("azureeventhubcheck"); - check.ShouldBeOfType(); - endpointFactoryCalled.ShouldBeTrue(); - eventHubNameFactoryCalled.ShouldBeTrue(); - tokenCredentialFactoryCalled.ShouldBeTrue(); - } - - [Fact] - public void fail_when_no_health_check_configuration_provided() - { - var services = new ServiceCollection(); - services.AddHealthChecks() - .AddAzureEventHub(string.Empty, string.Empty, new AzureCliCredential()); - - using var serviceProvider = services.BuildServiceProvider(); - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - - var exception = Should.Throw(() => registration.Factory(serviceProvider)); - exception.ParamName.ShouldBe("options.FullyQualifiedNamespace"); - } -} diff --git a/test/HealthChecks.AzureServiceBus.Tests/HealthChecks.AzureServiceBus.approved.txt b/test/HealthChecks.AzureServiceBus.Tests/HealthChecks.AzureServiceBus.approved.txt index e99ed17a40..d879b56adc 100644 --- a/test/HealthChecks.AzureServiceBus.Tests/HealthChecks.AzureServiceBus.approved.txt +++ b/test/HealthChecks.AzureServiceBus.Tests/HealthChecks.AzureServiceBus.approved.txt @@ -1,10 +1,5 @@ namespace HealthChecks.AzureServiceBus { - public class AzureEventHubHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck - { - public AzureEventHubHealthCheck(HealthChecks.AzureServiceBus.Configuration.AzureEventHubHealthCheckOptions options) { } - public System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { } - } public abstract class AzureServiceBusHealthCheck where TOptions : HealthChecks.AzureServiceBus.Configuration.AzureServiceBusHealthCheckOptions { @@ -51,15 +46,6 @@ namespace HealthChecks.AzureServiceBus } namespace HealthChecks.AzureServiceBus.Configuration { - public class AzureEventHubHealthCheckOptions - { - public AzureEventHubHealthCheckOptions() { } - public Azure.Messaging.EventHubs.EventHubConnection? Connection { get; set; } - public string? ConnectionString { get; set; } - public Azure.Core.TokenCredential? Credential { get; set; } - public string? EventHubName { get; set; } - public string? FullyQualifiedNamespace { get; set; } - } public abstract class AzureServiceBusHealthCheckOptions { protected AzureServiceBusHealthCheckOptions() { } @@ -101,11 +87,6 @@ namespace Microsoft.Extensions.DependencyInjection { public static class AzureServiceBusHealthCheckBuilderExtensions { - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureEventHub(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func eventHubConnectionFactory, System.Action? configure = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureEventHub(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func connectionStringFactory, System.Func eventHubNameFactory, System.Action? configure = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureEventHub(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string connectionString, string eventHubName, System.Action? configure = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureEventHub(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func fullyQualifiedNamespaceFactory, System.Func eventHubNameFactory, System.Func tokenCredentialFactory, System.Action? configure = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureEventHub(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string fullyQualifiedNamespace, string eventHubName, Azure.Core.TokenCredential tokenCredential, System.Action? configure = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureServiceBusQueue(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func connectionStringFactory, System.Func queueNameFactory, System.Action? configure = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureServiceBusQueue(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string connectionString, string queueName, System.Action? configure = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureServiceBusQueue(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func fullyQualifiedNamespaceFactory, System.Func queueNameFactory, System.Func tokenCredentialFactory, System.Action? configure = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } diff --git a/test/HealthChecks.AzureStorage.Tests/DependencyInjection/AzureBlobStorageRegistrationTests.cs b/test/HealthChecks.AzureStorage.Tests/DependencyInjection/AzureBlobStorageRegistrationTests.cs deleted file mode 100644 index 56c564ef72..0000000000 --- a/test/HealthChecks.AzureStorage.Tests/DependencyInjection/AzureBlobStorageRegistrationTests.cs +++ /dev/null @@ -1,177 +0,0 @@ -using Azure.Core; -using Azure.Storage.Blobs; -using NSubstitute; - -namespace HealthChecks.AzureStorage.Tests.DependencyInjection; - -public class azureblobstorage_registration_should -{ - [Theory] - [InlineData(null, null, null)] - [InlineData("container", null, null)] - [InlineData(null, "my-azureblob-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("container", "my-azureblob-group", HealthStatus.Degraded)] - public void add_health_check_when_properly_configured(string? containerName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddAzureBlobStorage( - "BlobEndpoint=https://unit-test.blob.core.windows.net", - containerName: containerName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azureblob"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("container", null, null)] - [InlineData(null, "my-azureblob-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("container", "my-azureblob-group", HealthStatus.Degraded)] - public void add_health_check_with_uri_when_properly_configured(string? containerName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddAzureBlobStorage( - new Uri("https://unit-test.blob.core.windows.net"), - Substitute.For(), - containerName: containerName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azureblob"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("container", null, null)] - [InlineData(null, "my-azureblob-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("container", "my-azureblob-group", HealthStatus.Degraded)] - public void add_health_check_with_client_from_service_provider(string? containerName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddSingleton(Substitute.For()) - .AddHealthChecks() - .AddAzureBlobStorage( - o => o.ContainerName = containerName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azureblob"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("container", null, null)] - [InlineData(null, "my-azureblob-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("container", "my-azureblob-group", HealthStatus.Degraded)] - public void add_health_check_with_client_from_delegate(string? containerName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddAzureBlobStorage( - clientFactory: sp => Substitute.For(), - o => o.ContainerName = containerName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azureblob"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("container", null, null)] - [InlineData(null, "my-azureblob-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("container", "my-azureblob-group", HealthStatus.Degraded)] - public void add_health_check_with_client_from_service_provider_and_advanced_delegate(string? containerName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddSingleton(Substitute.For()) - .AddHealthChecks() - .AddAzureBlobStorage( - (sp, o) => o.ContainerName = containerName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azureblob"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("container", null, null)] - [InlineData(null, "my-azureblob-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("container", "my-azureblob-group", HealthStatus.Degraded)] - public void add_health_check_with_client_from_delegate_and_advanced_delegate(string? containerName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddAzureBlobStorage( - clientFactory: sp => Substitute.For(), - (sp, o) => o.ContainerName = containerName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azureblob"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } -} diff --git a/test/HealthChecks.AzureStorage.Tests/DependencyInjection/AzureFileShareStorageRegistrationTests.cs b/test/HealthChecks.AzureStorage.Tests/DependencyInjection/AzureFileShareStorageRegistrationTests.cs deleted file mode 100644 index 171cb125e1..0000000000 --- a/test/HealthChecks.AzureStorage.Tests/DependencyInjection/AzureFileShareStorageRegistrationTests.cs +++ /dev/null @@ -1,91 +0,0 @@ -using Azure.Storage.Files.Shares; -using NSubstitute; - -namespace HealthChecks.AzureStorage.Tests.DependencyInjection; - -public class azurefilesharestorage_registration_should -{ - [Theory] - [InlineData(null, null, null)] - [InlineData("share", null, null)] - [InlineData(null, "my-azurefileshare-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("share", "my-azurefileshare-group", HealthStatus.Degraded)] - public void add_health_check_when_properly_configured(string? shareName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddAzureFileShare( - "FileEndpoint=https://unit-test.file.core.windows.net", - shareName: shareName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azurefileshare"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("share", null, null)] - [InlineData(null, "my-azurefileshare-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("share", "my-azurefileshare-group", HealthStatus.Degraded)] - public void add_health_check_with_client_from_service_provider(string? shareName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddSingleton(Substitute.For()) - .AddHealthChecks() - .AddAzureFileShare( - o => o.ShareName = shareName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azurefileshare"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("share", null, null)] - [InlineData(null, "my-azurefileshare-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("share", "my-azurefileshare-group", HealthStatus.Degraded)] - public void add_health_check_with_client_from_service_provider_and_advanced_delegate(string? shareName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddSingleton(Substitute.For()) - .AddHealthChecks() - .AddAzureFileShare( - (sp, o) => o.ShareName = shareName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azurefileshare"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } -} diff --git a/test/HealthChecks.AzureStorage.Tests/DependencyInjection/AzureQueueStorageRegistrationTests.cs b/test/HealthChecks.AzureStorage.Tests/DependencyInjection/AzureQueueStorageRegistrationTests.cs deleted file mode 100644 index 016b908ef5..0000000000 --- a/test/HealthChecks.AzureStorage.Tests/DependencyInjection/AzureQueueStorageRegistrationTests.cs +++ /dev/null @@ -1,121 +0,0 @@ -using Azure.Core; -using Azure.Storage.Queues; -using NSubstitute; - -namespace HealthChecks.AzureStorage.Tests.DependencyInjection; - -public class azurequeuestorage_registration_should -{ - [Theory] - [InlineData(null, null, null)] - [InlineData("queue", null, null)] - [InlineData(null, "my-azurequeue-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("queue", "my-azurequeue-group", HealthStatus.Degraded)] - public void add_health_check_when_properly_configured(string? queueName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddAzureQueueStorage( - "QueueEndpoint=https://unit-test.queue.core.windows.net", - queueName: queueName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azurequeue"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("queue", null, null)] - [InlineData(null, "my-azurequeue-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("queue", "my-azurequeue-group", HealthStatus.Degraded)] - public void add_health_check_with_uri_when_properly_configured(string? queueName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddAzureQueueStorage( - new Uri("https://unit-test.queue.core.windows.net"), - Substitute.For(), - queueName: queueName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azurequeue"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("queue", null, null)] - [InlineData(null, "my-azurequeue-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("queue", "my-azurequeue-group", HealthStatus.Degraded)] - public void add_health_check_with_client_from_service_provider(string? queueName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddSingleton(Substitute.For()) - .AddHealthChecks() - .AddAzureQueueStorage( - o => o.QueueName = queueName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azurequeue"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("queue", null, null)] - [InlineData(null, "my-azurequeue-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("queue", "my-azurequeue-group", HealthStatus.Degraded)] - public void add_health_check_with_client_from_service_provider_and_advanced_delegate(string? queueName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddSingleton(Substitute.For()) - .AddHealthChecks() - .AddAzureQueueStorage( - (sp, o) => o.QueueName = queueName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azurequeue"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } -} diff --git a/test/HealthChecks.AzureStorage.Tests/HealthChecks.AzureStorage.Tests.csproj b/test/HealthChecks.AzureStorage.Tests/HealthChecks.AzureStorage.Tests.csproj deleted file mode 100644 index 04e2db7ad6..0000000000 --- a/test/HealthChecks.AzureStorage.Tests/HealthChecks.AzureStorage.Tests.csproj +++ /dev/null @@ -1,11 +0,0 @@ - - - - net6.0;net7.0 - - - - - - - diff --git a/test/HealthChecks.AzureStorage.Tests/HealthChecks.AzureStorage.approved.txt b/test/HealthChecks.AzureStorage.Tests/HealthChecks.AzureStorage.approved.txt deleted file mode 100644 index c6a711058c..0000000000 --- a/test/HealthChecks.AzureStorage.Tests/HealthChecks.AzureStorage.approved.txt +++ /dev/null @@ -1,57 +0,0 @@ -namespace HealthChecks.AzureStorage -{ - public class AzureBlobStorageHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck - { - public AzureBlobStorageHealthCheck(Azure.Storage.Blobs.BlobServiceClient blobServiceClient, HealthChecks.AzureStorage.AzureBlobStorageHealthCheckOptions options) { } - public AzureBlobStorageHealthCheck(string connectionString, string? containerName = null, Azure.Storage.Blobs.BlobClientOptions? clientOptions = null) { } - public AzureBlobStorageHealthCheck(System.Uri blobServiceUri, Azure.Core.TokenCredential credential, string? containerName = null, Azure.Storage.Blobs.BlobClientOptions? clientOptions = null) { } - public System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { } - } - public sealed class AzureBlobStorageHealthCheckOptions - { - public AzureBlobStorageHealthCheckOptions() { } - public string? ContainerName { get; set; } - } - public class AzureFileShareHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck - { - public AzureFileShareHealthCheck(Azure.Storage.Files.Shares.ShareServiceClient shareServiceClient, HealthChecks.AzureStorage.AzureFileShareHealthCheckOptions options) { } - public AzureFileShareHealthCheck(string connectionString, string? shareName = null) { } - public System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { } - } - public sealed class AzureFileShareHealthCheckOptions - { - public AzureFileShareHealthCheckOptions() { } - public string? ShareName { get; set; } - } - public class AzureQueueStorageHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck - { - public AzureQueueStorageHealthCheck(Azure.Storage.Queues.QueueServiceClient queueServiceClient, HealthChecks.AzureStorage.AzureQueueStorageHealthCheckOptions options) { } - public AzureQueueStorageHealthCheck(string connectionString, string? queueName = null) { } - public AzureQueueStorageHealthCheck(System.Uri queueServiceUri, Azure.Core.TokenCredential credential, string? queueName = null) { } - public System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { } - } - public sealed class AzureQueueStorageHealthCheckOptions - { - public AzureQueueStorageHealthCheckOptions() { } - public string? QueueName { get; set; } - } -} -namespace Microsoft.Extensions.DependencyInjection -{ - public static class AzureStorageHealthCheckBuilderExtensions - { - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureBlobStorage(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Action? configureOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureBlobStorage(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Action? configureOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureBlobStorage(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func clientFactory, System.Action? configureOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureBlobStorage(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func clientFactory, System.Action? configureOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureBlobStorage(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string connectionString, string? containerName = null, Azure.Storage.Blobs.BlobClientOptions? clientOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureBlobStorage(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Uri blobServiceUri, Azure.Core.TokenCredential credential, string? containerName = null, Azure.Storage.Blobs.BlobClientOptions? clientOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureFileShare(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Action? configureOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureFileShare(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Action? configureOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureFileShare(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string connectionString, string? shareName = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureQueueStorage(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Action? configureOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureQueueStorage(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Action? configureOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureQueueStorage(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string connectionString, string? queueName = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureQueueStorage(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Uri queueServiceUri, Azure.Core.TokenCredential credential, string? queueName = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - } -} \ No newline at end of file diff --git a/test/HealthChecks.CosmosDb.Tests/CosmosDbConformanceTests.cs b/test/HealthChecks.CosmosDb.Tests/CosmosDbConformanceTests.cs new file mode 100644 index 0000000000..452d56489f --- /dev/null +++ b/test/HealthChecks.CosmosDb.Tests/CosmosDbConformanceTests.cs @@ -0,0 +1,21 @@ +using Microsoft.Azure.Cosmos; + +namespace HealthChecks.CosmosDb.Tests; + +public class CosmosDbConformanceTests : ConformanceTests +{ + // Sample raw connection string taken from https://github.com/Azure/azure-cosmos-dotnet-v3/blob/258d960ae3caa3ad989f60d5e656544c35006d0a/Microsoft.Azure.Cosmos/tests/Microsoft.Azure.Cosmos.Tests/CosmosClientTests.cs#L34 + private const string ConnectionString = "AccountEndpoint=https://localtestcosmos.documents.azure.com:443/;AccountKey=425Mcv8CXQqzRNCgFNjIhT424GK99CKJvASowTnq15Vt8LeahXTcN5wt3342vQ==;"; + + protected override IHealthChecksBuilder AddHealthCheck(IHealthChecksBuilder builder, Func? clientFactory = null, Func? optionsFactory = null, string? healthCheckName = null, HealthStatus? failureStatus = null, IEnumerable? tags = null, TimeSpan? timeout = null) + => builder.AddAzureCosmosDB(clientFactory, optionsFactory, healthCheckName, failureStatus, tags, timeout); + + protected override CosmosClient CreateClientForNonExistingEndpoint() + => new(ConnectionString); + + protected override AzureCosmosDbHealthCheck CreateHealthCheck(CosmosClient client, AzureCosmosDbHealthCheckOptions? options) + => new(client, options); + + protected override AzureCosmosDbHealthCheckOptions CreateHealthCheckOptions() + => new(); +} diff --git a/test/HealthChecks.CosmosDb.Tests/CosmosDbHealthCheckTests.cs b/test/HealthChecks.CosmosDb.Tests/CosmosDbHealthCheckTests.cs index f71e4b25d4..e16facfbd2 100644 --- a/test/HealthChecks.CosmosDb.Tests/CosmosDbHealthCheckTests.cs +++ b/test/HealthChecks.CosmosDb.Tests/CosmosDbHealthCheckTests.cs @@ -15,16 +15,16 @@ public class cosmosdbhealthcheck_should private readonly CosmosClient _cosmosClient; private readonly Database _database; private readonly IReadOnlyDictionary _containers; - private readonly CosmosDbHealthCheckOptions _options; - private readonly CosmosDbHealthCheck _healthCheck; + private readonly AzureCosmosDbHealthCheckOptions _options; + private readonly AzureCosmosDbHealthCheck _healthCheck; private readonly HealthCheckContext _context; public cosmosdbhealthcheck_should() { _cosmosClient = Substitute.For(); _database = Substitute.For(); - _options = new CosmosDbHealthCheckOptions(); - _healthCheck = new CosmosDbHealthCheck(_cosmosClient, _options); + _options = new AzureCosmosDbHealthCheckOptions(); + _healthCheck = new AzureCosmosDbHealthCheck(_cosmosClient, _options); _context = new HealthCheckContext { Registration = new HealthCheckRegistration(HealthCheckName, _healthCheck, HealthStatus.Unhealthy, null) @@ -296,7 +296,7 @@ public async Task return_unhealthy_when_invoked_from_healthcheckservice() .AddSingleton(_cosmosClient) .AddLogging() .AddHealthChecks() - .AddCosmosDb(o => o.DatabaseId = DatabaseId, name: HealthCheckName) + .AddAzureCosmosDB(optionsFactory: _ => new AzureCosmosDbHealthCheckOptions() { DatabaseId = DatabaseId }, healthCheckName: HealthCheckName) .Services .BuildServiceProvider(); diff --git a/test/HealthChecks.CosmosDb.Tests/DependencyInjection/AzureTableStorageRegistrationTests.cs b/test/HealthChecks.CosmosDb.Tests/DependencyInjection/AzureTableStorageRegistrationTests.cs deleted file mode 100644 index f5c9f21783..0000000000 --- a/test/HealthChecks.CosmosDb.Tests/DependencyInjection/AzureTableStorageRegistrationTests.cs +++ /dev/null @@ -1,151 +0,0 @@ -using Azure.Core; -using Azure.Data.Tables; -using HealthChecks.CosmosDb; -using NSubstitute; - -namespace HealthChecks.AzureStorage.Tests.DependencyInjection; - -public class azuretablestorage_registration_should -{ - [Theory] - [InlineData(null, null, null)] - [InlineData("tableName", null, null)] - [InlineData(null, "my-azuretable-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("tableName", "my-azuretable-group", HealthStatus.Degraded)] - public void add_health_check_when_properly_configured(string? tableName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddAzureTable( - $"AccountName=unit-test;AccountKey={Convert.ToBase64String(new byte[] { 1, 2, 3, 4, 5 })}", - tableName: tableName!, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azuretable"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("tableName", null, null)] - [InlineData(null, "my-azuretable-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("tableName", "my-azuretable-group", HealthStatus.Degraded)] - public void add_health_check_with_uri_when_properly_configured(string? tableName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddAzureTable( - new Uri("https://unit-test.table.core.windows.net"), - Substitute.For(), - tableName: tableName!, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azuretable"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("tableName", null, null)] - [InlineData(null, "my-azuretable-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("tableName", "my-azuretable-group", HealthStatus.Degraded)] - public void add_health_check_with_uri_and_shared_key_credential_when_properly_configured(string? tableName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddAzureTable( - new Uri("https://unit-test.table.core.windows.net"), - Substitute.For("unit-test", Convert.ToBase64String(new byte[] { 1, 2, 3, 4, 5 })), - tableName: tableName!, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azuretable"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("tableName", null, null)] - [InlineData(null, "my-azuretable-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("tableName", "my-azuretable-group", HealthStatus.Degraded)] - public void add_health_check_with_client_from_service_provider(string? tableName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddSingleton(Substitute.For()) - .AddHealthChecks() - .AddAzureTable( - o => o.TableName = tableName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azuretable"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("tableName", null, null)] - [InlineData(null, "my-azuretable-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("tableName", "my-azuretable-group", HealthStatus.Degraded)] - public void add_health_check_with_client_from_service_provider_and_advanced_delegate(string? tableName, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddSingleton(Substitute.For()) - .AddHealthChecks() - .AddAzureTable( - (sp, o) => o.TableName = tableName, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "azuretable"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } -} diff --git a/test/HealthChecks.CosmosDb.Tests/DependencyInjection/CosmosDbRegistrationTests.cs b/test/HealthChecks.CosmosDb.Tests/DependencyInjection/CosmosDbRegistrationTests.cs deleted file mode 100644 index 829a07569d..0000000000 --- a/test/HealthChecks.CosmosDb.Tests/DependencyInjection/CosmosDbRegistrationTests.cs +++ /dev/null @@ -1,284 +0,0 @@ -using Azure.Core; -using Microsoft.Azure.Cosmos; -using NSubstitute; - -namespace HealthChecks.CosmosDb.Tests.DependencyInjection; - -public class cosmosdb_registration_should -{ - [Theory] - [InlineData(null, null, null)] - [InlineData("cosmosdb", null, null)] - [InlineData(null, "my-cosmosdb-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("cosmosdb", "my-azureblob-group", HealthStatus.Degraded)] - public void add_health_check_when_properly_configured(string? databaseId, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddCosmosDb( - $"AccountEndpoint=https://unit-test.documents.azure.com:443/;AccountKey={Convert.ToBase64String(new byte[] { 1, 2, 3, 4, 5 })}", - database: databaseId, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "cosmosdb"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("cosmosdb", null, null)] - [InlineData(null, "my-cosmosdb-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData("cosmosdb", "my-azureblob-group", HealthStatus.Degraded)] - public void add_health_check_with_endpoint_when_properly_configured(string? databaseId, string? registrationName, HealthStatus? failureStatus) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddCosmosDb( - "https://unit-test.documents.azure.com:443/", - Substitute.For(), - database: databaseId, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "cosmosdb"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null)] - [InlineData("my-cosmosdb-group", null)] - [InlineData(null, HealthStatus.Degraded)] - [InlineData("my-azureblob-group", HealthStatus.Degraded)] - public void add_health_check_with_client_as_parameter(string? registrationName, HealthStatus? failureStatus) - { - var client = Substitute.For(); - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddCosmosDb(client, name: registrationName, failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "cosmosdb"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("cosmosdb", null, null)] - [InlineData(null, "my-cosmosdb-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData(null, null, null, "first-collection", "second_collections")] - [InlineData("cosmosdb", "my-azureblob-group", HealthStatus.Degraded, "first-collection", "second_collections")] - public void add_health_check_with_client_as_parameter_and_single_parameter_delegate(string? databaseId, string? registrationName, HealthStatus? failureStatus, params string[] containerIds) - { - var client = Substitute.For(); - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddCosmosDb( - client, - o => - { - o.ContainerIds = containerIds; - o.DatabaseId = databaseId; - }, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "cosmosdb"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("cosmosdb", null, null)] - [InlineData(null, "my-cosmosdb-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData(null, null, null, "first-collection", "second_collections")] - [InlineData("cosmosdb", "my-azureblob-group", HealthStatus.Degraded, "first-collection", "second_collections")] - public void add_health_check_with_client_as_parameter_and_double_parameter_delegate(string? databaseId, string? registrationName, HealthStatus? failureStatus, params string[] containerIds) - { - var client = Substitute.For(); - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddCosmosDb( - client, - (sp, o) => - { - o.ContainerIds = containerIds; - o.DatabaseId = databaseId; - }, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "cosmosdb"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("cosmosdb", null, null)] - [InlineData(null, "my-cosmosdb-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData(null, null, null, "first-collection", "second_collections")] - [InlineData("cosmosdb", "my-azureblob-group", HealthStatus.Degraded, "first-collection", "second_collections")] - public void add_health_check_with_client_from_service_provider(string? databaseId, string? registrationName, HealthStatus? failureStatus, params string[] containerIds) - { - using var serviceProvider = new ServiceCollection() - .AddSingleton(Substitute.For()) - .AddHealthChecks() - .AddCosmosDb( - o => - { - o.ContainerIds = containerIds; - o.DatabaseId = databaseId; - }, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "cosmosdb"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("cosmosdb", null, null)] - [InlineData(null, "my-cosmosdb-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData(null, null, null, "first-collection", "second_collections")] - [InlineData("cosmosdb", "my-azureblob-group", HealthStatus.Degraded, "first-collection", "second_collections")] - public void add_health_check_with_client_from_service_provider_and_advanced_delegate(string? databaseId, string? registrationName, HealthStatus? failureStatus, params string[] containerIds) - { - using var serviceProvider = new ServiceCollection() - .AddSingleton(Substitute.For()) - .AddHealthChecks() - .AddCosmosDb( - (sp, o) => - { - o.ContainerIds = containerIds; - o.DatabaseId = databaseId; - }, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "cosmosdb"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("cosmosdb", null, null)] - [InlineData(null, "my-cosmosdb-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData(null, null, null, "first-collection", "second_collections")] - [InlineData("cosmosdb", "my-azureblob-group", HealthStatus.Degraded, "first-collection", "second_collections")] - public void add_collection_health_check_when_properly_configured(string? databaseId, string? registrationName, HealthStatus? failureStatus, params string[] containerIds) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddCosmosDbCollection( - $"AccountEndpoint=https://unit-test.documents.azure.com:443/;AccountKey={Convert.ToBase64String(new byte[] { 1, 2, 3, 4, 5 })}", - database: databaseId, - collections: containerIds, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "cosmosdb"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } - - [Theory] - [InlineData(null, null, null)] - [InlineData("cosmosdb", null, null)] - [InlineData(null, "my-cosmosdb-group", null)] - [InlineData(null, null, HealthStatus.Degraded)] - [InlineData(null, null, null, "first-collection", "second_collections")] - [InlineData("cosmosdb", "my-azureblob-group", HealthStatus.Degraded, "first-collection", "second_collections")] - public void add_collection_health_check_with_endpoint_when_properly_configured(string? databaseId, string? registrationName, HealthStatus? failureStatus, params string[] containerIds) - { - using var serviceProvider = new ServiceCollection() - .AddHealthChecks() - .AddCosmosDbCollection( - "https://unit-test.blob.core.windows.net", - Substitute.For(), - database: databaseId, - collections: containerIds, - name: registrationName, - failureStatus: failureStatus) - .Services - .BuildServiceProvider(); - - var options = serviceProvider.GetRequiredService>(); - - var registration = options.Value.Registrations.First(); - var check = registration.Factory(serviceProvider); - - registration.Name.ShouldBe(registrationName ?? "cosmosdb"); - registration.FailureStatus.ShouldBe(failureStatus ?? HealthStatus.Unhealthy); - check.ShouldBeOfType(); - } -} diff --git a/test/HealthChecks.CosmosDb.Tests/HealthChecks.CosmosDb.approved.txt b/test/HealthChecks.CosmosDb.Tests/HealthChecks.CosmosDb.approved.txt index fb538e16cb..a2e98ea3ce 100644 --- a/test/HealthChecks.CosmosDb.Tests/HealthChecks.CosmosDb.approved.txt +++ b/test/HealthChecks.CosmosDb.Tests/HealthChecks.CosmosDb.approved.txt @@ -1,53 +1,21 @@ namespace HealthChecks.CosmosDb { - public class CosmosDbHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck + public sealed class AzureCosmosDbHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck { - public CosmosDbHealthCheck(Microsoft.Azure.Cosmos.CosmosClient cosmosClient) { } - public CosmosDbHealthCheck(string connectionString) { } - public CosmosDbHealthCheck(Microsoft.Azure.Cosmos.CosmosClient cosmosClient, HealthChecks.CosmosDb.CosmosDbHealthCheckOptions options) { } - public CosmosDbHealthCheck(string connectionString, string database) { } - public CosmosDbHealthCheck(string accountEndpoint, Azure.Core.TokenCredential tokenCredential, string database) { } - public CosmosDbHealthCheck(string connectionString, string? database, System.Collections.Generic.IEnumerable? containers) { } - public CosmosDbHealthCheck(string accountEndpoint, Azure.Core.TokenCredential tokenCredential, string? database, System.Collections.Generic.IEnumerable? containers) { } + public AzureCosmosDbHealthCheck(Microsoft.Azure.Cosmos.CosmosClient cosmosClient, HealthChecks.CosmosDb.AzureCosmosDbHealthCheckOptions? options) { } public System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { } } - public sealed class CosmosDbHealthCheckOptions + public sealed class AzureCosmosDbHealthCheckOptions { - public CosmosDbHealthCheckOptions() { } + public AzureCosmosDbHealthCheckOptions() { } public System.Collections.Generic.IEnumerable? ContainerIds { get; set; } public string? DatabaseId { get; set; } } - public class TableServiceHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck - { - public TableServiceHealthCheck(Azure.Data.Tables.TableServiceClient tableServiceClient, HealthChecks.CosmosDb.TableServiceHealthCheckOptions options) { } - public TableServiceHealthCheck(string connectionString, string? tableName) { } - public TableServiceHealthCheck(System.Uri endpoint, Azure.Core.TokenCredential tokenCredential, string? tableName) { } - public TableServiceHealthCheck(System.Uri endpoint, Azure.Data.Tables.TableSharedKeyCredential credentials, string? tableName) { } - public System.Threading.Tasks.Task CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { } - } - public sealed class TableServiceHealthCheckOptions - { - public TableServiceHealthCheckOptions() { } - public string? TableName { get; set; } - } } namespace Microsoft.Extensions.DependencyInjection { public static class CosmosDbHealthCheckBuilderExtensions { - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureTable(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Action? configureOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureTable(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Action? configureOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureTable(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string connectionString, string tableName, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureTable(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Uri endpoint, Azure.Core.TokenCredential tokenCredential, string tableName, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureTable(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Uri endpoint, Azure.Data.Tables.TableSharedKeyCredential credentials, string? tableName, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddCosmosDb(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, Microsoft.Azure.Cosmos.CosmosClient client, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddCosmosDb(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Action? configureOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddCosmosDb(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Action? configureOptions = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddCosmosDb(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, Microsoft.Azure.Cosmos.CosmosClient client, System.Action configureOptions, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddCosmosDb(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, Microsoft.Azure.Cosmos.CosmosClient client, System.Action configureOptions, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddCosmosDb(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string connectionString, string? database = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddCosmosDb(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string accountEndpoint, Azure.Core.TokenCredential tokenCredential, string? database = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddCosmosDbCollection(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string connectionString, string? database = null, System.Collections.Generic.IEnumerable? collections = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } - public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddCosmosDbCollection(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, string accountEndpoint, Azure.Core.TokenCredential tokenCredential, string? database = null, System.Collections.Generic.IEnumerable? collections = null, string? name = null, Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } + public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureCosmosDB(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func? clientFactory = null, System.Func? optionsFactory = null, string? healthCheckName = "azure_cosmosdb", Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable? tags = null, System.TimeSpan? timeout = default) { } } } \ No newline at end of file diff --git a/test/_SHARED/ConformanceTests.cs b/test/_SHARED/ConformanceTests.cs new file mode 100644 index 0000000000..2b529d466f --- /dev/null +++ b/test/_SHARED/ConformanceTests.cs @@ -0,0 +1,139 @@ +using System.Net; + +public abstract class ConformanceTests + where TClient : class + where THealthCheck : IHealthCheck + where THealthCheckOptions : class +{ + protected abstract TClient CreateClientForNonExistingEndpoint(); + + protected abstract THealthCheckOptions CreateHealthCheckOptions(); + + protected abstract THealthCheck CreateHealthCheck(TClient client, THealthCheckOptions? options); + + protected abstract IHealthChecksBuilder AddHealthCheck( + IHealthChecksBuilder builder, + Func? clientFactory = default, + Func? optionsFactory = default, + string? healthCheckName = default, + HealthStatus? failureStatus = default, + IEnumerable? tags = default, + TimeSpan? timeout = default); + + [Fact] + public void HealthCheckTypeIsSealed() => Assert.True(typeof(THealthCheck).IsSealed); + + [Fact] + public void OptionsTypeIsSealed() => Assert.True(typeof(THealthCheckOptions).IsSealed); + + [Fact] + public void CtorThrowsArgumentNullExceptionForNullClient() + { + ArgumentNullException argumentNullException = Assert.ThrowsAny( + () => CreateHealthCheck(client: null!, options: CreateHealthCheckOptions())); + + Assert.False(string.IsNullOrEmpty(argumentNullException.ParamName)); + } + + [Fact] + public void CtorAcceptsNullOptions() + { + TClient client = CreateClientForNonExistingEndpoint(); + + Assert.NotNull(client); + + CreateHealthCheck(client: client, options: null!); + } + + [Theory] + [InlineData(HealthStatus.Unhealthy, true)] + [InlineData(HealthStatus.Unhealthy, false)] + [InlineData(HealthStatus.Degraded, true)] + [InlineData(HealthStatus.Degraded, false)] + public async Task ReturnsProvidedFailureStatusWhenConnectionCanNotBeMade(HealthStatus failureStatus, bool useDiExtension) + { + var webHostBuilder = new WebHostBuilder() + .ConfigureServices(services => + { + if (useDiExtension) + { + services.AddSingleton(sp => CreateClientForNonExistingEndpoint()); + AddHealthCheck(builder: services.AddHealthChecks(), failureStatus: failureStatus); + } + else + { + TClient client = CreateClientForNonExistingEndpoint(); + + services.AddHealthChecks() + .Add(new HealthCheckRegistration( + name: "name", + instance: CreateHealthCheck(client, null), + failureStatus: failureStatus, + tags: null)); + } + }) + .Configure(app => + { + app.UseHealthChecks("/health", new HealthCheckOptions + { + Predicate = _ => true, + }); + }); + + using TestServer server = new(webHostBuilder); + + using var response = await server.CreateRequest("/health").GetAsync().ConfigureAwait(false); + + response.StatusCode.ShouldBe(failureStatus == HealthStatus.Unhealthy ? HttpStatusCode.ServiceUnavailable : HttpStatusCode.OK); + } + + [Theory] + [InlineData(HealthStatus.Unhealthy)] + [InlineData(HealthStatus.Healthy)] + public async Task DependencyInjectionRegistrationWorksAsExpected(HealthStatus failureStatus) + { + const string healthCheckName = "random_name"; + var timeout = TimeSpan.FromSeconds(5); + string[] tags = { "a", "b", "c" }; + int counter = 0; + + ServiceCollection services = new(); + + services.AddSingleton(_ => + { + counter++; + + return CreateClientForNonExistingEndpoint(); + }); + + AddHealthCheck(builder: services.AddHealthChecks(), + healthCheckName: healthCheckName, + failureStatus: failureStatus, + tags: tags, + timeout: timeout); + + await using ServiceProvider serviceProvider = services.BuildServiceProvider(); + IOptions options = serviceProvider.GetRequiredService>(); + + HealthCheckRegistration registration = options.Value.Registrations.Single(); + + counter.ShouldBe(0); + + IHealthCheck check = registration.Factory(serviceProvider); + check.ShouldBeOfType(); + + counter.ShouldBe(1); + + registration.Name.ShouldBe(healthCheckName); + registration.FailureStatus.ShouldBe(failureStatus); + registration.Tags.ToArray().ShouldBeEquivalentTo(tags); + registration.Timeout.ShouldBe(timeout); + + for (int i = 0; i < 10; i++) + { + registration.Factory(serviceProvider); + } + + counter.ShouldBe(1); + } +}