Skip to content

Commit

Permalink
Abstract App Insights JS SDK (#1226)
Browse files Browse the repository at this point in the history
* Making it a shared partial keeps the _layout.cshtml cleaner

* Adds missing configuration for click tracking and user identification

* Extract App Insights connection string into Options
  • Loading branch information
DrizzlyOwl authored Dec 2, 2024
1 parent 7086f91 commit 5430458
Show file tree
Hide file tree
Showing 12 changed files with 70 additions and 22 deletions.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Dfe.PrepareConversions.Configuration;
using Xunit;

namespace Dfe.PrepareConversions.Tests.Configuration;

public class ApplicationInsightsOptionsTests
{
[Fact]
public void Configuration_section_should_be_ApplicationInsights()
{
Assert.Equal("ApplicationInsights", ApplicationInsightsOptions.ConfigurationSection);
}

[Fact]
public void ConnectionString_should_default_to_null()
{
var _options = new ApplicationInsightsOptions();
Assert.Null(_options.ConnectionString);
}

[Fact]
public void InstrumentationKey_should_default_to_null()
{
var _options = new ApplicationInsightsOptions();
Assert.Null(_options.InstrumentationKey);
}

[Fact]
public void EnableBrowserAnalytics_should_default_to_null()
{
var _options = new ApplicationInsightsOptions();
Assert.Null(_options.EnableBrowserAnalytics);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace Dfe.PrepareConversions.Configuration;

public class ApplicationInsightsOptions
{
public const string ConfigurationSection = "ApplicationInsights";
public string ConnectionString { get; init; }
public string InstrumentationKey { get; init; }
public string EnableBrowserAnalytics { get; init; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@{
var authenticatedUserId = (User.Identity is not null && User.Identity.IsAuthenticated) ? User.Identity.Name ?? "Unknown" : "Anonymous";
}
<script type="text/javascript" integrity="sha384-g/ZkzetdQypWdY0NBZT5r2L3BR9/hURD8OBcd1rEaBpgX6QC7EaTL+o+mzWrBcXW" crossorigin="anonymous" src="https://js.monitor.azure.com/scripts/b/ext/ai.clck.2.8.18.min.js"></script>
<script type="text/javascript" asp-add-nonce>
window.appInsights = {
connectionString: '@ApplicationInsightsOptions.Value.ConnectionString',
instrumentationKey: '@ApplicationInsightsOptions.Value.InstrumentationKey',
authenticatedUserId: '@authenticatedUserId'
}
</script>
<script type="text/javascript" src="~/dist/application-insights.min.js" asp-add-nonce></script>
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
var isTransfersPage = Context.Request.Path.Value.ToLower().Contains("/transfers");

var notificationBannerMessage = Configuration["notificationBannerMessage"] ?? string.Empty;

var authenticatedUserId = User.Identity is not null && User.Identity.IsAuthenticated ? User.Identity.Name ?? "Unknown" : "Anonymous";
}

<!DOCTYPE html>
Expand Down Expand Up @@ -64,16 +62,7 @@

@if (enableAppInsightsAnalytics)
{
<!-- Application insights -->
<script type="text/javascript" integrity="sha384-g/ZkzetdQypWdY0NBZT5r2L3BR9/hURD8OBcd1rEaBpgX6QC7EaTL+o+mzWrBcXW" crossorigin="anonymous" src="https://js.monitor.azure.com/scripts/b/ext/ai.clck.2.8.18.min.js"></script>
<script type="text/javascript" asp-add-nonce>
window.appInsights = {
connectionString: '@Configuration["ApplicationInsights:ConnectionString"]',
authenticatedUserId: '@authenticatedUserId'
}
</script>
<script type="text/javascript" src="~/dist/application-insights.min.js" asp-add-nonce></script>
<!-- End Application insights -->
<partial name="_AppInsights"/>
}

<script type="text/javascript" src="~/dist/accessible-autocomplete.min.js" asp-add-nonce></script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
@using Dfe.PrepareConversions.Models
@using Dfe.PrepareConversions.ViewModels
@using Dfe.PrepareConversions.Extensions
@using Dfe.PrepareConversions.Configuration
@using Microsoft.ApplicationInsights.AspNetCore
@using Microsoft.Extensions.Options
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Microsoft.FeatureManagement.AspNetCore
@addTagHelper *, Dfe.PrepareConversions
@addTagHelper *, NetEscapades.AspNetCore.SecurityHeaders.TagHelpers
@addTagHelper *, NetEscapades.AspNetCore.SecurityHeaders.TagHelpers
@inject IOptions<ApplicationInsightsOptions> ApplicationInsightsOptions
3 changes: 2 additions & 1 deletion Dfe.PrepareConversions/Dfe.PrepareConversions/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -147,14 +147,15 @@ public void ConfigureServices(IServiceCollection services)

services.Configure<ServiceLinkOptions>(GetConfigurationSectionFor<ServiceLinkOptions>());
services.Configure<AzureAdOptions>(GetConfigurationSectionFor<AzureAdOptions>());
services.Configure<ApplicationInsightsOptions>(GetConfigurationSectionFor<ApplicationInsightsOptions>());

services.AddScoped<ErrorService>();
services.AddScoped<IGetEstablishment, EstablishmentService>();
services.Decorate<IGetEstablishment, GetEstablishmentItemCacheDecorator>();
services.AddScoped<SchoolPerformanceService>();
services.AddScoped<SchoolOverviewService>();
services.AddScoped<KeyStagePerformanceService>();
services.AddScoped<ITrustsRepository, TrustsRepository>();
services.AddScoped<ITrustsRepository, TrustsRepository>();
services.AddScoped<IProjectGroupsRepository, ProjectGroupsRepository>();
services.AddScoped<IRoleCapablitiesRepository, RoleCapablitiesRepository>();
services.AddScoped<IAcademyConversionProjectRepository, AcademyConversionProjectRepository>();
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
{
"scripts": {
"build": "npm run build:assets & npm run build:frontend",
"build:frontend": "webpack",
"build:assets": "webpack --config webpack.assets.config.js & npm run build:assets:application-insights",
"build:assets:application-insights": "webpack --config webpack.appinsights.config.js",
"build:watch": "webpack --watch"
"build": "webpack --config webpack.assets.config.js --mode=production & webpack --config webpack.config.js --mode=production & webpack --config webpack.appinsights.config.js --mode=production",
"build:watch": "webpack --config webpack.assets.config.js --mode=development --watch & webpack --config webpack.config.js --watch --mode=development & webpack --config webpack.appinsights.config.js --watch --mode=development"
},
"devDependencies": {
"copy-webpack-plugin": "^7.0.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ApplicationInsights } from '@microsoft/applicationinsights-web'
const clickPluginInstance = new Microsoft.ApplicationInsights.ClickAnalyticsPlugin();
const appInsights = new ApplicationInsights({ config: {
connectionString: window.appInsights.connectionString,
instrumentationKey: window.appInsights.instrumentationKey,
extensions: [ clickPluginInstance ],
extensionConfig: { [clickPluginInstance.identifier] : {
autoCapture : true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@
display: inline;
line-height: 2;
}

5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ RUN dotnet publish Dfe.PrepareConversions -c Release -o /app --no-restore

# Stage 2 - Build assets
FROM node:${NODEJS_IMAGE_TAG} as build

Check warning on line 19 in Dockerfile

View workflow job for this annotation

GitHub Actions / Deploy / Build and push to GHCR

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/

Check warning on line 19 in Dockerfile

View workflow job for this annotation

GitHub Actions / scan

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/

Check warning on line 19 in Dockerfile

View workflow job for this annotation

GitHub Actions / Deploy / Build and push to GHCR

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/

Check warning on line 19 in Dockerfile

View workflow job for this annotation

GitHub Actions / Deploy / Build and push to GHCR

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/
COPY --from=publish /app /app
COPY ./Dfe.PrepareConversions/Dfe.PrepareConversions/wwwroot /app/wwwroot
WORKDIR /app/wwwroot
RUN npm install
RUN npm run build
Expand All @@ -26,7 +26,8 @@ RUN npm run build
ARG ASPNET_IMAGE_TAG
FROM "mcr.microsoft.com/dotnet/aspnet:${ASPNET_IMAGE_TAG}" AS final
LABEL org.opencontainers.image.source=https://github.com/DFE-Digital/prepare-academy-conversions
COPY --from=build /app /app
COPY --from=publish /app /app
COPY --from=build /app/wwwroot /app/wwwroot

WORKDIR /app
COPY ./script/web-docker-entrypoint.sh ./docker-entrypoint.sh
Expand Down

0 comments on commit 5430458

Please sign in to comment.