angularspartacus-storefrontdynatrace

How to log the time of http requests in Spartacus SSR, even after the SSR timeout


How to log the time of http requests made in the Spartacus Angular SSR app, even after the SSR timeout (which sent the CSR fallback to a client)?

Context: In the the monitoring tool like dynatrace you can see a waterfall chart showing the duration of the rendered request, including also the http calls made by the rendered app to external services (e.g. OCC). However, when the Spartacus SSR returns a CSR fallback (due to a SSR request timeout), dynatrace stops showing the http calls that the rendered app is making. It's important to emphasize, that even after sending a CSR fallback by the ExpressJS server, the Angular SSR app keeps being rendered in the background and can still make http calls. When those http calls take too long, it would be good to debug which of those http calls took so long. How to debug duration of those http calls? Ideally, knowing whether the CSR fallback was already sent to a client...


Solution

  • For debugging purposes, you can provide an Angular HttpInteceptor that logs time of every http request made by the Angular app. Btw. it can also indicate if the response was already sent to the client by the ExpressJS engine (e.g. due to a SSR request timeout).

    See the example implementation:

    import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { tap } from 'rxjs/operators';
    import { Inject, InjectionToken, Optional } from '@angular/core';
    import { RESPONSE } from '@nguniversal/express-engine/tokens';
    import { Response } from 'express';
    
    export class LoggingInterceptor implements HttpInterceptor {
      constructor(@Optional() @Inject(RESPONSE) private response: Response) {}
    
      intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const started = Date.now();
        return next.handle(request).pipe(
          tap(
            _event => {
              console.log(
                `Request for ${request.urlWithParams} took ${Date.now() - started} ms. ` +
                `Was ExpressJS Response already sent?: ${this.response?.headersSent}`
              );
            },
            _error => {
              console.log(
                `Request for ${request.urlWithParams} failed after ${Date.now() - started} ms. ` +
                `Was ExpressJS Response already sent?: ${this.response?.headersSent}`
              );
            }
          )
        );
      }
    }
    

    Explanation:

    Note: If you want to also console.log the URL of the currently rendered page in SSR, you can inject WindowRef from @spartacus/core and log it’s property windowRef.location.href.