Differentiate browser vital metrics between 2 pages which are running in one script

Hello,
In my script I am visiting more than one page for example

  1. login page (Entering username and password and clicking “Sig in” button)
  2. dashboard page (navigating to dashboard page after login)

I found the following link to set different url values while defining the thresholds.

I added the following threshold into my script
thresholds: {
‘browser_web_vital_lcp’: [‘p(90) < 1000’],
‘browser_web_vital_lcp{url:https://xxxxxxx/my-dashboard#/sign-in/password }’: [‘p(90) < 100’],
‘browser_web_vital_lcp {url:https://xxxxxxx/my-dashboard#/dashboard}’: [‘p(90) < 100’],
},

But as you see from the following test result report, lcp metric value calculated only for one page

browser_data_received…: 9.5 MB 631 kB/s
browser_data_sent…: 165 kB 11 kB/s
browser_http_req_duration…: avg=114.79ms min=90µs med=56.91ms max=2.4s p(90)=225.81ms p(95)=309.28ms
browser_http_req_failed…: 0.55% ✓ 1 ✗ 180
browser_web_vital_cls…: avg=0.306377 min=0.306377 med=0.306377 max=0.306377 p(90)=0.306377 p(95)=0.306377
browser_web_vital_fcp…: avg=249ms min=249ms med=249ms max=249ms p(90)=249ms p(95)=249ms
browser_web_vital_fid…: avg=400µs min=400µs med=400µs max=400µs p(90)=400µs p(95)=400µs
browser_web_vital_inp…: avg=40ms min=40ms med=40ms max=40ms p(90)=40ms p(95)=40ms
✗ browser_web_vital_lcp…: avg=1.44s min=1.44s med=1.44s max=1.44s p(90)=1.44s p(95)=1.44s
✓ { url:https://xxxxxxx/my-dashboard#/dashboard }…: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s
✗ { url:https://xxxxxxx/my-dashboard#/sign-in/password }…: avg=1.44s min=1.44s med=1.44s max=1.44s p(90)=1.44s p(95)=1.44s
browser_web_vital_ttfb…: avg=197.16ms min=41.19ms med=77.79ms max=472.5ms p(90)=393.55ms p(95)=433.02ms
checks…: 100.00% ✓ 2 ✗ 0
data_received…: 0 B 0 B/s
data_sent…: 0 B 0 B/s
iteration_duration…: avg=12.88s min=12.88s med=12.88s max=12.88s p(90)=12.88s p(95)=12.88s
iterations…: 1 0.066235/s
vus…: 1 min=1 max=1
vus_max…: 1 min=1 max=1

Is there a way to get vital metric for each page visited in one script?

Thanks.

Hi!

Is it a single-page or a multi-page application? The LCP is only measured when a page is fetched from the server, i.e. a normal page navigation. If the app is using client-side routing, then the browser will consider it the same page. Looking at the URL:s in your thresholds, it looks like the app is using at least some client-side routing (hash-based to be more precise).

If there is a page navigation between sign-in and the dashboard page, then I’d need to do some diving to understand what’s going on.

Hi @johanallansson, sorry for my late response. I was off for a while. I just wanted to give answers to your questions as I spoke with one of our frontend developer.
Our application is a single-page application and we are using angular to build up our application.
And yes app is using client-side routing and as you already written browser consider it the same page.
Is there a way to get metric results for each page in one script?
And I want to learn your suggestions for this specific scenario.
Thanks in advance,
Mete

Hi again.

Yet another late response. My apologies.

I’m afraid that there’s little we can do at the moment. We are at the mercy of the capabilities of the browser and there’s currently no way to measure web vitals in a single page application. You can read the Chrome team’s explanation as to why here.

They are experimenting with APIs that would enable web vitals for single page applications, but as I understand it they are behind an experimental flag in Chrome and are nowhere stable yet.

What such an API would mean for k6 browser is too early to tell.

Depending on which metric you are interested in (seems like it’s LCP?), you could use a custom Trend metric to simulate these measurements yourself. Here’s some example code (not tested):

import { Trend } from "k6/metrics"

const loadTime = new Trend("load_time", true)

async function measure(page, fn) {
  const start = Date.now()

  const result = await fn()

  const end = Date.now()

  loadTime.add(end - start, {
    page: page
  })

  return result
}

export const options = {
  thresholds: {
    "load_time{page=welcome-page}": ['p(90) < 100']
  }
}

export default function () {
  // ... init browser, page, etc.

  await measure("welcome-page", () => {
    await locator('[data-testid="login-button"]').click();
    await locator('[data-testid="welcome-message"]').waitFor()
  })
}

The idea is basically to perform the action causing a navigation and then wait for some element that is indicative of the new content having been loaded (in a way it’s a more reliable measurement because you can set your own critiera for when a page has loaded, whereas the LCP is just a guess based on content being rendered).

I hope that helps. :slight_smile: