Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Refactor probes and add more health checks #1159

Merged
merged 55 commits into from
Oct 8, 2024

Conversation

oskogstad
Copy link
Collaborator

@oskogstad oskogstad commented Sep 18, 2024

  • Adds health check for Redis, PosgreSQL and the wellknown-endpoints.
  • Ensures that we have different endpoints for readiness/liveness/startup/health

Related to #292

image

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Added health check capabilities for Redis, PostgreSQL, and well-known endpoints.
    • Introduced multiple health check endpoints: /startup, /liveness, /readiness, and /health.
    • Integrated health checks into the service collection for better monitoring.
    • Added a new project for utility functions related to health checks.
  • Enhancements

    • Improved health monitoring with a new HTTP client and health check configurations, including a self-check feature.
    • Added support for dynamic configuration of health check probes in deployment templates.
    • Updated API specifications to reflect new health check schemas and structures.
  • Bug Fixes

    • Enhanced error handling for health checks to provide clearer feedback on endpoint status.

Copy link
Contributor

coderabbitai bot commented Sep 18, 2024

📝 Walkthrough

Walkthrough

The pull request introduces several enhancements to the health check functionalities within the application. A new project for Digdir.Library.Utils.AspNet is added, along with multiple package references to support health checks for Redis and PostgreSQL. New health check classes are implemented for Redis and well-known endpoints, and the infrastructure is updated to integrate these health checks. Additionally, the application's Program.cs file is modified to define multiple health check endpoints, improving the monitoring capabilities of the application.

Changes

Files Change Summary
src/Digdir.Domain.Dialogporten.sln Added new project entry for Digdir.Library.Utils.AspNet with its GUID and path.
src/Digdir.Domain.Dialogporten.Infrastructure/Digdir.Domain.Dialogporten.Infrastructure.csproj Added package references for AspNetCore.HealthChecks.NpgSql (v8.0.2), AspNetCore.HealthChecks.Redis (v8.0.1), AspNetCore.HealthChecks.UI.Client (v8.0.1), Microsoft.Extensions.DependencyInjection (v8.0.0), Microsoft.Extensions.Diagnostics.HealthChecks (v8.0.0), and Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore (v8.0.0).
src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/RedisHealthCheck.cs Added RedisHealthCheck class implementing IHealthCheck, with a method CheckHealthAsync for checking Redis database connection health.
src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/WellKnownHealthChecks.cs Introduced WellKnownEndpointsHealthCheck class implementing IHealthCheck, with a method CheckHealthAsync for checking well-known endpoints from configuration.
src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs Enhanced AddInfrastructure method to include a new HTTP client and health checks for Redis, PostgreSQL, and well-known endpoints.
src/Digdir.Domain.Dialogporten.WebApi/Program.cs Modified health check configuration to include a self-check and defined multiple health check endpoints: /startup, /liveness, /readiness, and /health.
src/Digdir.Domain.Dialogporten.WebApi/Digdir.Domain.Dialogporten.WebApi.csproj Added project reference to Digdir.Library.Utils.AspNet.
src/Digdir.Library.Utils.AspNet/Digdir.Library.Utils.AspNet.csproj Created new project file with package references for Microsoft.Extensions.Http (v8.0.0) and AspNetCore.HealthChecks.UI.Client (v8.0.1).
src/Digdir.Library.Utils.AspNet/AspNetUtilitiesExtensions.cs Introduced AspNetUtilitiesExtensions class with methods for configuring health checks and mapping endpoints.
src/Digdir.Library.Utils.AspNet/HealthChecks/EndpointsHealthCheck.cs Added EndpointsHealthCheck class implementing IHealthCheck for checking a list of endpoints with a method CheckHealthAsync.
docs/schema/V1/swagger.verified.json Updated OpenAPI specification with new schemas: ActorType_Values, AttachmentUrlConsumerType_Values, DialogActivityType_Values, AuthorizedPartyDto, ContentValueDto, CreateDialogActivityRequest, CreateDialogCommand, CreateDialogContentDto, CreateDialogTransmissionDto, and UpdateDialogDto.
.azure/applications/web-api-eu/main.bicep Added new variables for health probes in the Bicep template.
.azure/applications/web-api-so/main.bicep Added new variables for health probes in the Bicep template.
.azure/modules/containerApp/main.bicep Introduced a new parameter probes for dynamic health check configurations in the container app resource.

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 353138e and de44087.

📒 Files selected for processing (1)
  • src/Digdir.Library.Utils.AspNet/HealthChecks/EndpointsHealthCheck.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Digdir.Library.Utils.AspNet/HealthChecks/EndpointsHealthCheck.cs

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@oskogstad oskogstad changed the title chore: Add health checks for Redis and PostgreSQL [DRAFT] chore: Add health checks for Redis and PostgreSQL Sep 18, 2024
@arealmaas arealmaas changed the title [DRAFT] chore: Add health checks for Redis and PostgreSQL chore: Add health checks for Redis and PostgreSQL Sep 20, 2024
@arealmaas arealmaas changed the title chore: Add health checks for Redis and PostgreSQL chore: Refactor probes and add more health checks Sep 20, 2024
@arealmaas arealmaas marked this pull request as ready for review September 20, 2024 17:13
@arealmaas arealmaas requested a review from a team as a code owner September 20, 2024 17:13
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between c2559d8 and a275c12.

Files selected for processing (4)
  • src/Digdir.Domain.Dialogporten.Infrastructure/Digdir.Domain.Dialogporten.Infrastructure.csproj (1 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/WellKnownHealthChecks.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.WebApi/Program.cs (3 hunks)
Additional comments not posted (9)
src/Digdir.Domain.Dialogporten.Infrastructure/Digdir.Domain.Dialogporten.Infrastructure.csproj (4)

4-4: LGTM!

The AspNetCore.HealthChecks.NpgSql package reference is a good addition for implementing health checks with PostgreSQL database. The version 8.0.2 is a stable release.


5-5: LGTM!

The AspNetCore.HealthChecks.Redis package reference is a good addition for implementing health checks with Redis cache. The version 8.0.1 is a stable release.


7-7: LGTM!

The AspNetCore.HealthChecks.UI.Client package reference is a good addition for integrating with the health checks UI. The version 8.0.1 is a stable release.


13-13: LGTM!

The Microsoft.Extensions.DependencyInjection package reference is a good addition for dependency injection, which is typically used for registering health checks. The version 8.0.0 is a stable release.

src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs (3)

187-188: LGTM!

Adding a dedicated HTTP client for health checks is a good practice to isolate health check traffic from the application's main HTTP traffic. The handler lifetime of 10 seconds is reasonable for managing resources efficiently.


190-205: Comprehensive health checks added.

The addition of health checks for Redis, PostgreSQL, and well-known endpoints enhances the monitoring capabilities of the application. The configuration of each health check with a name, failure status, and tags is well-structured and allows for granular monitoring.

Using the Unhealthy failure status for all health checks is appropriate to indicate a critical issue when a health check fails. The tags "dependencies" and "auth" enable filtering and categorization of health check results.


33-37: Required using statements added.

The addition of the using statements for health check-related namespaces is necessary for the implementation of health checks. They import the required types and namespaces for configuring health checks in the InfrastructureExtensions class.

src/Digdir.Domain.Dialogporten.WebApi/Program.cs (2)

135-136: Correctly adding health checks service and self-check.

The health checks service is properly configured, and the self-check with the tag "self" is appropriately added.


211-215: Appropriate configuration of liveness endpoint.

The /liveness endpoint is correctly mapped to the "self" health check, which is suitable for liveness probes.

arealmaas and others added 4 commits September 20, 2024 19:19
…lKnownHealthChecks.cs

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
…lKnownHealthChecks.cs

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

Commits

Files that changed from the base of the PR and between a275c12 and 02c13b0.

Files selected for processing (3)
  • src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/WellKnownHealthChecks.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs (2 hunks)
  • src/Digdir.Domain.Dialogporten.WebApi/Program.cs (3 hunks)
Additional comments not posted (5)
src/Digdir.Domain.Dialogporten.WebApi/Program.cs (3)

135-136: Self health check registration is correct.

The 'self' health check is properly registered with the tag "self", which is used by the /liveness endpoint. This ensures that the liveness probe can correctly assess the application's basic health.


206-210: Dependency health checks are appropriately configured for startup.

The /startup endpoint is configured to report health checks tagged with "dependencies". Assuming that your critical dependencies (e.g., Redis, PostgreSQL) are registered with this tag elsewhere (e.g., in InfrastructureExtensions.cs), this setup will help in verifying that all essential services are running during application startup.


216-220: Verify registration of critical health checks for readiness probe.

The /readiness endpoint reports health checks tagged with "critical". Please ensure that all critical health checks are registered with the "critical" tag so that the readiness probe accurately reflects the application's ability to handle requests.

Run the following script to confirm the registration of health checks with the 'critical' tag:

src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs (2)

194-209: Health checks are well-configured and enhance monitoring capabilities.

The addition of health checks for Redis, PostgreSQL, and Well-Known Endpoints enhances the application's monitoring and reliability. The configurations use appropriate failure statuses and tags, which aids in categorizing and responding to issues effectively.


187-192: Verify the usage of HealthCheckClient in the codebase.

Ensure that the "HealthCheckClient" is being utilized appropriately within your health checks or elsewhere in the application. If it is not used, it might be unnecessary to configure this HttpClient.

Run the following script to search for usages of "HealthCheckClient":

Verification successful

HealthCheckClient is appropriately utilized within the HealthChecks.

  • Referenced in src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/WellKnownHealthChecks.cs
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for usages of 'HealthCheckClient' in the codebase.

# Test: Find all occurrences of 'HealthCheckClient'.
# Expect: References where 'HealthCheckClient' is used.

rg 'HealthCheckClient'

Length of output: 307

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between edb9f93 and e9322f1.

📒 Files selected for processing (1)
  • src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/WellKnownHealthChecks.cs (1 hunks)
🔇 Additional comments (4)
src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/WellKnownHealthChecks.cs (4)

22-24: Constructor arguments are properly validated

The constructor correctly checks for null arguments and assigns the dependencies.


31-34: Filter out null or empty URLs from the endpoints list


42-42: Ensure the HttpClient is configured with appropriate timeouts


57-66: Aggregate exceptions to check all endpoints before determining health status

@arealmaas arealmaas requested a review from a team as a code owner October 1, 2024 15:17
Copy link
Collaborator

@MagnusSandgren MagnusSandgren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vi bommer på ansvarsnivå i de forskjellige prosjektene IMAO. Burde kna litt mer

@arealmaas
Copy link
Collaborator

Konge 👍

Copy link
Collaborator

@MagnusSandgren MagnusSandgren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solution fila kjenner ikke til det nye prosjektet ditt. Husk på å committe solution fila også 🙂

src/Digdir.Domain.Dialogporten.WebApi/Program.cs Outdated Show resolved Hide resolved
src/Digdir.Domain.Dialogporten.WebApi/Program.cs Outdated Show resolved Hide resolved
src/Digdir.Library.Utils.AspNet/HealthCheckExtensions.cs Outdated Show resolved Hide resolved
src/Digdir.Library.Utils.AspNet/HealthCheckExtensions.cs Outdated Show resolved Hide resolved
src/Digdir.Library.Utils.AspNet/HealthCheckExtensions.cs Outdated Show resolved Hide resolved
src/Digdir.Library.Utils.AspNet/HealthCheckExtensions.cs Outdated Show resolved Hide resolved
src/Digdir.Library.Utils.AspNet/HealthCheckExtensions.cs Outdated Show resolved Hide resolved
src/Digdir.Library.Utils.AspNet/HealthCheckExtensions.cs Outdated Show resolved Hide resolved
…isHealthCheck.cs

Co-authored-by: Ole Jørgen Skogstad <skogstad@softis.net>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

🧹 Outside diff range comments (3)
docs/schema/V1/swagger.verified.json (3)

Line range hint 3326-3355: Consider removing "Invalid" from OperationType enum

The OperationType enum in the Operation schema includes an "Invalid" value, which is not part of the standard RFC6902 JSON Patch operations. This might lead to confusion in API usage and implementation.

Consider removing the "Invalid" value from the enum to strictly adhere to the RFC6902 standard, which defines only Add, Remove, Replace, Move, Copy, and Test operations.

"OperationType": {
  "description": "",
  "enum": [
    "Add",
    "Remove",
    "Replace",
    "Move",
    "Copy",
    "Test",
-   "Invalid"
  ],
  "type": "string",
  "x-enumNames": [
    "Add",
    "Remove",
    "Replace",
    "Move",
    "Copy",
    "Test",
-   "Invalid"
  ]
},

Line range hint 5663-5777: Add examples for PATCH operation request body

To improve the clarity of the PATCH operation for dialogs, consider adding examples of valid JSON Patch documents in the operation description or as part of the schema definition. This will help API consumers understand how to correctly format their requests.

You could add an example like this to the request body schema:

"example": [
  { "op": "replace", "path": "/status", "value": "Completed" },
  { "op": "add", "path": "/content/summary", "value": { "MediaType": "text/plain", "Value": [{ "LanguageCode": "en", "Value": "Updated summary" }] } }
]

Line range hint 1-6463: Include rate limiting information

The API specification would benefit from including information about rate limiting. This is important for API consumers to understand usage limits and plan their integrations accordingly.

Consider adding a global description or including rate limit headers in the responses of appropriate endpoints. You could use standard headers like X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset.

Add a global description about rate limiting in the API info section:

"info": {
  "title": "Dialogporten",
  "version": "v1",
  "description": "API for Dialogporten. This API is rate limited. Please see the 'Rate Limiting' section for details."
},

And include rate limit headers in the response objects of appropriate endpoints:

"responses": {
  "200": {
    "headers": {
      "X-RateLimit-Limit": {
        "schema": { "type": "integer" },
        "description": "The number of allowed requests in the current period"
      },
      "X-RateLimit-Remaining": {
        "schema": { "type": "integer" },
        "description": "The number of remaining requests in the current period"
      },
      "X-RateLimit-Reset": {
        "schema": { "type": "integer" },
        "description": "The number of seconds left in the current period"
      }
    },
    // ... existing response definition
  }
}
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE

📥 Commits

Files that changed from the base of the PR and between 48bab84 and f1b0186.

📒 Files selected for processing (5)
  • docs/schema/V1/swagger.verified.json (1 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/RedisHealthCheck.cs (1 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs (4 hunks)
  • src/Digdir.Library.Utils.AspNet/HealthCheckExtensions.cs (1 hunks)
  • src/Digdir.Library.Utils.AspNet/HealthChecks/EndpointsHealthCheck.cs (1 hunks)
🔇 Additional comments (8)
docs/schema/V1/swagger.verified.json (1)

Line range hint 5663-5777: PATCH operation improvements approved

The PATCH operation for dialogs has been successfully enhanced to use the RFC6902 JSON Patch standard. The implementation now includes:

  1. An array of Operation objects in the request body, aligning with the JSON Patch standard.
  2. Optimistic concurrency control using the If-Match header.
  3. Clear documentation mentioning the use of RFC6902.

These changes address the concerns raised in the previous review and significantly improve the robustness and reliability of dialog updates.

src/Digdir.Library.Utils.AspNet/HealthChecks/EndpointsHealthCheck.cs (2)

11-66: Well-implemented EndpointsHealthCheck class

The EndpointsHealthCheck class effectively implements the IHealthCheck interface and correctly checks the health of specified endpoints. The use of IHttpClientFactory and proper logging enhances the robustness of the health check.


68-71: EndpointsHealthCheckOptions class is properly defined

The EndpointsHealthCheckOptions class correctly encapsulates the endpoints configuration with appropriate default initialization.

src/Digdir.Library.Utils.AspNet/HealthCheckExtensions.cs (3)

13-22: Consider moving nested classes to separate files

The classes AspNetHealthChecksOptions and JwtBearerTokenSchema are nested within the HealthCheckExtensions static class. For better code organization and maintainability, consider moving these classes to separate files. This adheres to the standard practice of having one public class per file, improving readability, and making future modifications easier.


24-27: Add null checks for method parameters to enhance robustness

The method AddAspNetHealthChecks should validate its input parameters to prevent potential ArgumentNullException if configuration or configure is null. Implementing null checks improves code safety and provides clearer error messages.

Consider applying the following changes:

 public static IServiceCollection AddAspNetHealthChecks(this IServiceCollection services, IConfiguration configuration, Action<AspNetHealthChecksOptions> configure)
 {
+    if (configuration == null) throw new ArgumentNullException(nameof(configuration));
+    if (configure == null) throw new ArgumentNullException(nameof(configure));

     var options = new AspNetHealthChecksOptions();
     configure(options);

69-71: Health check predicate uses undefined tag "critical"

The /readiness endpoint is configured to select health checks with the tag "critical", but no health checks are registered with this tag. This means the /readiness endpoint will not return any health check results.

To resolve this, you can either:

  1. Add the "critical" tag to the necessary health checks. For example, if the "Endpoints" health check is critical for readiness, update its registration:
 healthChecks.AddCheck<EndpointsHealthCheck>(
     "Endpoints",
     failureStatus: HealthStatus.Unhealthy,
-    tags: [DependenciesTag]);
+    tags: [DependenciesTag, CriticalTag]);
  1. Change the predicate to use an existing tag. If the "dependencies" tag is appropriate for readiness checks, modify the predicate:
 app.MapHealthChecks("/readiness", new HealthCheckOptions
 {
-    Predicate = check => check.Tags.Contains("critical"),
+    Predicate = check => check.Tags.Contains(DependenciesTag),
     ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
 });

Ensure that the tags used in your predicates correspond to the tags assigned during health check registration.

src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs (2)

36-37: LGTM

The added using directives for Microsoft.Extensions.Diagnostics.HealthChecks and Digdir.Domain.Dialogporten.Infrastructure.HealthChecks are appropriate and necessary for implementing health checks.


204-204: LGTM

Adding services.AddCustomHealthChecks(); correctly integrates the custom health checks into the service collection.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (3)
src/Digdir.Library.Utils.AspNet/HealthCheckExtensions.cs (3)

13-16: Consider Moving 'AspNetHealthChecksSettings' to a Separate File

To improve code organization and maintainability, consider moving the AspNetHealthChecksSettings class to its own file. This adheres to the convention of having one public class per file, enhancing readability and easing future modifications.


22-22: Define Health Check Tags as Constants

Currently, tag strings like "self", "external", "dependencies", and "critical" are hard-coded in multiple places. Defining these tag strings as constants can improve maintainability and reduce the risk of typos.

Apply this refactoring:

 public static class HealthCheckExtensions
 {
+    private const string SelfTag = "self";
+    private const string ExternalTag = "external";
+    private const string DependenciesTag = "dependencies";
+    private const string CriticalTag = "critical";

     public class AspNetHealthChecksSettings
     {

Then update the tag usages:

 healthChecks.AddCheck("self", () => HealthCheckResult.Healthy(), tags: [SelfTag]);

 healthChecks.AddCheck<EndpointsHealthCheck>(
     "Endpoints",
     failureStatus: HealthStatus.Unhealthy,
     tags: [ExternalTag]);

 // In MapAspNetHealthChecks method
 app.MapHealthChecks("/health/startup", new HealthCheckOptions
 {
-    Predicate = check => check.Tags.Contains("dependencies"),
+    Predicate = check => check.Tags.Contains(DependenciesTag),
     ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
 });

 app.MapHealthChecks("/health/liveness", new HealthCheckOptions
 {
-    Predicate = check => check.Tags.Contains("self"),
+    Predicate = check => check.Tags.Contains(SelfTag),
     ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
 });

 app.MapHealthChecks("/health/readiness", new HealthCheckOptions
 {
-    Predicate = check => check.Tags.Contains("critical"),
+    Predicate = check => check.Tags.Contains(CriticalTag),
     ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
 });

 app.MapHealthChecks("/health", new HealthCheckOptions
 {
-    Predicate = check => check.Tags.Contains("dependencies"),
+    Predicate = check => check.Tags.Contains(DependenciesTag),
     ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
 });

 app.MapHealthChecks("/health/deep", new HealthCheckOptions
 {
-    Predicate = check => check.Tags.Contains("dependencies") || check.Tags.Contains("external"),
+    Predicate = check => check.Tags.Contains(DependenciesTag) || check.Tags.Contains(ExternalTag),
     ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
 });

Also applies to: 34-34, 44-44, 49-49, 54-54, 59-59, 64-64


13-16: Add XML Documentation Comments to Public Members

To improve code clarity and assist other developers, consider adding XML documentation comments to the AspNetHealthChecksSettings class and the public methods AddAspNetHealthChecks and MapAspNetHealthChecks.

Example:

/// <summary>
/// Settings for configuring ASP.NET health checks.
/// </summary>
public class AspNetHealthChecksSettings
{
    /// <summary>
    /// A list of HTTP GET endpoints to include in the health checks.
    /// </summary>
    public List<string>? HttpGetEndpointsToCheck { get; set; }
}

/// <summary>
/// Adds ASP.NET health checks to the service collection.
/// </summary>
/// <param name="services">The service collection.</param>
/// <param name="settings">The health check settings.</param>
/// <returns>The updated service collection.</returns>
public static IServiceCollection AddAspNetHealthChecks(this IServiceCollection services, AspNetHealthChecksSettings settings)

/// <summary>
/// Maps the health check endpoints to the web application.
/// </summary>
/// <param name="app">The web application.</param>
/// <returns>The updated web application.</returns>
public static WebApplication MapAspNetHealthChecks(this WebApplication app)

Also applies to: 18-38, 40-68

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between f1b0186 and e282c76.

📒 Files selected for processing (7)
  • Digdir.Domain.Dialogporten.sln (3 hunks)
  • docs/schema/V1/swagger.verified.json (1 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/Digdir.Domain.Dialogporten.Infrastructure.csproj (1 hunks)
  • src/Digdir.Domain.Dialogporten.WebApi/Digdir.Domain.Dialogporten.WebApi.csproj (1 hunks)
  • src/Digdir.Domain.Dialogporten.WebApi/Program.cs (5 hunks)
  • src/Digdir.Library.Utils.AspNet/HealthCheckExtensions.cs (1 hunks)
  • src/Digdir.Library.Utils.AspNet/HealthChecks/EndpointsHealthCheck.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • docs/schema/V1/swagger.verified.json
  • src/Digdir.Domain.Dialogporten.Infrastructure/Digdir.Domain.Dialogporten.Infrastructure.csproj
  • src/Digdir.Domain.Dialogporten.WebApi/Digdir.Domain.Dialogporten.WebApi.csproj
  • src/Digdir.Domain.Dialogporten.WebApi/Program.cs
  • src/Digdir.Library.Utils.AspNet/HealthChecks/EndpointsHealthCheck.cs
🧰 Additional context used
🔇 Additional comments (6)
Digdir.Domain.Dialogporten.sln (4)

66-67: New project added to the solution

The new project Digdir.Library.Utils.AspNet has been correctly added to the solution. This addition aligns with the PR objective of enhancing health check capabilities, as it likely contains utility functions for ASP.NET, which could be used for implementing health checks.


158-161: Project configurations set up correctly

The Debug and Release configurations for the new Digdir.Library.Utils.AspNet project have been properly set up. This ensures that the project can be built and debugged within the solution.


191-191: Project correctly nested in solution structure

The new project has been appropriately nested under the "src" folder in the solution structure. This maintains consistency with the existing project organization.


Line range hint 66-191: Verify project references

While the addition of the new project looks correct, it's important to ensure that any necessary project references have been set up in the projects that will use the new Digdir.Library.Utils.AspNet library.

This script will help identify if any existing projects are referencing the new library. If no results are returned, you may need to add the necessary references in the projects that will use this new utility library.

src/Digdir.Library.Utils.AspNet/HealthCheckExtensions.cs (2)

54-56: ⚠️ Potential issue

Ensure Health Checks Use Defined Tags

The /health/readiness endpoint filters health checks using the "critical" tag, but no health checks are registered with this tag. This means the endpoint will not return any results.

To resolve this, consider one of the following:

  • Add the "critical" tag to relevant health checks. For example, if certain checks are critical for readiness, assign the tag when registering them.
  • Modify the predicate to use an existing tag. If the "dependencies" tag is appropriate, update the predicate accordingly.

Apply this diff if choosing the second option:

 app.MapHealthChecks("/health/readiness", new HealthCheckOptions
 {
-    Predicate = check => check.Tags.Contains(CriticalTag),
+    Predicate = check => check.Tags.Contains(DependenciesTag),
     ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
 });

Likely invalid or redundant comment.


44-44: Verify Usage of the 'dependencies' Tag

The health check endpoints /health/startup and /health use the "dependencies" tag in their predicates, but there are no health checks registered with this tag. This could result in these endpoints not returning any health check results.

Run the following script to check for health checks registered with the "dependencies" tag:

Also applies to: 59-59

src/Digdir.Library.Utils.AspNet/HealthCheckExtensions.cs Outdated Show resolved Hide resolved
src/Digdir.Library.Utils.AspNet/HealthCheckExtensions.cs Outdated Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Outside diff range and nitpick comments (3)
src/Digdir.Library.Utils.AspNet/AspNetUtilitiesSettings.cs (1)

8-11: LGTM: Well-structured settings class with a minor suggestion

The HealthCheckSettings class is well-designed:

  • It's sealed, preventing unintended inheritance.
  • The HttpGetEndpointsToCheck property is properly initialized with an empty list.
  • The use of C# 12 collection expression syntax [] is modern and concise.

Consider making the HttpGetEndpointsToCheck property init-only for immutability:

- public List<string> HttpGetEndpointsToCheck { get; set; } = [];
+ public List<string> HttpGetEndpointsToCheck { get; init; } = [];

This change would prevent the entire list from being replaced after initialization, while still allowing modifications to the list's contents.

src/Digdir.Library.Utils.AspNet/AspNetUtilitiesExtensions.cs (1)

12-15: Add XML Documentation Comments to Public Methods

Adding XML documentation comments to your public extension methods enhances code readability and provides clear guidance to other developers using this library. Including summaries, parameter descriptions, and return value explanations will improve maintainability.

Also applies to: 17-34, 36-41

src/Digdir.Library.Utils.AspNet/HealthChecks/EndpointsHealthCheck.cs (1)

27-27: Address the TODO: Resolve strong dependency on infrastructure registration

The comment on line 27 indicates a strong dependency on infrastructure registration that needs to be fixed.

Would you like assistance in refactoring this code to reduce the dependency, or should we open a GitHub issue to track this task?

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between e282c76 and 89accc8.

📒 Files selected for processing (6)
  • Digdir.Domain.Dialogporten.sln (3 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs (4 hunks)
  • src/Digdir.Domain.Dialogporten.WebApi/Program.cs (4 hunks)
  • src/Digdir.Library.Utils.AspNet/AspNetUtilitiesExtensions.cs (1 hunks)
  • src/Digdir.Library.Utils.AspNet/AspNetUtilitiesSettings.cs (1 hunks)
  • src/Digdir.Library.Utils.AspNet/HealthChecks/EndpointsHealthCheck.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs
  • src/Digdir.Domain.Dialogporten.WebApi/Program.cs
🧰 Additional context used
🔇 Additional comments (3)
src/Digdir.Library.Utils.AspNet/AspNetUtilitiesSettings.cs (1)

3-6: LGTM: Well-structured settings class

The AspNetUtilitiesSettings class is well-designed:

  • It's sealed, preventing unintended inheritance.
  • The HealthCheckSettings property is properly initialized, ensuring it's always available.
  • The class structure allows for easy extension if more settings are needed in the future.
Digdir.Domain.Dialogporten.sln (1)

66-67: LGTM: New project added to the solution

The new project Digdir.Library.Utils.AspNet has been correctly added to the solution with appropriate build configurations and nested under the "Libraries" folder. This addition aligns with the PR objectives of enhancing health check mechanisms.

To ensure the project file exists, please run the following command:

Also applies to: 158-161, 191-191

✅ Verification successful

Verification Successful: Project File Exists

The new project Digdir.Library.Utils.AspNet has been successfully added to the solution, and the project file exists at the specified path. This addition aligns with the PR objectives of enhancing health check mechanisms.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Verify the existence of the new project file
if [ -f "src/Digdir.Library.Utils.AspNet/Digdir.Library.Utils.AspNet.csproj" ]; then
    echo "Project file exists"
else
    echo "Project file does not exist"
fi

Length of output: 128

src/Digdir.Library.Utils.AspNet/HealthChecks/EndpointsHealthCheck.cs (1)

28-28: Ensure the HTTP client is properly configured and registered

The code creates an HTTP client with the name "HealthCheckClient". Make sure that this named client is registered and configured in the dependency injection container. If not, this could lead to a runtime error.

To confirm whether the client is registered, you can check the codebase using this script:

✅ Verification successful

HTTP client "HealthCheckClient" is properly registered.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that "HealthCheckClient" is registered in the codebase.

# Search for registration of the named HTTP client.
rg --type cs $'AddHttpClient("HealthCheckClient")'

Length of output: 51


Script:

#!/bin/bash
# Description: Comprehensive search for "HealthCheckClient" registration in the codebase.

# Search for any occurrence of "HealthCheckClient" related to HTTP client registrations.
rg --type cs 'AddHttpClient\s*\(\s*"HealthCheckClient"'

Length of output: 183

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (5)
docs/schema/V1/swagger.verified.json (5)

Line range hint 1-6477: Consider implementing API versioning in the base path

The current API structure uses /api/v1/ in the individual paths. While this works, consider moving the version to the base path for easier management of multiple API versions in the future. This approach allows for cleaner path definitions and simplifies version routing.

Update the servers section to include the version:

"servers": [
  {
    "url": "https://altinn-dev-api.azure-api.net/dialogporten/v1"
  }
]

Then, remove the /api/v1 prefix from all path definitions. This change will make it easier to introduce new API versions in the future without modifying all path definitions.


Line range hint 6450-6457: Enhance documentation for JWT scopes

The API uses different scopes for various operations, which is good for fine-grained access control. However, it would be beneficial to provide more detailed documentation about these scopes, their purposes, and how to obtain them.

Consider adding a detailed description of the scopes in the security scheme definition:

"securitySchemes": {
  "JWTBearerAuth": {
    "bearerFormat": "JWT",
    "description": "Enter a JWT token to authorize the requests. The following scopes are used:\n\n- digdir:dialogporten: General access to the Dialogporten API\n- digdir:dialogporten.serviceprovider: Access for service providers\n- digdir:dialogporten.serviceprovider.search: Access for service providers to search dialogs\n- altinn:system/notifications.condition.check: Access for checking notification conditions\n\nPlease refer to the documentation for details on how to obtain these scopes.",
    "scheme": "Bearer",
    "type": "http"
  }
}

This change will help API consumers understand the required scopes for different operations more easily.


Line range hint 1-6477: Enhance endpoint documentation for consistency

The endpoint definitions are well-structured, but there's an opportunity to improve consistency in documentation across all endpoints. Consider implementing the following enhancements:

  1. Ensure all endpoints have a clear summary and description.
  2. Use consistent terminology across similar endpoints.
  3. Provide examples for request bodies and responses where applicable.

Here's an example of how to enhance the documentation for the "Create Dialog" endpoint:

"/api/v1/serviceowner/dialogs": {
  "post": {
    "summary": "Create a new dialog",
    "description": "Creates a new dialog with the provided configuration. The dialog will be associated with the authenticated service owner.\n\nRequired scope: `digdir:dialogporten.serviceprovider`",
    "requestBody": {
      "content": {
        "application/json": {
          "schema": {
            "$ref": "#/components/schemas/CreateDialogCommand"
          },
          "example": {
            "serviceResource": "urn:altinn:resource:some-service-identifier",
            "party": "urn:altinn:organization:identifier-no:123456789",
            "content": {
              "title": {
                "mediaType": "text/plain",
                "value": [
                  {
                    "languageCode": "en",
                    "value": "Example Dialog Title"
                  }
                ]
              }
            }
          }
        }
      }
    },
    "responses": {
      "201": {
        "description": "Dialog created successfully",
        "content": {
          "application/json": {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "018bb8e5-d9d0-7434-8ec5-569a6c8e01fc"
          }
        }
      },
      // ... other response codes ...
    }
  }
}

Apply similar enhancements to other endpoints for improved consistency and clarity.


Line range hint 1-6477: Enhance schema documentation and consistency

The schema definitions are well-structured, but there's room for improvement in documentation and consistency. Consider implementing the following enhancements:

  1. Ensure all properties have clear descriptions.
  2. Use consistent formatting for property descriptions.
  3. Provide examples for complex objects.
  4. Use enums for properties with a fixed set of values.

Here's an example of how to enhance the documentation for the CreateDialogCommand schema:

"CreateDialogCommand": {
  "type": "object",
  "properties": {
    "serviceResource": {
      "type": "string",
      "format": "uri",
      "description": "The URN of the service resource associated with this dialog.",
      "example": "urn:altinn:resource:some-service-identifier"
    },
    "party": {
      "type": "string",
      "format": "uri",
      "description": "The URN of the party (organization or person) that the dialog belongs to.",
      "example": "urn:altinn:organization:identifier-no:123456789"
    },
    "content": {
      "$ref": "#/components/schemas/CreateDialogContentDto"
    },
    "status": {
      "type": "string",
      "enum": ["New", "InProgress", "Completed"],
      "description": "The current status of the dialog."
    },
    "dueAt": {
      "type": "string",
      "format": "date-time",
      "description": "The due date for the dialog, if applicable.",
      "example": "2023-12-31T23:59:59Z"
    }
  },
  "required": ["serviceResource", "party", "content"]
}

Apply similar enhancements to other schema definitions for improved consistency and clarity.


Line range hint 1-6477: Improve error handling and endpoint consistency

The API generally follows good practices, but there are opportunities to enhance error handling and maintain consistency across endpoints:

  1. Standardize error responses: Ensure all endpoints return consistent error structures, preferably using the Problem Details for HTTP APIs (RFC 7807) format.

  2. Use consistent query parameters: Standardize common query parameters (e.g., pagination, filtering) across all list endpoints.

  3. Implement rate limiting: Consider adding rate limiting headers to prevent API abuse.

  4. Standardize error responses by using the Problem Details format consistently:

"responses": {
  "400": {
    "description": "Bad Request",
    "content": {
      "application/problem+json": {
        "schema": {
          "$ref": "#/components/schemas/ProblemDetails"
        }
      }
    }
  }
}
  1. Implement consistent query parameters for list endpoints:
"parameters": [
  {
    "name": "page",
    "in": "query",
    "description": "Page number for pagination",
    "schema": {
      "type": "integer",
      "minimum": 1,
      "default": 1
    }
  },
  {
    "name": "pageSize",
    "in": "query",
    "description": "Number of items per page",
    "schema": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "default": 20
    }
  }
]
  1. Add rate limiting headers to the API responses:
"responses": {
  "200": {
    "description": "Successful response",
    "headers": {
      "X-RateLimit-Limit": {
        "schema": {
          "type": "integer"
        },
        "description": "The maximum number of requests you're permitted to make per hour."
      },
      "X-RateLimit-Remaining": {
        "schema": {
          "type": "integer"
        },
        "description": "The number of requests remaining in the current rate limit window."
      },
      "X-RateLimit-Reset": {
        "schema": {
          "type": "integer",
          "format": "unix-timestamp"
        },
        "description": "The time at which the current rate limit window resets in UTC epoch seconds."
      }
    }
  }
}

Implementing these suggestions will improve the overall consistency and robustness of the API.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 89accc8 and 8b8806d.

📒 Files selected for processing (4)
  • Digdir.Domain.Dialogporten.sln (3 hunks)
  • docs/schema/V1/swagger.verified.json (1 hunks)
  • src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs (4 hunks)
  • src/Digdir.Library.Utils.AspNet/HealthChecks/EndpointsHealthCheck.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Digdir.Domain.Dialogporten.Infrastructure/InfrastructureExtensions.cs
  • src/Digdir.Library.Utils.AspNet/HealthChecks/EndpointsHealthCheck.cs
🧰 Additional context used
🔇 Additional comments (2)
Digdir.Domain.Dialogporten.sln (1)

66-67: LGTM! New project added successfully.

The new project Digdir.Library.Utils.AspNet has been correctly added to the solution with appropriate build configurations and solution structure placement. This addition aligns with the PR objectives of enhancing health check mechanisms.

To ensure the project is set up correctly, please verify:

  1. The project file exists at the specified path.
  2. The project has the necessary dependencies for ASP.NET utilities.
  3. The project contains the intended health check related code.

You can use the following script to check the project file's existence and content:

Also applies to: 160-163, 197-197

✅ Verification successful

Verification Successful: Project Added Correctly

The project Digdir.Library.Utils.AspNet exists at the specified path, includes the necessary dependencies for ASP.NET utilities, and contains the intended health check code (EndpointsHealthCheck.cs).

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if the project file exists and view its content
if [ -f "src/Digdir.Library.Utils.AspNet/Digdir.Library.Utils.AspNet.csproj" ]; then
    echo "Project file exists. Content:"
    cat "src/Digdir.Library.Utils.AspNet/Digdir.Library.Utils.AspNet.csproj"
else
    echo "Project file not found at the expected location."
fi

# List files in the project directory
echo "Files in the project directory:"
ls -R "src/Digdir.Library.Utils.AspNet"

Length of output: 984

docs/schema/V1/swagger.verified.json (1)

Line range hint 1-6477: Overall assessment of the Dialogporten API specification

The Dialogporten API specification is well-structured and follows many best practices for RESTful API design. It provides a comprehensive set of endpoints for managing dialogs, activities, and transmissions. The use of JWT authentication with scopes for access control is appropriate for this type of API.

However, there are several areas where the specification could be improved:

  1. API versioning strategy could be enhanced by moving the version to the base path.
  2. Documentation for JWT scopes could be more detailed to help API consumers.
  3. Endpoint documentation could be more consistent and provide more examples.
  4. Schema definitions could benefit from more detailed property descriptions and examples.
  5. Error handling could be standardized across all endpoints using the Problem Details format.
  6. Consistency in query parameters for list endpoints could be improved.
  7. Rate limiting headers could be added to prevent API abuse.

Implementing these suggestions would result in a more robust, consistent, and developer-friendly API specification. Despite these areas for improvement, the current specification provides a solid foundation for the Dialogporten API.

Copy link

sonarqubecloud bot commented Oct 8, 2024

@arealmaas arealmaas merged commit 6889a96 into main Oct 8, 2024
22 checks passed
@arealmaas arealmaas deleted the chore/add-redis-postgres-health-checks branch October 8, 2024 14:13
oskogstad pushed a commit that referenced this pull request Oct 10, 2024
🤖 I have created a release *beep* *boop*
---


##
[1.23.0](v1.22.0...v1.23.0)
(2024-10-10)


### Features

* **infra:** upgrade postgresql SKU in test
([#1257](#1257))
([5a751af](5a751af))
* **webAPI:** Add legacy HTML support for MainContentReference
([#1256](#1256))
([482b38a](482b38a))


### Bug Fixes

* Add missing return types for Transmissions and Activities in OpenAPI
spec ([#1244](#1244))
([972870d](972870d))
* **graphQL:** Missing MediaType on dialog attachment url
([#1264](#1264))
([3919343](3919343))
* Refactor probes and add more health checks
([#1159](#1159))
([6889a96](6889a96))
* **webapi:** ensure correct health checks are used in probes
([#1249](#1249))
([f951152](f951152))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants