diff --git a/.github/workflows/markdownlint.yml b/.github/workflows/markdownlint.yml index c0232c30c7..61b52f0af0 100644 --- a/.github/workflows/markdownlint.yml +++ b/.github/workflows/markdownlint.yml @@ -25,9 +25,9 @@ jobs: steps: - uses: actions/checkout@v4 - name: Use Node.js - uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 + uses: actions/setup-node@c2ac33f2c62f978d6c944d9648125a294e56dc0b with: - node-version: 16.x + node-version: 20.x - name: Run Markdownlint run: | echo "::add-matcher::.github/workflows/markdownlint-problem-matcher.json" diff --git a/docs/fundamentals/health-checks.md b/docs/fundamentals/health-checks.md index 4aae5c36aa..0913c496b0 100644 --- a/docs/fundamentals/health-checks.md +++ b/docs/fundamentals/health-checks.md @@ -1,7 +1,7 @@ --- title: .NET Aspire health checks description: Explore .NET Aspire health checks -ms.date: 12/08/2023 +ms.date: 04/02/2024 ms.topic: quickstart --- @@ -15,7 +15,7 @@ Health checks provide availability and state information about an app. Health ch ## .NET Aspire health check endpoints -.NET Aspire exposes two default health check HTTP endpoints when the `AddServiceDefaults` and `MapDefaultEndpoints` methods are called from the _Program.cs_ file: +.NET Aspire exposes two default health check HTTP endpoints in **Development** environments when the `AddServiceDefaults` and `MapDefaultEndpoints` methods are called from the _Program.cs_ file: - The `/health` endpoint indicates if the app is running normally where it's ready to receive requests. All health checks must pass for app to be considered ready to accept traffic after starting. @@ -35,6 +35,28 @@ Health checks provide availability and state information about an app. Health ch The `AddServiceDefaults` and `MapDefaultEndpoints` methods also apply various configurations to your app beyond just health checks, such as OpenTelemetry and service discovery configurations. +### Non-development environments + +In non-development environments, the `/health` and `/alive` endpoints are disabled by default. If you need to enable them, its recommended to protect these endpoints with various routing features, such as host filtering and/or authorization. For more information, see [Health checks in ASP.NET Core](/aspnet/core/host-and-deploy/health-checks#use-health-checks-routing). + +Additionally, it may advantageous to configure request timeouts and output caching for these endpoints to prevent abuse or denial-of-service attacks. To do so, consider the following modified `AddDefaultHealthChecks` method: + +:::code language="csharp" source="snippets/healthz/Healthz.ServiceDefaults/Extensions.cs" id="healthchecks"::: + +The preceding code: + +- Adds a timeout of 5 seconds to the health check requests with a policy named `HealthChecks`. +- Adds a 10-second cache to the health check responses with a policy named `HealthChecks`. + +Now consider the updated `MapDefaultEndpoints` method: + +:::code language="csharp" source="snippets/healthz/Healthz.ServiceDefaults/Extensions.cs" id="mapendpoints"::: + +The preceding code: + +- Groups the health check endpoints under the `/` path. +- Caches the output and specifies a request time with the corresponding `HealthChecks` policy. + ## Component health checks .NET Aspire components can also register additional health checks for your app. These health checks contribute to the returned status of the `/health` and `/alive` endpoints. For example, the .NET Aspire PostgreSQL component automatically adds a health check to verify the following conditions: diff --git a/docs/fundamentals/snippets/healthz/Healthz.ServiceDefaults/Extensions.cs b/docs/fundamentals/snippets/healthz/Healthz.ServiceDefaults/Extensions.cs new file mode 100644 index 0000000000..e79e751e95 --- /dev/null +++ b/docs/fundamentals/snippets/healthz/Healthz.ServiceDefaults/Extensions.cs @@ -0,0 +1,59 @@ +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; + +namespace Microsoft.Extensions.Hosting; + +public static class Extensions +{ + public static IHostApplicationBuilder AddServiceDefaults(this IHostApplicationBuilder builder) + { + builder.AddDefaultHealthChecks(); + + return builder; + } + + // + public static IHostApplicationBuilder AddDefaultHealthChecks(this IHostApplicationBuilder builder) + { + builder.Services.AddRequestTimeouts( + configure: static timeouts => + timeouts.AddPolicy("HealthChecks", TimeSpan.FromSeconds(5))); + + builder.Services.AddOutputCache( + configureOptions: static caching => + caching.AddPolicy("HealthChecks", + build: static policy => policy.Expire(TimeSpan.FromSeconds(10)))); + + builder.Services.AddHealthChecks() + // Add a default liveness check to ensure app is responsive + .AddCheck("self", () => HealthCheckResult.Healthy(), ["live"]); + + return builder; + } + // + + // + public static WebApplication MapDefaultEndpoints(this WebApplication app) + { + var healthChecks = app.MapGroup(""); + + healthChecks + .CacheOutput("HealthChecks") + .WithRequestTimeout("HealthChecks"); + + // All health checks must pass for app to be + // considered ready to accept traffic after starting + healthChecks.MapHealthChecks("/health"); + + // Only health checks tagged with the "live" tag + // must pass for app to be considered alive + healthChecks.MapHealthChecks("/alive", new() + { + Predicate = static r => r.Tags.Contains("live") + }); + + return app; + } + // +} diff --git a/docs/fundamentals/snippets/healthz/Healthz.ServiceDefaults/Healthz.ServiceDefaults.csproj b/docs/fundamentals/snippets/healthz/Healthz.ServiceDefaults/Healthz.ServiceDefaults.csproj new file mode 100644 index 0000000000..80f9ee917e --- /dev/null +++ b/docs/fundamentals/snippets/healthz/Healthz.ServiceDefaults/Healthz.ServiceDefaults.csproj @@ -0,0 +1,24 @@ + + + + net8.0 + enable + enable + true + + + + + + + + + + + + + + + + + diff --git a/docs/fundamentals/snippets/healthz/Healthz.ServiceDefaults/healthz.sln b/docs/fundamentals/snippets/healthz/Healthz.ServiceDefaults/healthz.sln new file mode 100644 index 0000000000..118f200ed9 --- /dev/null +++ b/docs/fundamentals/snippets/healthz/Healthz.ServiceDefaults/healthz.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.34727.303 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Healthz.ServiceDefaults", "Healthz.ServiceDefaults.csproj", "{489CF15E-6758-4CD5-80B7-DD698ED2D964}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {489CF15E-6758-4CD5-80B7-DD698ED2D964}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {489CF15E-6758-4CD5-80B7-DD698ED2D964}.Debug|Any CPU.Build.0 = Debug|Any CPU + {489CF15E-6758-4CD5-80B7-DD698ED2D964}.Release|Any CPU.ActiveCfg = Release|Any CPU + {489CF15E-6758-4CD5-80B7-DD698ED2D964}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B445EE8B-3BD1-4F13-A5BB-DE20505966D9} + EndGlobalSection +EndGlobal diff --git a/docs/whats-new/preview-5.md b/docs/whats-new/preview-5.md index dbaf88b504..cfbec57086 100644 --- a/docs/whats-new/preview-5.md +++ b/docs/whats-new/preview-5.md @@ -1,41 +1,45 @@ --- title: .NET Aspire preview 5 description: .NET Aspire preview 5 is now available and includes many improvements and new capabilities -ms.date: 03/28/2024 +ms.date: 04/02/2024 --- # .NET Aspire preview 5 Breaking Changes -- The major package split, Aspire.* and Aspire.Hosting.* + +- The major package split, Aspire.*and Aspire.Hosting.* - AppHost projects now need to reference Aspire.Hosting.AppHost - Each resource was split into individual packages - - Aspire.Hosting.Redis - - Aspire.Hosting.PostgreSQL - - Aspire.Hosting.MongoDB - - Aspire.Hosting.RabbitMQ - - etc. + - Aspire.Hosting.Redis + - Aspire.Hosting.PostgreSQL + - Aspire.Hosting.MongoDB + - Aspire.Hosting.RabbitMQ + - etc. - The same applies to the Azure resources - - Aspire.Hosting.Azure.Redis (etc) +- Aspire.Hosting.Azure.Redis (etc) - Async all the things, various callbacks in the app model APIs are now async. (GetConnectionStringAsync etc.) Dashboard -- Support for authentication + +- Support for authentication - OTLP - UI (Frontend) - LOTS of performance improvements - - Console log virtualization - - Load time improvements - - Trace ingestion improvements + - Console log virtualization + - Load time improvements + - Trace ingestion improvements - Run on a single port (OTLP and UI) - Standalone container now forces you to choose auth Templates + - HTTPs by default - Test project support AppModel + - Forwarded headers enabled by default for projects with endpoints - Custom resources support in dashboard - Can publish notifications to the dashboard @@ -47,36 +51,41 @@ AppModel - Support for composing environment variables using string interpolation that can capture resource properties. (ReferenceExpression, WithEnvironment overload) - Service Discovery + - Service discovery API changes - Service discovery auto scheme detection Tooling + - VS Code support - Prompting for parameters in Visual Studio Components + - Azure Events Hubs - Renamed all of the methods to end with *Client e.g. AddRedisClient - Nats OpenTelemetry support Azure + - Azure CDK Support (introducing the new Azure CDK) - All Azure resources were refactored to use the CDK - Azure Provisioning for Development - Azure OpenAI provisioning Manifest + - Express container volumes and bindmounts in the manifest - Support for multiple endpoints in the manifest - Renamed containerPort to targetPort - Added port as the "exposed port" Azure Deployment + - Service selection prompt gone (WithExternalHttpEndpoints in apphost) - Support for multiple endpoints in ACA - Support for adding volumes to containers in ACA - IDE protocol changes - - There's a new IDE protcol +- There's a new IDE protcol