To get the most out of Application Insights when building a Single Page Application, some specific tweaks are required. Let's walk through the steps to get Application Insights configured in your Angular application.
I expect that you already configured an Application Insights resource in the Azure Portal and have an existing Angular application.
Step 1 - Add dependencies and configuration settings
We’ll start by adding an extra dependency ‘@microsoft/applicationinsights-web’ to our package.json:
"dependencies": { | |
"@angular/animations": "~8.2.14", | |
"@angular/common": "~8.2.14", | |
"@angular/compiler": "~8.2.14", | |
"@angular/core": "~8.2.14", | |
"@angular/forms": "~8.2.14", | |
"@angular/platform-browser": "~8.2.14", | |
"@angular/platform-browser-dynamic": "~8.2.14", | |
"@angular/router": "~8.2.14", | |
"bootstrap": "^4.3.1", | |
"font-awesome": "^4.7.0", | |
"rxjs": "~6.4.0", | |
"tslib": "^1.10.0", | |
"zone.js": "~0.9.1" | |
"@microsoft/applicationinsights-web": "^2.8.3", | |
}, |
We also update our environment.ts file to store our Application Insights instrumentation key there:
export const environment = { | |
production: false, | |
baseApiUrl: 'http://localhost:3000/api', | |
appInsights: { | |
instrumentationKey: '[Replace With Your Key]' | |
} | |
}; |
Step 2 – Create an Angular Service to wrap the Application Insights SDK
We create an Angular service that we will use as a wrapper around the Application Insights SDK. Here we inject the AppInsights class.
Notice that we set both the ‘enableCorsCorrelation’
and ‘enableAutoRouteTracking’
to true
. This will correctly inject a correlation-id in our request headers and will track all route changes as navigation events.
import { Injectable } from '@angular/core'; | |
import { ApplicationInsights } from '@microsoft/applicationinsights-web'; | |
import { environment } from 'src/environments/environment'; | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class AppInsightsService { | |
instance: ApplicationInsights; | |
constructor() { | |
this.instance = new ApplicationInsights({ config: { | |
instrumentationKey: environment.appInsights.instrumentationKey, | |
enableCorsCorrelation: true, | |
enableAutoRouteTracking: true | |
} }); | |
this.instance.loadAppInsights(); | |
this.instance.trackPageView(); | |
} | |
} |
We can further expand this service with extra methods to explicitly call specific functionality of the Application Insights SDK:
import { Injectable } from '@angular/core'; | |
import { ApplicationInsights } from '@microsoft/applicationinsights-web'; | |
import { environment } from 'src/environments/environment'; | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class AppInsightsService { | |
instance: ApplicationInsights; | |
constructor() { | |
this.instance = new ApplicationInsights({ config: { | |
instrumentationKey: environment.appInsights.instrumentationKey, | |
enableCorsCorrelation: true, | |
enableAutoRouteTracking: true | |
} }); | |
this.instance.loadAppInsights(); | |
this.instance.trackPageView(); | |
} | |
logPageView(name?: string, url?: string) { // option to call manually | |
this.instance.trackPageView({ | |
name: name, | |
uri: url | |
}); | |
} | |
logEvent(name: string, properties?: { [key: string]: any }) { | |
this.instance.trackEvent({ name: name}, properties); | |
} | |
logMetric(name: string, average: number, properties?: { [key: string]: any }) { | |
this.instance.trackMetric({ name: name, average: average }, properties); | |
} | |
logException(exception: Error, severityLevel?: number) { | |
this.instance.trackException({ exception: exception, severityLevel: severityLevel }); | |
} | |
logTrace(message: string, properties?: { [key: string]: any }) { | |
this.instance.trackTrace({ message: message}, properties); | |
} | |
} |
Step 3 – Consume the service in our Angular application
To consume the service as soon as the application starts, we’ll inject it in our AppComponent:
import { Component } from '@angular/core'; | |
import { AppInsightsService } from './app-insights.service'; | |
@Component({ | |
selector: 'app-root', | |
templateUrl: './app.component.html', | |
styleUrls: ['./app.component.css'] | |
}) | |
export class AppComponent { | |
title = 'App Insights Demo'; | |
constructor(private appInsights: AppInsightsService) { } | |
} |
We can go one step further by creating our own ErrorHandler instance so that all client side exceptions are nicely logged in Application Insights:
import { AppInsightsService } from './app-insights.service'; | |
@Injectable() | |
export class ApplicationInsightsErrorHandler extends ErrorHandler { | |
constructor(private appInsightsService: AppInsightsService) { | |
super(); | |
} | |
handleError(error: Error) { | |
this.appInsightsService.logException(error); // Manually log exception | |
} | |
} |
Don’t forget to configure the AppModule to use this handler:
import { BrowserModule } from '@angular/platform-browser'; | |
import { NgModule } from '@angular/core'; | |
import { FormsModule } from '@angular/forms'; | |
import { AppRoutingModule } from './app-routing.module'; | |
import { HttpClientModule } from '@angular/common/http'; | |
import { ApplicationInsightsErrorHandler } from './app-insights.errorhandler'; | |
import { AppComponent } from './app.component'; | |
import { ActivitiesComponent } from './activities/activities.component'; | |
import { HomeComponent } from './home/home.component'; | |
import { LoginComponent } from './login/login.component'; | |
@NgModule({ | |
declarations: [AppComponent, ActivitiesComponent, HomeComponent, LoginComponent], | |
imports: [BrowserModule, AppRoutingModule, FormsModule, HttpClientModule], | |
providers: [{ provide: ErrorHandler, useClass: ApplicationInsightsErrorHandler }], | |
bootstrap: [AppComponent] | |
}) | |
export class AppModule {} |