Skip to content

Add unique identifier to "PerformanceResourceTiming" API #1007

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

monica-ch
Copy link

Explainer doc for the feedback.

@noamr
Copy link

noamr commented Apr 8, 2025

Thanks for working on this! I'm a bit confused about how the solution (specifically option 1) maps to the use case.
Seems like the use case is about mapping resource timing entries to fetch events, but the solution in option 1 only deals with navigations and maps the clientId, which would be the same across resources?

This OP alludes to that but this explainer doesn't...

Another issue with this is that mapping a response to a clientId only works if you don't use caches, which often beats the purpose of using a service-worker in the first place. A Cache allows you to reuse responses across clients, and this kind of mapping would break on the first response reuse.

Copy link
Member

@fabiorocha fabiorocha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like both files are almost identical. I assume we only need one of them?

@monica-ch monica-ch marked this pull request as ready for review April 25, 2025 20:44
@monica-ch monica-ch changed the title Add explainer to expose client info on "PerformanceResourceTiming" API Add unique identifier to "PerformanceResourceTiming" API Apr 25, 2025
The payload of a performance.getEntriesByType("resource") or performance.getEntriesByType("navigation") call would then look like:

```
requestId: “123e4567-e89b-12d3-a456-426614174000”

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please replace smart quotes with regular quotes.

Suggested change
requestId: 123e4567-e89b-12d3-a456-426614174000
requestId: "123e4567-e89b-12d3-a456-426614174000"

Or

fetch('https://api.example.com/data', {
method: ‘GET’,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix smart quotes

Suggested change
method: GET,
method: 'GET',

[Would like a precise way to map PerformanceTimings to FetchEvent](https://github.com/w3c/resource-timing/issues/259)

## Introduction
[Resource Timing](https://www.w3.org/TR/resource-timing/) API has no information that uniquely identifies each resource timing to each fetch request. As such, in situations where resources are fetched multiple times, such as with multiple tabs or multiple requests to the same URL, it’s not possible to accurately map resource timings. This lack of clear mapping can hinder performance analysis and optimization efforts.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[Resource Timing](https://www.w3.org/TR/resource-timing/) API has no information that uniquely identifies each resource timing to each fetch request. As such, in situations where resources are fetched multiple times, such as with multiple tabs or multiple requests to the same URL, it’s not possible to accurately map resource timings. This lack of clear mapping can hinder performance analysis and optimization efforts.
The [Resource Timing](https://www.w3.org/TR/resource-timing/) API has no information that uniquely maps each resource timing to each fetch request. As such, in situations where resources are fetched multiple times, such as with multiple tabs or multiple requests to the same URL, it’s not possible to accurately map resource timings. This lack of clear mapping can hinder performance analysis and optimization efforts.


## Use Cases
Tracking resource timing across multiple requests, whether from different browsing contexts (e.g. multiple tabs) or service workers, can be challenging. Some examples include:
1. **Measuring Resource Timing Across Client and Service Worker** <br>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This <br> and the next <br> look weirdly out of place as the only embedded HTML in the document. Can you replace with an additional newline?

## Use Cases
Tracking resource timing across multiple requests, whether from different browsing contexts (e.g. multiple tabs) or service workers, can be challenging. Some examples include:
1. **Measuring Resource Timing Across Client and Service Worker** <br>
When multiple tabs request the same resource through a service worker, associating timing data between the Performance Resource Timing entries observed in the client and those within the service worker can be difficult. The client-side performance.getEntries() provide the total duration of the request, but it lacks insight into processes inside service worker, such as request handling and network retrieval. The service worker itself can collect performance timing for fetch requests, but there is no direct linkage between these entries and those in the client’s performance timeline.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
When multiple tabs request the same resource through a service worker, associating timing data between the Performance Resource Timing entries observed in the client and those within the service worker can be difficult. The client-side performance.getEntries() provide the total duration of the request, but it lacks insight into processes inside service worker, such as request handling and network retrieval. The service worker itself can collect performance timing for fetch requests, but there is no direct linkage between these entries and those in the client’s performance timeline.
When multiple tabs request the same resource through a service worker, associating timing data between the Performance Resource Timing entries observed in the client and those within the service worker can be difficult. The client-side `performance.getEntries()` provides the total duration of the request, but it lacks insight into processes inside the service worker, such as request handling and network retrieval. The service worker itself can collect performance timing for fetch requests, but there is no direct linkage between these entries and those in the client’s performance timeline.

event.respondWith((async () => {
const response = await fetch(event.request);
const entries = self.performance.getEntriesByType("resource");
const timing = entries.find(e => e.responseId === response.responseId);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the sample code in this document contains code something like this

      const entries = self.performance.getEntriesByType("resource"); 
      const timing = entries.find(e => e.responseId === response.responseId); 

Should we also be proposing a new Performance function to help find these entries?

partial interface Performance {
  PerformanceEntry getEntryById (DOMString id);
}
      const timing = self.performance.getEntryById(response.responseId); 

Adding a read-only `requestId` field on the Request interface.

```webidl
[ Exposed=Window, Worker ]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[ Exposed=Window, Worker ]
[Exposed=(Window,Worker)]

```js
self.addEventListener('fetch', event => {
const request = event.request;
console.log(request.requestId); '123e4567-e89b-12d3-a456-426614174000'

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
console.log(request.requestId); '123e4567-e89b-12d3-a456-426614174000'
console.log(request.requestId); // '123e4567-e89b-12d3-a456-426614174000'

Adding a read-only 'requestId' field on the Response interface.

```webidl
[ Exposed=Window, Worker ]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[ Exposed=Window, Worker ]
[Exposed=(Window, Worker)]

|Distinguish between identical requests from different clients. | ✅ |✅ | ✅ |
|Enables end-to-end correlation between requests, responses, and resource timings.| ❌ |✅| ❌ |
|Leverages existing identifiers (FetchEvent).| ❌ | ❌ | ✅ |
|Developers do not need to generate and manage RequestIds | ✅ |❌| ✅ |

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For option 2 I thought the request ID is optional and will be generated by the user agent if not provided? If so then 'Developers do not need to generate manage RequestIds' for option 2 is true - they don't need to. Maybe this row is supposed to be about removing flexibility for end devs to use their own IDs?

Copy link
Member

@fabiorocha fabiorocha left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM after pending comments are addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants