-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
feat(profiling): js self profiling #7273
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
Conversation
size-limit report 📦
|
… causing long spans again
Replay SDK metrics 🚀
develop |
Revision | LCP | CLS | CPU | JS heap avg | JS heap max | netTx | netRx | netCount | netTime |
---|---|---|---|---|---|---|---|---|---|
4b95c04 | +57.56 ms | -0.00 ms | +7.94 pp | +920.88 kB | +1.05 MB | +2.21 kB | +41 B | +1 | +90.32 ms |
e60cd02 | +56.25 ms | -0.00 ms | +6.32 pp | +927.44 kB | +1.06 MB | +2.21 kB | +41 B | +1 | +117.55 ms |
e25c067 | +48.34 ms | +0.00 ms | +5.59 pp | +926.37 kB | +1.05 MB | +2.22 kB | +41 B | +1 | +65.23 ms |
b1b249b | +43.88 ms | +0.00 ms | +4.80 pp | +937.99 kB | +1.05 MB | +2.22 kB | +41 B | +1 | +111.56 ms |
12e34d4 | +28.57 ms | +0.00 ms | +5.77 pp | +930.12 kB | +1.04 MB | +2.26 kB | +41 B | +1 | +109.67 ms |
c46c56c | +65.45 ms | -0.00 ms | +5.38 pp | +930.26 kB | +1.07 MB | +2.21 kB | +41 B | +1 | +91.29 ms |
7f4c4ec | +56.64 ms | -0.00 ms | +5.57 pp | +927.42 kB | +1.06 MB | +2.21 kB | +41 B | +1 | +110.83 ms |
00d2360 | +55.18 ms | +0.00 ms | +2.23 pp | +934.14 kB | +1.05 MB | +2.22 kB | +41 B | +1 | +71.65 ms |
Last updated: Mon, 27 Feb 2023 00:20:25 GMT
Are those replay metrics accurate? I did not make any changes to replay and unless profiling is installed and enabled, the metrics should not be impacted 🤔 |
@JonasBa honestly I kinda ignore them but from what I've seen they're pretty fluctuating. |
Since this is a large PR to review, some comments on how it works: TLDR:
Longer explanation: A naive solution would be to await profiler.stop and block transaction.finish which would delay transaction.finish as well as block the event loop (from some testing, that can be in the range of hundreds of ms) which makes it prohibitive. The second solution and the one I opted for was to introduce an event cache in our profiling integration which stores events that are carrying the profile context - this removes the need for awaiting profiler.stop at the expense of possibly dropping profiles (if the corresponding transaction event cannot be pulled from the cache, we cannot construct a profiling envelope). We would be dropping profiles in the event that max active transactions exceeds N (where N is the cache size = 20 = magic number. I'm open to increasing/decreasing that number, but my senses tell me that it is probably unlikely that more than 20 transactions would be active in the browser). Supporting browser tracing |
@@ -0,0 +1,254 @@ | |||
import { WINDOW } from '@sentry/browser'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exported code here is responsible for providing both the implementation of the patched startTransaction functionality (wrapTransactionWithProfiling) and the code that performs the patching addExtensionMethods
@@ -0,0 +1,10 @@ | |||
import { addExtensionMethods, wrapTransactionWithProfiling } from './hubextensions'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reexports the integration and patches the carrier
* rely on being able to pull the event from the cache when we need to construct the envelope. This makes the | ||
* integration less reliable as we might be dropping profiles when the cache is full. | ||
*/ | ||
export class BrowserProfilingIntegration implements Integration { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Listens for processed events with profile context and stores them in the cache
@@ -0,0 +1,400 @@ | |||
import { WINDOW } from '@sentry/browser'; | |||
import type { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of this is mostly about constructing the profile envelope and converting from JS sampled format to the one we expect in Sentry
f292041
to
42a9639
Compare
42a9639
to
d62e3aa
Compare
@lforst profiling logic has been moved under the browser package so this is now ready for another review :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super clean PR 👌 Just some minor stuff.
Co-authored-by: Luca Forstner <[email protected]>
Co-authored-by: Luca Forstner <[email protected]>
This pr adds support for JS self profiling to @sentry/browser package. This is a POC stage and we want to test it on our sentry dashboard - the current approach is to take the js profiler output and convert it to our sample format. Due to overhead reasons I do not think this will be a good long term solution, but at least for now, it allows us to visualize the profiles and test the feasibility of the API without a significant investment.
To support automated browser instrumentation (route navigation), we had to make a small change to @sentry/tracing to support. Tldr, browser tracing uses idle transactions as opposed to regular transactions and our hubExtension patch was never being called. Thanks @k-fish for the help there.
I will be adding some more tests to cover the profile conversion logic-> done