Skip to content

Tabs and dialogs

An error on the payment screen says view payment › Attachment, so you know the attachment dialog was open on top of it.

A page is navigation. A tab, a checkout step or a dialog inside it is a view. A page-level label cannot say that the error happened with the attachment dialog open, and a breadcrumb cannot either, because a breadcrumb is a step the user took. A view is where they were.

Mark the places that matter in your markup, and turn views on once at startup.

src/main.ts
import { enableViews } from '@dasasian/firebase-structured-logger/client/views'
enableViews()
<section data-fsl-view="payment">…</section>
<div class="modal" data-fsl-view="Attachment">…</div>

An entry written while both are visible has the label view: "payment › Attachment". With nothing marked visible, there is no view label. To find every entry written with that dialog open, filter the Logs Explorer for labels.view:"Attachment". Calling enableViews() again does nothing more.

enableViews lives in its own entry point, /client/views, not in /client. If your app has a shared modal component, put the mark there and pass the name in as a prop, so every dialog is marked once.

The logger finds the visible marks at the moment the entry is written, in page order, and joins their names with ›. There are no open or close calls and nothing to keep in sync. A closed dialog is not visible, so it is not in the label.

Visible means what the browser says. checkVisibility() counts display: none, visibility: hidden and opacity: 0 on the mark or any parent. Browsers without it, Safari before 17.4, count only display: none.

Order is page order. A modal rendered at the end of <body>, such as a React portal or a Vue <Teleport>, comes after the page, so it reads payment › Attachment. If an order reads wrong, move the mark.

The logger never reads the page’s text, so a fixed name holds no personal data. Mark places, not items: a mark on every row of a list gives row › row › row …. Mark the list once.

  • The label shows what was on screen when the entry was written, not when the trouble started. An error that surfaces after a request finishes shows whatever is open then.
  • The view is not part of the repeat count, so the same error in two dialogs on one screen counts as one error. Repeat summaries have no view.
  • Only browser entries have view. Entries your Cloud Functions write do not. Follow the trace id to the browser entry. Browser entries sent through your log function keep it.
  • Marks inside a web component’s shadow root are not found.
  • A dialog is not a breadcrumb. The click that opened it is a bc.action, covered in breadcrumbs.

Made by Dasasian