Lifecycle
Every trace needs at least one container span. A container is the unit of work Flare organises everything else around. In a browser that unit is a page view.
Browser container types
| Type | What it is |
|---|---|
browser_pageload |
The browser loading a document |
browser_navigation |
Your router swapping the view without loading a document |
browser_web_vital |
A page's late arriving vitals |
A browser trace is rooted in browser_pageload or browser_navigation. Everything else, so browser_fetch, browser_xhr and browser_component, reaches one of those two by following parentSpanId and never appears as a root span itself. A trace whose root is not a container type fails processing.
The PHP containers, and the optional php_application wrapper around them, are covered in the PHP lifecycle page.
What a browser trace looks like
You send spans as a flat list, in the order they finished. parentSpanId is what carries the shape:
spanId |
parentSpanId |
Type | Name |
|---|---|---|---|
2b3c…8192 |
1a2b…7081 |
browser_fetch |
GET /api/products/9f2c |
4d5e…a3b4 |
3c4d…92a3 |
browser_component |
PriceTag |
6f70…c5d6 |
3c4d…92a3 |
browser_component |
AddToCart |
3c4d…92a3 |
1a2b…7081 |
browser_component |
ProductPage |
1a2b…7081 |
null |
browser_pageload |
/products/{id} |
Which Flare displays as:
browser_pageload /products/{id}
├── browser_fetch GET /api/products/9f2c
└── browser_component ProductPage
├── browser_component PriceTag
└── browser_component AddToCart
PriceTag and AddToCart point at ProductPage, not at the page load. The flat list has nothing else to record that relationship with, so pointing every component at the container throws it away. Keeping it means a slow parent with fast children tells you the time went into the parent's own work.
The children also appear before their parent, and the root appears last. Components finish from the inside out, so that is the natural order to send them in. You do not have to sort the array. Flare reads the whole payload before resolving parents, so any order works.
Span events are the exception to all of this. They live in the events array of the span they belong to, so they really are nested inside it.
Each client-side route change starts a new trace with its own browser_navigation root. A single page app that runs for an hour produces many traces, not one enormous one.
Parent references across requests
Normally a span's parentSpanId has to point at a span in the same request. Flare finds a span's container by walking up the parent chain, so if the parent never arrived, the span drops out of the trace, and sometimes others with it. The request still returns a success response, so nothing tells you the data went missing.
Container spans are the exception. A container may name a parent that arrived in an earlier request.
This is the whole reason browser_web_vital is a container. It goes out minutes after its browser_pageload parent, in a request of its own, and still attaches to the right page. See Web vitals.