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
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
1317e97
sup
oskogstad Sep 18, 2024
51c3515
low cse
oskogstad Sep 18, 2024
b25034e
chore: mo health checks pls
arealmaas Sep 20, 2024
42326d1
chore: even mo health checks pls
arealmaas Sep 20, 2024
a275c12
Merge branch 'main' into chore/add-redis-postgres-health-checks
arealmaas Sep 20, 2024
ddf0ce7
cleanup
arealmaas Sep 20, 2024
d58b8e4
Update src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/Wel…
arealmaas Sep 20, 2024
1cafcdf
Update src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/Wel…
arealmaas Sep 20, 2024
3996060
cleanup
arealmaas Sep 20, 2024
8889b77
cleanup
arealmaas Sep 20, 2024
02c13b0
cleanup
arealmaas Sep 23, 2024
edb9f93
Merge branch 'main' into chore/add-redis-postgres-health-checks
oskogstad Oct 1, 2024
e9322f1
Update src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/Wel…
oskogstad Oct 1, 2024
383f56a
chore: adjust health checks
arealmaas Oct 1, 2024
62bd903
chore: adjust health checks
arealmaas Oct 1, 2024
1129ce2
cleanup
arealmaas Oct 1, 2024
7ffc934
Merge branch 'main' into chore/add-redis-postgres-health-checks
arealmaas Oct 1, 2024
33e7c4e
chore(deps): update dependency htmlagilitypack to 1.11.66 (#1212)
renovate[bot] Oct 2, 2024
08e94cb
ci: ensure unique revisions for deployments (#1211)
arealmaas Oct 2, 2024
f8fe468
chore(main): release 1.20.1 (#1207)
dialogporten-bot Oct 2, 2024
ea2400b
ci: send message on release created and successfully validated (#1185)
arealmaas Oct 2, 2024
b755f0c
beginning
arealmaas Oct 2, 2024
84f0941
refactor
arealmaas Oct 3, 2024
4b8fdb6
refactor
arealmaas Oct 3, 2024
59ef954
ok
arealmaas Oct 3, 2024
2ca9fae
ok
arealmaas Oct 3, 2024
d7e3b3f
ok
arealmaas Oct 3, 2024
e41bd02
swaggah
arealmaas Oct 3, 2024
fcf6727
cleanup
arealmaas Oct 3, 2024
34ce8a8
cleanup
arealmaas Oct 3, 2024
62ced3e
cleanup
arealmaas Oct 3, 2024
3abf115
Update src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/Red…
arealmaas Oct 3, 2024
3173da9
cleanup
arealmaas Oct 3, 2024
2f267c8
cleanup
arealmaas Oct 3, 2024
48bab84
cleanup
arealmaas Oct 3, 2024
1a4dddb
cleanup
arealmaas Oct 3, 2024
296c01b
Update src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/Red…
arealmaas Oct 3, 2024
4038e3b
cleanup
arealmaas Oct 3, 2024
f5eea3a
cleanup
arealmaas Oct 3, 2024
1210864
cleanup
arealmaas Oct 3, 2024
4ba55db
Update src/Digdir.Library.Utils.AspNet/HealthChecks/EndpointsHealthCh…
arealmaas Oct 3, 2024
f1b0186
Update src/Digdir.Domain.Dialogporten.Infrastructure/HealthChecks/Red…
arealmaas Oct 4, 2024
dd80084
add to sln
arealmaas Oct 4, 2024
f6d385b
doc
arealmaas Oct 7, 2024
9792cda
Merge branch 'main' into chore/add-redis-postgres-health-checks
arealmaas Oct 7, 2024
e282c76
redo options
arealmaas Oct 7, 2024
51af7ed
cleanup
arealmaas Oct 7, 2024
776cb9d
cleanup
arealmaas Oct 7, 2024
49a3b89
cleanup
arealmaas Oct 7, 2024
89accc8
Some suggestions (#1243)
MagnusSandgren Oct 7, 2024
abcf931
parallelize
arealmaas Oct 7, 2024
284cd17
cleanup
arealmaas Oct 7, 2024
8b8806d
Merge branch 'main' into chore/add-redis-postgres-health-checks
arealmaas Oct 7, 2024
353138e
cleanup
arealmaas Oct 8, 2024
de44087
cleanup
arealmaas Oct 8, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .azure/applications/web-api-eu/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,38 @@ resource environmentKeyVaultResource 'Microsoft.KeyVault/vaults@2023-07-01' exis

var containerAppName = '${namePrefix}-webapi-eu-ca'

var port = 8080

var probes = [
{
periodSeconds: 5
initialDelaySeconds: 2
type: 'Liveness'
httpGet: {
path: '/liveness'
port: port
}
}
{
periodSeconds: 5
initialDelaySeconds: 2
type: 'Readiness'
httpGet: {
path: '/readiness'
port: port
}
}
{
periodSeconds: 5
initialDelaySeconds: 2
type: 'Startup'
httpGet: {
path: '/startup'
port: port
}
}
]

module containerApp '../../modules/containerApp/main.bicep' = {
name: containerAppName
params: {
Expand All @@ -94,6 +126,7 @@ module containerApp '../../modules/containerApp/main.bicep' = {
apimIp: apimIp
tags: tags
resources: resources
probes: probes
revisionSuffix: revisionSuffix
}
}
Expand Down
34 changes: 34 additions & 0 deletions .azure/applications/web-api-so/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,38 @@ resource environmentKeyVaultResource 'Microsoft.KeyVault/vaults@2023-07-01' exis

var containerAppName = '${namePrefix}-webapi-so-ca'

var port = 8080

var probes = [
{
periodSeconds: 5
initialDelaySeconds: 2
type: 'Liveness'
httpGet: {
path: '/liveness'
port: port
}
}
{
periodSeconds: 5
initialDelaySeconds: 2
type: 'Readiness'
httpGet: {
path: '/readiness'
port: port
}
}
{
periodSeconds: 5
initialDelaySeconds: 2
type: 'Startup'
httpGet: {
path: '/startup'
port: port
}
}
]
arealmaas marked this conversation as resolved.
Show resolved Hide resolved

module containerApp '../../modules/containerApp/main.bicep' = {
name: containerAppName
params: {
Expand All @@ -98,6 +130,8 @@ module containerApp '../../modules/containerApp/main.bicep' = {
apimIp: apimIp
tags: tags
resources: resources
probes: probes
port: port
revisionSuffix: revisionSuffix
}
}
Expand Down
25 changes: 3 additions & 22 deletions .azure/modules/containerApp/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,12 @@ param resources object?
@description('The suffix for the revision of the container app')
param revisionSuffix string

@description('The probes for the container app')
param probes array = []
arealmaas marked this conversation as resolved.
Show resolved Hide resolved

// Container app revision name does not allow '.' character
var cleanedRevisionSuffix = replace(revisionSuffix, '.', '-')

var probes = [
{
periodSeconds: 5
initialDelaySeconds: 2
type: 'Liveness'
httpGet: {
path: '/healthz'
port: port
}
}
{
periodSeconds: 5
initialDelaySeconds: 2
type: 'Readiness'
httpGet: {
path: '/healthz'
port: port
}
}
]

var ipSecurityRestrictions = empty(apimIp)
? []
: [
Expand All @@ -74,7 +56,6 @@ resource containerApp 'Microsoft.App/containerApps@2024-03-01' = {
identity: {
type: 'SystemAssigned'
}

properties: {
configuration: {
ingress: ingress
Expand Down
7 changes: 7 additions & 0 deletions Digdir.Domain.Dialogporten.sln
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Digdir.Domain.Dialogporten.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Digdir.Domain.Dialogporten.Architecture.Tests", "tests\Digdir.Domain.Dialogporten.Architecture.Tests\Digdir.Domain.Dialogporten.Architecture.Tests.csproj", "{E389C7C8-9610-40AC-86DC-769B1B7DC78E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Digdir.Library.Utils.AspNet", "src\Digdir.Library.Utils.AspNet\Digdir.Library.Utils.AspNet.csproj", "{6A485C65-3613-4A49-A16F-2789119F6F38}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -153,6 +155,10 @@ Global
{E389C7C8-9610-40AC-86DC-769B1B7DC78E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E389C7C8-9610-40AC-86DC-769B1B7DC78E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E389C7C8-9610-40AC-86DC-769B1B7DC78E}.Release|Any CPU.Build.0 = Release|Any CPU
{6A485C65-3613-4A49-A16F-2789119F6F38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6A485C65-3613-4A49-A16F-2789119F6F38}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A485C65-3613-4A49-A16F-2789119F6F38}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A485C65-3613-4A49-A16F-2789119F6F38}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -182,6 +188,7 @@ Global
{AF35FFCA-1206-4C08-A003-DA4A1344CCD5} = {CADB8189-4AA1-4732-844A-C41DBF3EC8B7}
{0900E3CF-F9D8-4B29-957F-484B3B028D6D} = {320B47A0-5EB8-4B6E-8C84-90633A1849CA}
{E389C7C8-9610-40AC-86DC-769B1B7DC78E} = {CADB8189-4AA1-4732-844A-C41DBF3EC8B7}
{6A485C65-3613-4A49-A16F-2789119F6F38} = {320B47A0-5EB8-4B6E-8C84-90633A1849CA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B2FE67FF-7622-4AFB-AD8E-961B6A39D888}
Expand Down
2 changes: 1 addition & 1 deletion docs/schema/V1/swagger.verified.json
Original file line number Diff line number Diff line change
Expand Up @@ -6460,4 +6460,4 @@
"url": "https://altinn-dev-api.azure-api.net/dialogporten"
}
]
}
}
arealmaas marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<TreatAsUsed>true</TreatAsUsed>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="8.0.0"/>
<PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="8.0.0"/>
arealmaas marked this conversation as resolved.
Show resolved Hide resolved
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0"/>
<PackageReference Include="Polly.Contrib.WaitAndRetry" Version="1.1.1"/>
<PackageReference Include="ZiggyCreatures.FusionCache" Version="1.4.0" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using StackExchange.Redis;
using Microsoft.Extensions.Options;

namespace Digdir.Domain.Dialogporten.Infrastructure.HealthChecks;

internal sealed class RedisHealthCheck : IHealthCheck
{
private readonly InfrastructureSettings _settings;

public RedisHealthCheck(IOptions<InfrastructureSettings> options)
{
_settings = options?.Value ?? throw new ArgumentNullException(nameof(options));
}
arealmaas marked this conversation as resolved.
Show resolved Hide resolved

public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
try
{
using var redis = await ConnectionMultiplexer.ConnectAsync(_settings.Redis.ConnectionString);
var db = redis.GetDatabase();
await db.PingAsync();
arealmaas marked this conversation as resolved.
Show resolved Hide resolved
return HealthCheckResult.Healthy("Redis connection is healthy.");
}
catch (RedisConnectionException ex)
{
return HealthCheckResult.Unhealthy("Unable to connect to Redis.", exception: ex);
}
catch (Exception ex)
{
return HealthCheckResult.Unhealthy("An unexpected error occurred while checking Redis health.", exception: ex);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
using StackExchange.Redis;
using ZiggyCreatures.Caching.Fusion;
using ZiggyCreatures.Caching.Fusion.NullObjects;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Digdir.Domain.Dialogporten.Infrastructure.HealthChecks;

namespace Digdir.Domain.Dialogporten.Infrastructure;

Expand Down Expand Up @@ -199,6 +201,8 @@ public static IServiceCollection AddInfrastructure(this IServiceCollection servi
})
.AddPolicyHandlerFromRegistry(PollyPolicy.DefaultHttpRetryPolicy);

services.AddCustomHealthChecks();

if (environment.IsDevelopment())
{
var localDeveloperSettings = configuration.GetLocalDevelopmentSettings();
Expand All @@ -212,6 +216,24 @@ public static IServiceCollection AddInfrastructure(this IServiceCollection servi
return services;
}

private static IServiceCollection AddCustomHealthChecks(this IServiceCollection services)
{
services.AddHttpClient("HealthCheckClient")
.ConfigureHttpClient(client =>
{
client.Timeout = TimeSpan.FromSeconds(5);
})
.AddPolicyHandlerFromRegistry(PollyPolicy.DefaultHttpRetryPolicy); ;
arealmaas marked this conversation as resolved.
Show resolved Hide resolved

services.AddHealthChecks()
MagnusSandgren marked this conversation as resolved.
Show resolved Hide resolved
.AddCheck<RedisHealthCheck>("redis", tags: ["dependencies", "redis"])
.AddDbContextCheck<DialogDbContext>("postgres", tags: ["dependencies", "critical"]);

services.AddSingleton<RedisHealthCheck>();
arealmaas marked this conversation as resolved.
Show resolved Hide resolved

return services;
}
arealmaas marked this conversation as resolved.
Show resolved Hide resolved

private static IServiceCollection AddGraphQlRedisSubscriptions(this IServiceCollection services,
string redisConnectionString)
{
Expand Down Expand Up @@ -295,4 +317,4 @@ private static IServiceCollection ConfigureFusionCache(this IServiceCollection s

return services;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
<ItemGroup>
<ProjectReference Include="..\Digdir.Domain.Dialogporten.Application\Digdir.Domain.Dialogporten.Application.csproj"/>
<ProjectReference Include="..\Digdir.Domain.Dialogporten.Infrastructure\Digdir.Domain.Dialogporten.Infrastructure.csproj"/>
<ProjectReference Include="..\Digdir.Library.Utils.AspNet\Digdir.Library.Utils.AspNet.csproj"/>
<ProjectReference Include="..\Digdir.Tool.Dialogporten.GenerateFakeData\Digdir.Tool.Dialogporten.GenerateFakeData.csproj"/>
</ItemGroup>

</Project>
</Project>
70 changes: 46 additions & 24 deletions src/Digdir.Domain.Dialogporten.WebApi/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
using Microsoft.AspNetCore.Authorization;
using NSwag;
using Serilog;
using Digdir.Library.Utils.AspNet;
using static Digdir.Library.Utils.AspNet.HealthCheckExtensions;

// Using two-stage initialization to catch startup errors.
Log.Logger = new LoggerConfiguration()
Expand Down Expand Up @@ -126,11 +128,27 @@ static void BuildAndRun(string[] args)
.AddNewtonsoftJson()
.Services


// Auth
.AddDialogportenAuthentication(builder.Configuration)
.AddAuthorization()
.AddHealthChecks();
.AddAuthorization();

// Retrieve JWT bearer token schema URLs from configuration
var authSettings = builder.Configuration
.GetSection("WebApi")
.Get<WebApiSettings>();

var wellKnownUrls = authSettings?
.Authentication
.JwtBearerTokenSchemas
.Select(schema => schema.WellKnown)
.Where(url => !string.IsNullOrEmpty(url))
.ToList() ?? new List<string>();

// Add health checks with the retrieved URLs
builder.Services.AddAspNetHealthChecks(new AspNetHealthChecksSettings
{
HttpGetEndpointsToCheck = wellKnownUrls
});

if (builder.Environment.IsDevelopment())
{
Expand All @@ -155,25 +173,11 @@ static void BuildAndRun(string[] args)
.UseAuthorization()
.UseServiceOwnerOnBehalfOfPerson()
.UseUserTypeValidation()
.UseAzureConfiguration()
.UseFastEndpoints(x =>
{
x.Endpoints.RoutePrefix = "api";
x.Versioning.Prefix = "v";
x.Versioning.PrependToRoute = true;
x.Versioning.DefaultVersion = 1;
x.Serializer.Options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
// Do not serialize empty collections
x.Serializer.Options.TypeInfoResolver = new DefaultJsonTypeInfoResolver
{
Modifiers = { IgnoreEmptyCollections }
};
x.Serializer.Options.Converters.Add(new JsonStringEnumConverter());
x.Serializer.Options.Converters.Add(new UtcDateTimeOffsetConverter());
x.Serializer.Options.Converters.Add(new DateTimeNotSupportedConverter());
x.Errors.ResponseBuilder = ErrorResponseBuilderExtensions.ResponseBuilder;
})
.UseAddSwaggerCorsHeader()
.UseAzureConfiguration();

app.MapAspNetHealthChecks();

app.UseAddSwaggerCorsHeader()
.UseSwaggerGen(config =>
{
config.PostProcess = (document, _) =>
Expand All @@ -198,9 +202,27 @@ static void BuildAndRun(string[] args)
// We have to add dialogporten here to get the correct base url for swagger.json in the APIM. Should not be done for development
var dialogPrefix = builder.Environment.IsDevelopment() ? "" : "/dialogporten";
uiConfig.DocumentPath = dialogPrefix + "/swagger/{documentName}/swagger.json";
})
.UseFastEndpoints(x =>
{
x.Endpoints.RoutePrefix = "api";
x.Versioning.Prefix = "v";
x.Versioning.PrependToRoute = true;
x.Versioning.DefaultVersion = 1;
x.Serializer.Options.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
// Do not serialize empty collections
x.Serializer.Options.TypeInfoResolver = new DefaultJsonTypeInfoResolver
{
Modifiers = { IgnoreEmptyCollections }
};
x.Serializer.Options.Converters.Add(new JsonStringEnumConverter());
x.Serializer.Options.Converters.Add(new UtcDateTimeOffsetConverter());
x.Serializer.Options.Converters.Add(new DateTimeNotSupportedConverter());
x.Errors.ResponseBuilder = ErrorResponseBuilderExtensions.ResponseBuilder;
});

app.MapControllers();
app.MapHealthChecks("/healthz");

app.Run();
}

Expand All @@ -216,4 +238,4 @@ static void IgnoreEmptyCollections(JsonTypeInfo typeInfo)
}

// ReSharper disable once ClassNeverInstantiated.Global
public sealed partial class Program;
public sealed partial class Program;
arealmaas marked this conversation as resolved.
Show resolved Hide resolved
MagnusSandgren marked this conversation as resolved.
Show resolved Hide resolved
Loading
Loading