DEV Community

Julien Dubois for Microsoft Azure

Posted on • Updated on

Using Azure Application Insights with Angular (5/7)

This blog post is part of a series on "deploying a Spring Boot and Angular application on Azure", here is the full list of posts:

Azure Application Insights and Angular

In the previous blog post, we configured Azure Application Insights with Spring Boot, so we could monitor our server-side application. But what about our client-side application? And how about doing joint dashboards, showing both server-side and client-side data, in order to better understand why our user feel that our application is slow?

We're going to do all this in this blog post, by configuring our existing Application Insights instance to also monitor client-side data.

Installing Application Insights for Angular

First of all, be careful! There is a very popular and official applicationinsights-js library, and in you should not use it! This version is packaged as an AMD module, which will cause issues with our unit tests. There's a new version, packaged as an UMD module, that will work everywhere, and which has a new (and better!) name: @microsoft/applicationinsights-web. At the time of this writing, nearly nobody uses this new and improved release, so we hope to change this thanks to this blog post!

First of all, install this library by doing npm i --save @microsoft/applicationinsights-web@2.0.0.

Now we need to configure it, and please note that your Azure Application Insights instrumentation key will be public (but that shouldn't cause any trouble):

private appInsights = new ApplicationInsights({
  config: {
    instrumentationKey: 'a8aca698-844c-4515-9875-fb6b480e4fec'
  }
});

// ...

this.appInsights.loadAppInsights();

Then, in order to record what users do on the application, we have hooked this mechanism on the Angular Router: each time a route changes, an event will be sent to Azure Application Insights, so we can record what people are doing.

Here is the Angular service we created:

import { Injectable, OnInit } from '@angular/core';
import { ApplicationInsights } from '@microsoft/applicationinsights-web';
import { ActivatedRouteSnapshot, ResolveEnd, Router } from '@angular/router';
import { filter } from 'rxjs/operators';
import { Subscription } from 'rxjs';

@Injectable()
export class ApplicationInsightsService {
  private routerSubscription: Subscription;

  private appInsights = new ApplicationInsights({
    config: {
      instrumentationKey: 'a8aca698-844c-4515-9875-fb6b480e4fec'
    }
  });

  constructor(private router: Router) {
    this.appInsights.loadAppInsights();
    this.routerSubscription = this.router.events.pipe(filter(event => event instanceof ResolveEnd)).subscribe((event: ResolveEnd) => {
      const activatedComponent = this.getActivatedComponent(event.state.root);
      if (activatedComponent) {
        this.logPageView(`${activatedComponent.name} ${this.getRouteTemplate(event.state.root)}`, event.urlAfterRedirects);
      }
    });
  }

  setUserId(userId: string) {
    this.appInsights.setAuthenticatedUserContext(userId);
  }

  clearUserId() {
    this.appInsights.clearAuthenticatedUserContext();
  }

  logPageView(name?: string, uri?: string) {
    this.appInsights.trackPageView({ name, uri });
  }

  private getActivatedComponent(snapshot: ActivatedRouteSnapshot): any {
    if (snapshot.firstChild) {
      return this.getActivatedComponent(snapshot.firstChild);
    }

    return snapshot.component;
  }

  private getRouteTemplate(snapshot: ActivatedRouteSnapshot): string {
    let path = '';
    if (snapshot.routeConfig) {
      path += snapshot.routeConfig.path;
    }

    if (snapshot.firstChild) {
      return path + this.getRouteTemplate(snapshot.firstChild);
    }

    return path;
  }
}

(You can see the whole file here)

Please note that we have created setUserId() and clearUserId() methods: we will use them when a user authenticates or logs out of the application, so we can better track what individuals are doing. We hooked those methods in the account.service.ts file generated by JHipster, so we could directly use the account login.

Also, user data is sent when the browser window is closed, which is very good in production, but might be annoying in development. One interesting method to use is appInsights.flush();, which will force the data to be sent. This could be used in development in our new Angular service, in order to test it more easily.

As this part required quite a lot code, check this commit to see all the details that we have changed to make this part work. Please note that we needed to mock the Azure Application Insights service in our tests, and this is why we needed to use the UMD module.

Using Application Insights to track users

As we are tracking user sessions as well as logins, we can have very detailed informations on our users' behavior, and also better understand the performance issues of our application.

The first thing you will probably do is just to check users and sessions on your website:

But you'll be able to do much more, for example you can check the flow of users in your application:

You will then be able to combine dashboards with data from the Spring Boot application, in order to better understand what your users do, and which issues they encounter.

This will lead us to our next two blog posts, on improving both client-side and server-side performance. Thanks to Azure Application Insights we will be able to make the right choices, and better understand if our performance tunings have the right impact.

Top comments (10)

Collapse
 
shimjithkumar profile image
shimjithkumar

Hi, thanks for the above article
I am trying to integrate azure insight to my angular-7 application.
this are any questions, any help is appreciated.

  • Is there any difference by adding the insight through npm vs html script in header as mentioned in the azure insight doc.

  • One of my requirement is that to track how long a user stayed(duration) in each
    page and what all event user clicked. how track this.

Thanks

Collapse
 
jdubois profile image
Julien Dubois

I would rather use a package manager than adding the HTML script manually, especially as you already have one set up with Angular. It will be easier to manage versions, etc... And also this allows to have everything in one or several bundles packaged by Webpack, so better performance in the end.
What I do in this post should give you the time the user stayed on your application, and give you events for each route change: that seems enough, but if you want more events (not just route changes) you can use the same principle on any user action. Of course, if you abuse this, you might reach a quota on Azure Insights, and also that might send quite a lot of user requests (might slow down the app, maybe some users will be concerned about this, so this opens up quite a lot of other issues).

Collapse
 
shimjithkumar profile image
shimjithkumar

Thanks for the update. I installed the library.
where I need to configure the instrumentation key(the first code snippet)?
how to add the service you created(the second code) ?
Thanks in advance.

Thread Thread
 
jdubois profile image
Julien Dubois

As you can check in this commit I stored the key (look for instrumentationKey) in a dedicated Angular service. We could of course do better, but that key will be shared publicly at some point (as it is used to send the data), and it's probably not going to change much, so that solution should be good enough for most people.
Once the service is created, it is just a normal Angular service, so you need to inject it wherever you need it. In the example, it is done in the constructor of the Account service -> you just reference the Insight Service there, and then you can use it.

Thread Thread
 
shimjithkumar profile image
shimjithkumar

Thanks for the help, basic implementation is just done now with login, will test tomorrow morning and let you know the result, thanks

Thread Thread
 
shimjithkumar profile image
shimjithkumar

Hope every thing looks good expect below issue

passed all param for setAuthenticatedUserContext(validatedId, accountId, boolean) boolean is for saving the details in cookie,. we have two unique ides for the application so passed both in validateId and in accountId boolean made as true. not sure this is a correct approach

the page name is captured as with component name like "HomeComponent home".

Thread Thread
 
shimjithkumar profile image
shimjithkumar

the page view duration capture is not accurate, same second is captured for all pages. any help is appreciated

Collapse
 
atlas361 profile image
Atlas361

I downloaded your Angular Demo from github.com/dmnk/application-insigh... and installed all the NPM packages and then ran the project but I get this error "ERROR TypeError: this.appInsights.loadAppInsights is not a function" from Line 19 in the app.component.ts file?

I would love to get this working and would appreciate any help! Thanks

Collapse
 
jdubois profile image
Julien Dubois

I understand you installed the packages, but did you write the code from the blog post? The first thing we do is defining the appInsights function, and given your error is looks like it is not yet in your code.
If that can help, you can see all the changes I did in my code in this commit: github.com/jdubois/spring-on-azure...

Collapse
 
harishankar0301 profile image
Harishankar • Edited

How to get errors in console of web app to application insights?