Tracepanel

Angular

Record the pages of an Angular app in the browser, each view and click with the API calls it made, and put the panel on them.

Tracepanel records the pages of an Angular app in the browser. Each view and each click is a trace, with the API calls it made, its errors and its console output. The panel sits on the app's pages, and lists each click with its calls under it.

Add it to your app

Install @tracepanel/js in the Angular app:

npm install @tracepanel/js

Add provideTracepanel() to the app's providers:

// src/app/app.config.ts
import type { ApplicationConfig } from "@angular/core";
import { provideHttpClient } from "@angular/common/http";
import { provideRouter } from "@angular/router";
import { provideTracepanel } from "@tracepanel/js/angular";
import { routes } from "./app.routes";

export const appConfig: ApplicationConfig = {
  providers: [
    provideRouter(routes),
    provideHttpClient(),
    provideTracepanel({ service: "shop-web" }),
  ],
};

service names the app in the console. It is browser by default. Tracepanel supports Angular 20 and newer.

The recording starts as Angular makes the app's injector, before any of your services. So it sees every call HttpClient makes, on fetch() or on XMLHttpRequest. It also puts the panel's script into the page.

Send the console on

The panel and the recording talk to the console at /__tracepanel__/ on the page's origin. ng serve sends it on with its proxy, as it does your API.

A backend in Python or Java, or a Next.js app, serves its own console. Send both paths to it:

{
  "/api": { "target": "http://127.0.0.1:8000" },
  "/__tracepanel__": { "target": "http://127.0.0.1:8000" }
}

Save it as proxy.conf.json and start the dev server with it. The proxyConfig option of ng serve in angular.json does the same:

ng serve --proxy-config proxy.conf.json

An Express, Fastify or other Node.js backend serves no console. Its agent does. Start the agent with tracepanel dev in the backend's directory, before the backend:

npx @tracepanel/js dev

It serves the console on http://127.0.0.1:8765/. The backend finds the agent and sends its traces to it. Send /__tracepanel__/ there, with the prefix taken off:

{
  "/api": { "target": "http://127.0.0.1:3000" },
  "/__tracepanel__": {
    "target": "http://127.0.0.1:8765",
    "pathRewrite": { "^/__tracepanel__": "" }
  }
}

Read what users do

Each view of a page is a trace: its load, or a route change. So is each action on it:

  • a click or a submit that called the API or threw, named after its control, such as click "Borrow"
  • calls the page made in the background, which no one started

A view is named by the route the router matched, such as /books/:id, so every book's page is one page in the console. Its path, such as /books/2, stays with it. An action is named on its route, such as /books/:id › click "Borrow".

A view or an action keeps its calls, its errors and its console output, with the line that logged each record. It lasts until its last call answered. The console lists them in Pages. See Pages in the browser.

An error in an event handler or a component never reaches window. Angular catches it and hands it to its ErrorHandler. Tracepanel takes each error from the app's ErrorHandler first, whichever it is, and the click that threw it fails. Your handler gets the error as before.

An error your code catches itself stays out. Pass it to report() to fail the click it happened in:

import { report } from "@tracepanel/js/angular";

this.api.borrow(id).subscribe({ error: (error) => report(error) });

Call an API on another origin

A call to the page's own origin, such as /api/ through the proxy, carries a W3C traceparent. The console links it to the API's trace. To link calls to another origin too, name it in propagateTo:

provideTracepanel({ service: "shop-web", propagateTo: ["http://127.0.0.1:8000"] });

That origin's CORS must allow the traceparent and X-Tracepanel-Profile headers. See Pages in the browser.

Development only

provideTracepanel() works in a development build, such as ng serve's. In a production build it does nothing, and the build leaves it out of the bundle.

The console answers only this machine when a backend serves it. Through the dev server's proxy, the backend sees the proxy's address. Keep ng serve on localhost, its default, so no other machine reaches the console.

On this page