diff --git a/Lombiq.Hosting.Azure.ApplicationInsights/Extensions/ApplicationInsightsInitializerExtensions.cs b/Lombiq.Hosting.Azure.ApplicationInsights/Extensions/ApplicationInsightsInitializerExtensions.cs index fdb2c52..91419ce 100644 --- a/Lombiq.Hosting.Azure.ApplicationInsights/Extensions/ApplicationInsightsInitializerExtensions.cs +++ b/Lombiq.Hosting.Azure.ApplicationInsights/Extensions/ApplicationInsightsInitializerExtensions.cs @@ -8,7 +8,10 @@ using Microsoft.ApplicationInsights.DependencyCollector; using Microsoft.ApplicationInsights.Extensibility; using Microsoft.ApplicationInsights.Extensibility.PerfCounterCollector.QuickPulse; +using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using System.Linq; using ApplicationInsightsFeatureIds = Lombiq.Hosting.Azure.ApplicationInsights.Constants.FeatureIds; @@ -17,6 +20,49 @@ namespace Microsoft.Extensions.DependencyInjection; public static class ApplicationInsightsInitializerExtensions { + /// + /// Lombiq-recommended opinionated default configuration for features of an Orchard Core application hosted in + /// Azure, with Application Insights telemetry. If any of the configuration values exist, they won't be overridden, + /// so e.g. appsettings.json configuration will take precedence. + /// + /// The instance of the app. + /// Configuration for the hosting defaults. + public static OrchardCoreBuilder ConfigureAzureHostingDefaultsWithApplicationInsightsTelemetry( + this OrchardCoreBuilder builder, + WebApplicationBuilder webApplicationBuilder, + AzureHostingConfiguration hostingConfiguration = null) + { + builder.ConfigureAzureHostingDefaults(webApplicationBuilder, hostingConfiguration); + + var logLevelSection = webApplicationBuilder.Configuration.GetSection("Logging:ApplicationInsights:LogLevel"); + + logLevelSection.AddValueIfKeyNotExists("Default", "Warning"); + + var ocAppInsightsSection = webApplicationBuilder.Configuration.GetSection("OrchardCore:Lombiq_Hosting_Azure_ApplicationInsights"); + + ocAppInsightsSection + .AddValueIfKeyNotExists("EnableUserNameCollection", "true") + .AddValueIfKeyNotExists("EnableUserAgentCollection", "true") + .AddValueIfKeyNotExists("EnableIpAddressCollection", "true"); + + if (webApplicationBuilder.Environment.IsDevelopment()) + { + ocAppInsightsSection.AddValueIfKeyNotExists("EnableLoggingTestMiddleware", "true"); + + var appInsightsSection = webApplicationBuilder.Configuration.GetSection("ApplicationInsights"); + + appInsightsSection.AddValueIfKeyNotExists("EnableDependencyTrackingTelemetryModule", "false"); + } + else + { + ocAppInsightsSection.AddValueIfKeyNotExists("EntraAuthenticationType", "ManagedIdentity"); + } + + builder.AddOrchardCoreApplicationInsightsTelemetry(webApplicationBuilder.Configuration); + + return builder; + } + /// /// Initializes Application Insights for Orchard Core. Should be used in the application Program.cs file. /// diff --git a/Readme.md b/Readme.md index e1fc5d0..66719c5 100644 --- a/Readme.md +++ b/Readme.md @@ -67,6 +67,8 @@ builder.Services Note that due to how the Application Insights .NET SDK works, telemetry can only be collected for the whole app at once; collecting telemetry separately for each tenant is not supported. +You can also use `ConfigureAzureHostingDefaultsWithApplicationInsightsTelemetry` instead; this sets up all the recommended hosting configuration with `ConfigureAzureHostingDefaults` from [Lombiq Helpful Libraries - Orchard Core Libraries](https://github.com/Lombiq/Helpful-Libraries/blob/dev/Lombiq.HelpfulLibraries.OrchardCore/Readme.md). + When using the full CMS approach of Orchard Core (i.e. not decoupled or headless) then the client-side tracking script will be automatically injected as a head script. Otherwise, you can create it with `ITrackingScriptFactory`. ### Advanced configuration @@ -122,6 +124,8 @@ If you want to use Entra Authentication for Application Insights, or if you have } ``` +> ⚠ Client-side tracking will currently fail with 401 Unauthorized if Local Authentication is disabled, see [this bug report](https://github.com/microsoft/ApplicationInsights-dotnet/issues/2893) for the Application Insights .NET SDK. If you need client-side tracking, you will have to keep Local Authentication enabled on your AI resource for now. + To set up Entra Authentication for an application hosted on Azure you will have to set up a Managed Identity for the application and give it the `Monitoring Metrics Publisher` role (see more on assigning Azure roles [here](https://learn.microsoft.com/en-us/azure/role-based-access-control/role-assignments-portal)) to be able to publish metrics to AI. A managed identity will allow your app to authenticate with the Application Insights resource; see how to set it up for specific Azure services [here](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/managed-identities-status). We recommend using the simpler system-assigned identity option, since then you can easily allow your app's identity to get a role under the Application Insights resource. Note that it might take a few minutes for the managed identity to work; until then, Live Metrics won't be available. You can also use a service principal to authenticate. To set this up, you will have to provide the service principal credentials in the configuration. See the [Service principal](#service-principal) section for more information. This is also the only way to authenticate if you are using a non-Azure (or local) environment - or an Azure resource that does not support Managed Identities.