angularfirebaseangularfirefirebase-performance

Angular Fire 19 performance not reporting to console


Problem

I'm having trouble getting performance monitoring, built into the sdk (https://firebase.google.com/docs/perf-mon/page-load-traces), to show up in the Firebase Console.

What I've tried

export function provideFirebaseForApp(
  options: FirebaseOptions,
  siteKey: string,
  isDevMode: boolean = false
) {
  return makeEnvironmentProviders([
    provideFirebaseApp(() => initializeApp(options)),
    provideAppCheck(() => {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      (window as any).FIREBASE_APPCHECK_DEBUG_TOKEN = isDevMode;
      return initializeAppCheck(getApp(), {
        provider: new ReCaptchaEnterpriseProvider(siteKey),
        isTokenAutoRefreshEnabled: true,
      });
    }),
    provideFirestore(() => {
      const firestore = getFirestore();
      // if (isDevMode()) connectFirestoreEmulaor(firestore, 'localhost', 8080);
      return firestore;
    }),
    provideAuth(() => getAuth()),
    provideFunctions(() => {
      const functions = getFunctions();
      // connectFunctionsEmulator(functions, 'localhost', 5001);
      return functions;
    }),
    provideStorage(() => getStorage()),
    provideDatabase(() => getDatabase()),

    provideAnalytics(() => getAnalytics()),
    ScreenTrackingService,
    UserTrackingService,
    providePerformance(() => getPerformance()),
  ]);
}
@Component({
  selector: 'app-root',
  imports: [NavigationComponent],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  private appCheck = inject(AppCheck);
  private performance = inject(Performance);

  constructor() {
    console.log(
      this.performance.dataCollectionEnabled,
      this.performance.instrumentationEnabled
    );
  }
}

The console output indicates true for both values

@Component({
  selector: 'app-login-page',
  imports: [
    RouterLink,
    ReactiveFormsModule,
    MatFormFieldModule,
    MatInputModule,
    MatCardModule,
    MatButtonModule,
  ],
  templateUrl: './login-page.component.html',
  styleUrls: ['./login-page.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export default class LoginPageComponent {
  readonly #performance = getPerformance();
  readonly #fb = inject(FormBuilder);
  readonly #router = inject(Router);
  readonly #auth = inject(AuthService);
  readonly #snacks = inject(MatSnackBar);
  readonly mfaResolution = injectMultiFactorErrorResolution();

  readonly loading = signal(false);

  readonly form = this.#fb.nonNullable.group({
    email: ['', [Validators.required, Validators.email]],
    password: ['', [Validators.minLength(8), Validators.required]],
  });

  protected async onSubmit() {
    this.loading.set(true);
    const { email, password } = this.form.getRawValue();

    const loginTrace = trace(this.#performance, 'login');
    try {
      loginTrace.start();
      const credential = await this.#auth.login(email, password);
      this.#snacks.open(
        `Welcome back, ${credential.user.displayName || credential.user.email}!`
      );
      loginTrace.putAttribute('verified', `${credential.user.emailVerified}`);
      loginTrace.stop();
      this.#router.navigate(['/']);
    } catch (error) {
      if (error instanceof FirebaseError) {
        loginTrace.putAttribute('errorCode', error.code);
        loginTrace.stop();
        switch (error.code) {
          case 'auth/user-not-found':
          case 'auth/wrong-password':
            this.#snacks.open('Invalid email or password');
            break;
          case 'auth/multi-factor-auth-required':
            await lastValueFrom(this.mfaResolution(error as MultiFactorError));
            this.#router.navigate(['/']);
            break;
          default:
            this.#snacks.open('An unknown error occurred');
            if (isDevMode()) console.error(error);
            break;
        }
      }
    }

    this.loading.set(false);
  }
}

Versions

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/
    

Angular CLI: 19.2.13
Node: 20.18.3
Package Manager: npm 11.4.1
OS: linux x64

Angular: 19.2.13
... animations, cli, common, compiler, compiler-cli, core
... elements, forms, platform-browser, platform-browser-dynamic
... router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1902.13
@angular-devkit/build-angular   19.2.13
@angular-devkit/core            19.2.13
@angular-devkit/schematics      19.2.13
@angular/cdk                    19.2.17
@angular/fire                   19.2.0
@angular/google-maps            19.2.17
@angular/material               19.2.17
@schematics/angular             19.2.13
ng-packagr                      19.2.2
rxjs                            7.8.2
typescript                      5.6.3
zone.js                         0.15.1

Console Output

I noticed that when I have the Performance injection happen, I begin getting this in the console at various times on each page refresh:

enter image description here

The call stack on this doesn't seem to give any clue as to where this is coming from in modules I recognize. But I get the impression that I'm seeing performance failing to do something and retrying several times before giving up.

Other Firebase services

All other firebase services in the provideFirebaseForApp function seem to be working just fine. So is this maybe an issue with something outside my code? The SDK is enabled in the console, it is just void of events entirely.

Other projects

I have evidence of the performance functionality working on a project that was using Angular 17.0, with the importProvidersFrom function we used to have to call surrounding the provide[Service](...) calls. For example:

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideAnimations(),
    provideHttpClient(),
    importProvidersFrom(
      BuilderModule.forRoot(environment.builderPublicKey),
      provideFirebaseApp(() => initializeApp(environment.firebase)),
      provideFirestore(() => getFirestore()),
      provideStorage(() => getStorage()),
      provideAuth(() => getAuth()),
      provideAnalytics(() => getAnalytics()),
      provideAppCheck(() =>
        initializeAppCheck(getApp(), {
          provider: new ReCaptchaEnterpriseProvider(
            environment.appCheckSiteKey
          ),
          isTokenAutoRefreshEnabled: true,
        })
      ),
      providePerformance(() => getPerformance()),
      provideFunctions(() => getFunctions())
    ),
    ScreenTrackingService,
    UserTrackingService,
  ],
};

This project currently IS reporting performance to its corresponding console in the Firebase Console.


Solution

  • This has been resolved by firebase and I would imagine the next version will have this issue resolved: https://github.com/firebase/firebase-js-sdk/issues/9067#event-18340390531