From 1f9fa2b3fbb7ea9bd84ddde5f99697724785921d Mon Sep 17 00:00:00 2001 From: Are Almaas Date: Thu, 24 Oct 2024 14:00:51 +0200 Subject: [PATCH 1/2] feat(infrastructure): add availability test for apim (#1327) ## Description An availability test for the backend. For now will send a health-check request to web-api-so so verify that the service is up and running with the all dependencies. The health-endpoint in APIM will send requests to web-api-so by default, the other services are not exposed yet. - Adds an availability test towards our APIM. Will probe the deep version of the health-checks which checks third party URLs together with Redis and Postgres. - Will now only target web-api-so as it is the default backend. Should expose all services like this. image The frontend availability test: ![image](https://github.com/user-attachments/assets/55cbe387-d246-4b45-bbd4-17722f4117ab) ## Related Issue(s) - #292 ## Verification - [ ] **Your** code builds clean without any errors or warnings - [ ] Manual testing done (required) - [ ] Relevant automated test added (if you find this hard, leave it and we'll help out) ## Documentation - [ ] Documentation is updated (either in `docs`-directory, Altinnpedia or a separate linked PR in [altinn-studio-docs.](https://github.com/Altinn/altinn-studio-docs), if applicable) ## Summary by CodeRabbit - **New Features** - Introduced a new parameter `apimUrl` for capturing the APIM instance URL across various environments (production, staging, test, yt01). - Added a new module for creating an availability test for the APIM instance, enhancing monitoring capabilities. - **Enhancements** - New output declaration for the Application Insights resource ID, allowing easier access to the resource identifier post-deployment. --- .azure/infrastructure/main.bicep | 15 ++++++ .azure/infrastructure/prod.bicepparam | 2 + .azure/infrastructure/staging.bicepparam | 2 + .azure/infrastructure/test.bicepparam | 2 + .azure/infrastructure/yt01.bicepparam | 2 + .../availabilityTest.bicep | 54 +++++++++++++++++++ .../modules/applicationInsights/create.bicep | 1 + 7 files changed, 78 insertions(+) create mode 100644 .azure/modules/applicationInsights/availabilityTest.bicep diff --git a/.azure/infrastructure/main.bicep b/.azure/infrastructure/main.bicep index d46f53a18..576a1861b 100644 --- a/.azure/infrastructure/main.bicep +++ b/.azure/infrastructure/main.bicep @@ -39,6 +39,9 @@ param sourceKeyVaultSshJumperSshPublicKey string @description('The object ID of the group to assign the Admin Login role for SSH Jumper') param sshJumperAdminLoginGroupObjectId string +@description('The URL of the APIM instance') +param apimUrl string + import { Sku as KeyVaultSku } from '../modules/keyvault/create.bicep' param keyVaultSku KeyVaultSku @@ -117,6 +120,18 @@ module appInsights '../modules/applicationInsights/create.bicep' = { } } +module apimAvailabilityTest '../modules/applicationInsights/availabilityTest.bicep' = { + scope: resourceGroup + name: 'apimAvailabilityTest' + params: { + name: '${namePrefix}-dialogporten-health-test' + location: location + tags: tags + appInsightsId: appInsights.outputs.appInsightsId + url: '${apimUrl}/health/deep' + } +} + module serviceBus '../modules/serviceBus/main.bicep' = { scope: resourceGroup name: 'serviceBus' diff --git a/.azure/infrastructure/prod.bicepparam b/.azure/infrastructure/prod.bicepparam index 15ea338be..2eb2d4c17 100644 --- a/.azure/infrastructure/prod.bicepparam +++ b/.azure/infrastructure/prod.bicepparam @@ -48,3 +48,5 @@ param serviceBusSku = { // Altinn Product Dialogporten: Developers Prod param sshJumperAdminLoginGroupObjectId = 'a94de4bf-0a83-4d30-baba-0c6a7365571c' + +param apimUrl = 'https://platform.altinn.no/dialogporten' diff --git a/.azure/infrastructure/staging.bicepparam b/.azure/infrastructure/staging.bicepparam index 4f9f91688..40ebabf97 100644 --- a/.azure/infrastructure/staging.bicepparam +++ b/.azure/infrastructure/staging.bicepparam @@ -47,3 +47,5 @@ param serviceBusSku = { } // Altinn Product Dialogporten: Developers Prod param sshJumperAdminLoginGroupObjectId = 'a94de4bf-0a83-4d30-baba-0c6a7365571c' + +param apimUrl = 'https://platform.tt02.altinn.no/dialogporten' diff --git a/.azure/infrastructure/test.bicepparam b/.azure/infrastructure/test.bicepparam index 4efab5825..ce73b3286 100644 --- a/.azure/infrastructure/test.bicepparam +++ b/.azure/infrastructure/test.bicepparam @@ -48,3 +48,5 @@ param serviceBusSku = { // Altinn Product Dialogporten: Developers Dev param sshJumperAdminLoginGroupObjectId = 'c12e51e3-5cbd-4229-8a31-5394c423fb5f' + +param apimUrl = 'https://altinn-dev-api.azure-api.net/dialogporten' diff --git a/.azure/infrastructure/yt01.bicepparam b/.azure/infrastructure/yt01.bicepparam index 26c80d77b..0e40d97a0 100644 --- a/.azure/infrastructure/yt01.bicepparam +++ b/.azure/infrastructure/yt01.bicepparam @@ -47,3 +47,5 @@ param serviceBusSku = { } // Altinn Product Dialogporten: Developers Dev param sshJumperAdminLoginGroupObjectId = 'c12e51e3-5cbd-4229-8a31-5394c423fb5f' + +param apimUrl = 'https://platform.yt01.altinn.cloud/dialogporten' diff --git a/.azure/modules/applicationInsights/availabilityTest.bicep b/.azure/modules/applicationInsights/availabilityTest.bicep new file mode 100644 index 000000000..3a384e0e3 --- /dev/null +++ b/.azure/modules/applicationInsights/availabilityTest.bicep @@ -0,0 +1,54 @@ +@description('The name of the availability test') +param name string + +@description('The location where the resources will be deployed') +param location string + +@description('Tags to apply to resources') +param tags object + +@description('The ID of the Application Insights resource') +param appInsightsId string + +@description('The URL of the availability test') +param url string + +@description('The frequency in seconds at which the test runs') +param frequency int = 120 // Default is every 2 minutes + +@description('The timeout in seconds for the test') +param timeout int = 60 // Default is 1 minute + +resource availabilityTest 'Microsoft.Insights/webtests@2022-06-15' = { + name: name + location: location + tags: union(tags, { + 'hidden-link:${appInsightsId}': 'Resource' + }) + kind: 'standard' + properties: { + Enabled: true + SyntheticMonitorId: name + Name: name + Description: 'Availability test for ${name}' + Frequency: frequency + Timeout: timeout + Kind: 'standard' + RetryEnabled: true + Locations: [ + { Id: 'emea-nl-ams-azr' } // Amsterdam + { Id: 'emea-se-sto-edge' } // Stockholm + { Id: 'emea-gb-db3-azr' } // Dublin + ] + Request: { + RequestUrl: url + HttpVerb: 'GET' + ParseDependentRequests: false + } + ValidationRules: { + ExpectedHttpStatusCode: 200 + SSLCheck: true + SSLCertRemainingLifetimeCheck: 7 + } + } +} diff --git a/.azure/modules/applicationInsights/create.bicep b/.azure/modules/applicationInsights/create.bicep index dcac7fb1c..fdc24e54b 100644 --- a/.azure/modules/applicationInsights/create.bicep +++ b/.azure/modules/applicationInsights/create.bicep @@ -53,3 +53,4 @@ resource appInsights 'Microsoft.Insights/components@2020-02-02' = { output connectionString string = appInsights.properties.ConnectionString output appInsightsWorkspaceName string = appInsightsWorkspace.name output appInsightsName string = appInsights.name +output appInsightsId string = appInsights.id From fa3157a565d8b186790029ae79ea3f59ad8da27b Mon Sep 17 00:00:00 2001 From: Are Almaas Date: Thu, 24 Oct 2024 15:13:06 +0200 Subject: [PATCH 2/2] chore(web-api): separate the telemetry-configuration into aspnet utils library (#1341) ## Description As a step to configure telemetry in service and graphql, separating the configuration into the aspnet-project ## Related Issue(s) - #1262 ## Verification - [ ] **Your** code builds clean without any errors or warnings - [ ] Manual testing done (required) - [ ] Relevant automated test added (if you find this hard, leave it and we'll help out) ## Documentation - [ ] Documentation is updated (either in `docs`-directory, Altinnpedia or a separate linked PR in [altinn-studio-docs.](https://github.com/Altinn/altinn-studio-docs), if applicable) ## Summary by CodeRabbit - **New Features** - Introduced a new method for configuring telemetry in the application, enhancing observability through OpenTelemetry for tracing and metrics. - Added support for Azure Monitor and Application Insights based on environment settings. - **Bug Fixes** - Removed outdated telemetry configuration that could lead to inconsistencies in monitoring. - **Chores** - Updated project dependencies to include necessary telemetry packages for improved performance and monitoring capabilities. --- .../WebApplicationBuilderExtensions.cs | 49 ------------------- .../Digdir.Domain.Dialogporten.WebApi.csproj | 5 -- .../AspNetUtilitiesExtensions.cs | 49 ++++++++++++++++++- .../Digdir.Library.Utils.AspNet.csproj | 5 ++ 4 files changed, 52 insertions(+), 56 deletions(-) delete mode 100644 src/Digdir.Domain.Dialogporten.WebApi/Common/Extensions/WebApplicationBuilderExtensions.cs diff --git a/src/Digdir.Domain.Dialogporten.WebApi/Common/Extensions/WebApplicationBuilderExtensions.cs b/src/Digdir.Domain.Dialogporten.WebApi/Common/Extensions/WebApplicationBuilderExtensions.cs deleted file mode 100644 index 88b734912..000000000 --- a/src/Digdir.Domain.Dialogporten.WebApi/Common/Extensions/WebApplicationBuilderExtensions.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Azure.Monitor.OpenTelemetry.AspNetCore; -using OpenTelemetry.Trace; -using Npgsql; -using OpenTelemetry.Metrics; -using OpenTelemetry.Resources; - -namespace Digdir.Domain.Dialogporten.WebApi.Common.Extensions; - -internal static class WebApplicationBuilderExtensions -{ - public static WebApplicationBuilder ConfigureTelemetry(this WebApplicationBuilder builder) - { - builder.Services.AddOpenTelemetry() - .ConfigureResource(resource => resource - .AddService(serviceName: builder.Environment.ApplicationName)) - .WithTracing(tracing => - { - if (builder.Environment.IsDevelopment()) - { - tracing.SetSampler(new AlwaysOnSampler()); - } - - tracing.AddAspNetCoreInstrumentation(options => - { - options.Filter = (httpContext) => - !httpContext.Request.Path.StartsWithSegments("/health"); - }); - - tracing.AddHttpClientInstrumentation(); - tracing.AddNpgsql(); - }) - .WithMetrics(metrics => - { - metrics.AddRuntimeInstrumentation(); - }); - - if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING"))) - { - builder.Services.AddOpenTelemetry().UseAzureMonitor(); - } - else - { - // Use Application Insights SDK for local development - builder.Services.AddApplicationInsightsTelemetry(); - } - - return builder; - } -} diff --git a/src/Digdir.Domain.Dialogporten.WebApi/Digdir.Domain.Dialogporten.WebApi.csproj b/src/Digdir.Domain.Dialogporten.WebApi/Digdir.Domain.Dialogporten.WebApi.csproj index 31715419d..e84cc903e 100644 --- a/src/Digdir.Domain.Dialogporten.WebApi/Digdir.Domain.Dialogporten.WebApi.csproj +++ b/src/Digdir.Domain.Dialogporten.WebApi/Digdir.Domain.Dialogporten.WebApi.csproj @@ -8,17 +8,12 @@ - - - - - diff --git a/src/Digdir.Library.Utils.AspNet/AspNetUtilitiesExtensions.cs b/src/Digdir.Library.Utils.AspNet/AspNetUtilitiesExtensions.cs index e5e4d0b4c..dd108c44b 100644 --- a/src/Digdir.Library.Utils.AspNet/AspNetUtilitiesExtensions.cs +++ b/src/Digdir.Library.Utils.AspNet/AspNetUtilitiesExtensions.cs @@ -1,9 +1,15 @@ +using Azure.Monitor.OpenTelemetry.AspNetCore; using Digdir.Library.Utils.AspNet.HealthChecks; using HealthChecks.UI.Client; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.HealthChecks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Diagnostics.HealthChecks; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.HealthChecks; +using Microsoft.Extensions.Hosting; +using Npgsql; +using OpenTelemetry.Trace; +using OpenTelemetry.Metrics; +using OpenTelemetry.Resources; namespace Digdir.Library.Utils.AspNet; @@ -40,4 +46,43 @@ private static WebApplication MapHealthCheckEndpoint(this WebApplication app, st app.MapHealthChecks(path, new HealthCheckOptions { Predicate = predicate, ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse }); return app; } + + public static WebApplicationBuilder ConfigureTelemetry(this WebApplicationBuilder builder) + { + builder.Services.AddOpenTelemetry() + .ConfigureResource(resource => resource + .AddService(serviceName: builder.Environment.ApplicationName)) + .WithTracing(tracing => + { + if (builder.Environment.IsDevelopment()) + { + tracing.SetSampler(new AlwaysOnSampler()); + } + + tracing.AddAspNetCoreInstrumentation(options => + { + options.Filter = (httpContext) => + !httpContext.Request.Path.StartsWithSegments("/health"); + }); + + tracing.AddHttpClientInstrumentation(); + tracing.AddNpgsql(); + }) + .WithMetrics(metrics => + { + metrics.AddRuntimeInstrumentation(); + }); + + if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("APPLICATIONINSIGHTS_CONNECTION_STRING"))) + { + builder.Services.AddOpenTelemetry().UseAzureMonitor(); + } + else + { + // Use Application Insights SDK for local development + builder.Services.AddApplicationInsightsTelemetry(); + } + + return builder; + } } diff --git a/src/Digdir.Library.Utils.AspNet/Digdir.Library.Utils.AspNet.csproj b/src/Digdir.Library.Utils.AspNet/Digdir.Library.Utils.AspNet.csproj index 3695da595..97901c576 100644 --- a/src/Digdir.Library.Utils.AspNet/Digdir.Library.Utils.AspNet.csproj +++ b/src/Digdir.Library.Utils.AspNet/Digdir.Library.Utils.AspNet.csproj @@ -7,9 +7,14 @@ + + + + +