3

I'm working on an Angular app and try to analyse the performance of this app. For this I am using Elasticsearch's Kibana and APM server. The APM server is already able to measure the time for the inital page load and routing changes, by mainly getting the times for various HTTP requests. So far, so good.

But now I want to finetune this measurement because not every HTTP request happens during a route change. The situation is that on a site are multiple components, lots of them including PrimeNG tables (<p-table>) which are updated without a route change, e.g. when the user enters something into a search input.

So here is my approach to measure the lifetime of every component by creating a decorator @TimeTracking() which extends the Angular lifecycle hooks ngOnInit() and ngOnDestroy(). To get some more information about the component's life, I also measured the performance between ngDoCheck() and ngOnViewChecked().

export function TimeTracking(): ClassDecorator {
  return function(target: any) {
    const lifecycleHooks = ['ngOnInit', 'ngDoCheck', 'ngAfterViewChecked', 'ngOnDestroy'];

    lifecycleHooks.forEach(hook => {
      const original = target.prototype[hook];

      target.prototype[hook] = function ( ...args: any ) {
        if (hook === 'ngOnInit') {
          // start performance measurement of component
        } 
        else if (hook === 'ngDoCheck') {
          // start measurement of checking cycle
        } 
        else if (hook === 'ngAfterViewChecked') {
          // end measurement of checking cycle
        } 
        else if (hook === 'ngOnDestroy') {
          // end performance measurement for component
        }

        original && original.apply(this, args);
      };
    });
  };
}

The idea of this approach I got from How to test rendering speed in Angular and https://netbasal.com/inspiration-for-custom-decorators-in-angular-95aeb87f072c.

Additionally, I am also measuring the time for each HTTP request by using a HTTP interceptor:

@Injectable()
export class LoggingInterceptor implements HttpInterceptor {
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const t0 = performance.now();
    let okString: string;

    return next.handle(req)
    .pipe(
      tap(
        (event: HttpEvent<any>) => okString = event instanceof HttpResponse ? 'succeeded' : '',
        (error: HttpErrorResponse) => okString = 'failed'
      ),
      finalize(() => {
        console.log(`${req.method} "${req.urlWithParams}" ${okString} in ${performance.now() - t0} ms.`);
      })
    );
  }
}

To cut a long story short, here are my questions: What do you think about this approach? Do you have any further ideas or proposals for improvement? Is there any possibility to get information about which event has triggered the ngDoCheck() to get more information? Is it possible to match the measured HTTP requests (in the interceptor) to the component which triggered it?

rchrdmgwtz
  • 55
  • 2
  • In order to determine what would be the most effective approach, it would be useful if you could articulate more clearly the specific problem you're trying to solve. Slow page loads? – Robert Harvey Dec 04 '19 at 16:28
  • Yes, slow page loads is a problem I would like to solve too. But for that specific issue the APM server from Elasticsearch automatically collects data. My main problem is to determine why (sometimes) these primeNG tables load slowly when they are updated. To investigate that, I implemented these approaches above to get an insight into the component's lifecycle which are including these tables and would like to ask your opinions. – rchrdmgwtz Dec 06 '19 at 17:03
  • The usual way to troubleshoot performance problems is by measuring and profiling. Have you done these things to determine which parts of your code are the "hot spots," the ones that are causing most of the slowdowns? – Robert Harvey Dec 06 '19 at 17:04
  • I intend to do so with this code. But before bringing it in production I wanted to get some feedback. – rchrdmgwtz Dec 09 '19 at 07:10
  • How did this approach work out for you? I'm looking to do something similar. – kaszac Nov 26 '20 at 18:22

0 Answers0