Skip to content
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

add request duration metadata to network breadcrumbs #1903

Merged
merged 9 commits into from
Jan 25, 2023

Conversation

yousif-bugsnag
Copy link
Contributor

@yousif-bugsnag yousif-bugsnag commented Jan 17, 2023

Goal

Adds a new metadata field duration to network breadcrumbs for JS and Electron - this is the elapsed time in milliseconds between the request start and completion or error

Design

  • plugin-network-breadcrumbs

    • For XMLHttpRequest :
      • Override request object's send method in order to record the start time of the request, and get the duration in milliseconds when handleXHRLoad / handleXHRError are invoked
    • For fetch:
      • Record start of request when calling native fetch and get the duration in milliseconds whenhandleFetchSuccess / handleFetchError are invoked
  • plugin-electron-net-breadcrumbs

    • Override request object's request.end method in order to record the start time of the request, and get the duration in milliseconds when the request / abort / error handlers are invoked

Testing

  • Unit tests:

    • Extended existing unit tests to check for new metadata field
  • e2e tests

    • Extended existing e2e tests to check for new metadata field
    • Added basic e2e tests for network breadcrumbs on Electron

@github-actions
Copy link

github-actions bot commented Jan 17, 2023

@bugsnag/browser bundle size diff

Minified Minfied + Gzipped
Before 43.90 kB 13.42 kB
After 44.11 kB 13.47 kB
± ⚠️ +208 bytes ⚠️ +51 bytes

code coverage diff

<temporarily disabled>

Generated by 🚫 dangerJS against 07fa693

@yousif-bugsnag yousif-bugsnag marked this pull request as ready for review January 17, 2023 16:47
Comment on lines 38 to 41
request.end = (...args) => {
requestStart = new Date()
originalEnd.apply(request, args)
}
Copy link
Member

Choose a reason for hiding this comment

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

we save the requestStart date on request.end? if that's correct I think a comment here would be nice

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Aah this is a good point actually - if the request is using chunked encoding that would only be the duration of the final chunk that was sent. Maybe it's better to set requestStart on the first write operation instead, or do something like this (cc @imjoehaines):

Suggested change
request.end = (...args) => {
requestStart = new Date()
originalEnd.apply(request, args)
}
let requestStart
// For chunked requests the request begins when the first chunk is written,
// otherwise the request begins when the last chunk is written
const originalWrite = request.write
request.write = (...args) => {
if (request.chunkedEncoding && !requestStart) requestStart = new Date()
originalWrite.apply(request, args)
}
const originalEnd = request.end
request.end = (...args) => {
if (!requestStart) requestStart = new Date()
originalEnd.apply(request, args)
}

Copy link
Contributor

Choose a reason for hiding this comment

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

request.end is what finalises the request, i.e. it makes sure that everything is actually sent. This is still a good point though — request.write can start the process of sending the request:

The first write operation may cause the request headers to be issued on the wire
https://www.electronjs.org/docs/latest/api/client-request#requestwritechunk-encoding-callback

So only using request.end means the duration may be wrong if we want to capture the duration from the point the request actually starts being sent — I doubt it will make a different most of the time in a real app TBH, especially with Date only having millisecond precision, but if there's a large request body it could take a non-trivial amount of time from writing it to the request with request.write and finishing the request with request.end

Maybe we need to use both request.write & request.end, recording the start time from whichever is called first? You have to call request.end but don't necessarily have to call request.write, so we can't just use request.write

Copy link
Contributor

@imjoehaines imjoehaines Jan 24, 2023

Choose a reason for hiding this comment

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

Replied at the same time as you @yousif-bugsnag!

What you suggested LGTM if it's only when using chunked encoding that write can start the request. Electron's docs aren't that specific so I'm not sure if there are other cases where write can start sending the request?

Edit: looks like write does only start sending when using chunked encoding: https://github.com/electron/electron/blob/ca3145a54716d864c2487f239f6ebd44989bb7ff/lib/browser/api/net.ts#L164

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cool, yep, looks that way - I've been doing some manual testing with a local http server and that tallies up with what I've observed (the connection is established on write only when request.chunkedEncoding = true)

Although looks like I could have just read the source! 😅

Co-authored-by: Joe Haines <hello@joehaines.co.uk>
@yousif-bugsnag yousif-bugsnag force-pushed the PLAT-9443/network-breadcrumb-duration branch from 97719e2 to 802f0d8 Compare January 24, 2023 15:37
@yousif-bugsnag yousif-bugsnag force-pushed the PLAT-9443/network-breadcrumb-duration branch from 802f0d8 to 07fa693 Compare January 24, 2023 17:55
@yousif-bugsnag
Copy link
Contributor Author

I've added some unit tests for the new duration logic but was finding that the unit tests for plugin-electron-net-breadcrumbs started flaking heavily again so I've reverted the previous change to reinstate these and updated the PR comment accordingly

@yousif-bugsnag yousif-bugsnag merged commit 0a3f9ad into integration/v8 Jan 25, 2023
@yousif-bugsnag yousif-bugsnag deleted the PLAT-9443/network-breadcrumb-duration branch January 25, 2023 10:14
@gingerbenw gingerbenw mentioned this pull request Aug 29, 2024
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