Skip to content

feat: apply unified HTTP semantic conventions to resource timing#232

Draft
martinkuba wants to merge 5 commits into
open-telemetry:mainfrom
martinkuba:resource-timing-unified-semantics
Draft

feat: apply unified HTTP semantic conventions to resource timing#232
martinkuba wants to merge 5 commits into
open-telemetry:mainfrom
martinkuba:resource-timing-unified-semantics

Conversation

@martinkuba
Copy link
Copy Markdown
Contributor

@martinkuba martinkuba commented Apr 15, 2026

This is a draft PR to demonstrate how the unified HTTP client network timing conventions from semantic-conventions#3385 would look when applied to the resource timing instrumentation. The goal is to provide a concrete implementation to inform discussion.

Changes

  • Event name: browser.resource.timingbrowser.resource_timing
  • Timing attributes: Moved from browser.resource.* to http.* namespace (e.g., http.call.start_time, http.dns.start_time, http.connect.start_time)
  • Delta time model: http.call.start_time is absolute (ms since epoch); all other timing attributes are deltas from it. Browser API values of 0 (phase did not occur) are omitted.
  • Protocol parsing: nextHopProtocol split into network.protocol.name + network.protocol.version
  • New attributes: http.response.status_code, http.response.header.content-type, http.response.body.encoded_size, http.response.body.decoded_size
  • Reuses existing semconv attributes where available: url.full, http.response.status_code, http.response.size, network.protocol.name, network.protocol.version

Attribute mapping

Browser API field Attribute Notes
fetchStart http.call.start_time Absolute timestamp (ms since epoch)
responseEnd http.call.end_time Delta from start_time
duration http.call.duration Total duration (ms)
redirectStart/End http.redirect.start_time/end_time Omit if 0
domainLookupStart/End http.dns.start_time/end_time Omit if 0
connectStart/End http.connect.start_time/end_time Omit if 0
secureConnectionStart http.secure_connect.start_time Omit if 0
requestStart http.request.headers.start_time Omit if 0
responseStart http.response.headers.start_time Omit if 0
workerStart http.worker.start_time Omit if 0
transferSize http.response.size
encodedBodySize http.response.body.encoded_size New; see semconv#3406
decodedBodySize http.response.body.decoded_size New; see semconv#3406
responseStatus http.response.status_code Omit if 0
contentType http.response.header.content-type
name url.full
nextHopProtocol network.protocol.name + .version Parsed
initiatorType browser.resource.initiator_type Browser-specific
renderBlockingStatus browser.resource.render_blocking_status Chromium only

Here is what user would see in the browser dev console when debugging:

image

And this corresponds to this resource timing object:

image

Open questions for discussion

Key concerns — should we adopt the unified conventions for browser?

  • Non-intuitive mapping: The mapping between these unified attributes and the well-known PerformanceResourceTiming fields is not obvious. Developers familiar with the browser API will need to learn a new naming scheme.
  • Relative timestamps differ from browser API: The browser reports values relative to timeOrigin; this convention uses deltas relative to request start. Anyone cross-referencing DevTools with telemetry data will see different values for the same phase.
  • Mixed absolute/relative is confusing: http.call.start_time is ~1.7 trillion while http.call.end_time is ~100 — looks like a bug when eyeballing raw data.

Follow-up items if we adopt the unified conventions

  • DNS namespace: http.dns.start_time vs dns.start_time — DNS is not HTTP-specific
  • Redundant attributes: http.call.duration and http.call.end_time are always identical
  • startTime vs fetchStart: startTime is the true beginning (includes redirects), fetchStart is after redirects. Which should http.call.start_time represent?
  • transferSize: 0 semantics: Means cache hit — should it be sent as explicit signal or omitted?
  • Body size ambiguity: http.response.body.size is ambiguous (see semconv#3406); this PR uses explicit encoded_size / decoded_size instead

@martinkuba
Copy link
Copy Markdown
Contributor Author

martinkuba commented Apr 16, 2026

For comparison, here is what users would see now in the browser console
image

Compared to what they would see with the unified HTTP semantics
image

@surbhiia
Copy link
Copy Markdown

surbhiia commented Apr 21, 2026

@martinkuba As we discussed yesterday and you pointed out that there's a solution to the following concerns:

Concern:

Relative timestamps differ from browser API: The browser reports values relative to timeOrigin; this convention uses deltas relative to request start. Anyone cross-referencing DevTools with telemetry data will see different values for the same phase.
Mixed absolute/relative is confusing: http.call.start_time is ~1.7 trillion while http.call.end_time is ~100 — looks like a bug when eyeballing raw data.

Solution:

  • We can remove the http.call.start_time attribute in favor of the Event Timestamp filed as these two are similar.
  • Browser would continue populating the values it receives from the API which are already deltas from timeOrigin and mobile would add delta time from Event Timestamp field.

For the other remaining concern:

Non-intuitive mapping: The mapping between these unified attributes and the well-known PerformanceResourceTiming fields is not obvious. Developers familiar with the browser API will need to learn a new naming scheme.

You mentioned the browser sig thought of providing flexibility to the customers on choosing which semantic conventions to use and keep both browser specific and unified semantic conventions. Can you please add this proposal to the unified semantics issue?


Regarding the follow up items:

Follow-up items if we adopt the unified conventions

  • DNS namespace: http.dns.start_time vs dns.start_time — DNS is not HTTP-specific
  • Redundant attributes: http.call.duration and http.call.end_time are always identical
  • startTime vs fetchStart: startTime is the true beginning (includes redirects), fetchStart is after redirects. Which should http.call.start_time represent?
  • transferSize: 0 semantics: Means cache hit — should it be sent as explicit signal or omitted?
  • Body size ambiguity: http.response.body.size is ambiguous (see It is not clear if http.response.body.size is intended for encoded or decoded size semantic-conventions#3406); this PR uses explicit encoded_size / decoded_size instead

My responses to above items:

  • As here we're talking about HTTP timing event, we're looking at dns, tls in terms of an HTTP request, we could rename the attribute to dns.start_time if everyone agrees to that. Can you please add a proposal for this as well in the unified semantics issue?
  • Does any browser use case need http.call.duration attribute in the event? We did not have it in the unified semantics proposal because it should be derived from existing attributes -> http.call.end_time - http.call.start_time (or Event Timestamp if that is used instead of http.call.start_time)
  • For the remaining three items in above list - I think these are new items that came up that we can discuss and decide a path forward. Would you be able to add your or browser sig's proposal for these as well in the unified semantic issue? Thanks!

@surbhiia
Copy link
Copy Markdown

surbhiia commented Apr 22, 2026

@martinkuba I got a chance to look at the remaining items not covered in above response and here are my responses:

  • http.call.start_time should be the overall start time including redirects i.e before fetchStart. So, you might need a new attribute to mark the fetchStart for browser.

    • Note about resends/redirects on mobile - If there are resends/redirects leading to multiple requests in effect and multiple spans where there are span instrumentations, each request/span will have a corresponding network timing event so http.call.start_time would capture when the first phase for that request started - which could be dns.start_time or connection.start_time or request.start_time based on whether domain name was same or different on that resend/redirect. Mobile also adds a http.request.resend_count to identify these.
    • The browser seems to be capturing it all in one network timing event in case of redirects and using additional attributes like http.redirect.start_time and http.redirect.start_time to capture relevant redirect data? That's perhaps another notable difference between Browser and Mobile.
  • I think if there's a use case to differentiate between 0 vs null then you should set it otherwise omitting is better to reduce amount of data stored/transferred/read.

  • We can perhaps use simple attribute http.response.body.size in mobile and dedicated attributes in browser. Or use http.response.body.size in browser for whatever it makes the most sense for - the compressed or decompressed size and introduce a separate attribute for the remaining kind.

@martinkuba
Copy link
Copy Markdown
Contributor Author

@surbhiia

The browser seems to be capturing it all in one network timing event in case of redirects and using additional attributes like http.redirect.start_time and http.redirect.start_time to capture relevant redirect data?

Yes, this is correct. This diagram shows how the different timestamps relate to each other:
timestamp-diagram

taken from here:
https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming#timestamps

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.

3 participants