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

Browser Profiling #792

Closed
timfish opened this issue Dec 1, 2023 · 9 comments · Fixed by #799
Closed

Browser Profiling #792

timfish opened this issue Dec 1, 2023 · 9 comments · Fixed by #799

Comments

@timfish
Copy link
Collaborator

timfish commented Dec 1, 2023

Problem Statement

Newer versions of Chrome support the BrowserProfilingIntegration which captures CPU profiles.

Solution Brainstorm

Initial testing shows this does not work out-of-the-box.

@AbhiPrasad
Copy link
Member

cc @JonasBa

@JonasBa
Copy link
Member

JonasBa commented Dec 1, 2023

@timfish can you explain a bit more about what breaks?

@JonasBa
Copy link
Member

JonasBa commented Dec 1, 2023

Or wait, do you mean newer versions of Electron right?

@timfish
Copy link
Collaborator Author

timfish commented Dec 1, 2023

Just need to publish an SDK release and then I'll upload my demo app which is easier to debug.

So far the log looks like this:

[App] [Renderer] Sentry Logger [log]: [Tracing] starting undefined transaction - Long work
[App] [Renderer] Sentry Logger [log]: [Profiling] started profiling transaction: Long work
[App] [Renderer] Sentry Logger [log]: [Tracing] Starting '< unknown op >' span on transaction 'Long work' (b49c1529ba22dcba).
/// snip extra
[App] [Renderer] Sentry Logger [log]: [Tracing] Finishing '< unknown op >' span on transaction 'Long work' (b49c1529ba22dcba).
[App] [Renderer] Sentry Logger [log]: [Profiling] stopped profiling of transaction: Long work
[App] [Renderer] Sentry Logger [log]: [Tracing] Finishing undefined transaction: Long work.
envelope

My best guess so far is that the profile context is not being added to the event as it's not hitting any of the debug logging when it should attempt to add the profile envelope.

@JonasBa
Copy link
Member

JonasBa commented Dec 1, 2023

Oh I see. It does seem like the profiler is correctly started, it just never gets attached to the envelope 🤔 Let me know when you publish your example app and I'll take a look

@timfish
Copy link
Collaborator Author

timfish commented Dec 4, 2023

Sorry for the delay. Here is the demo repo:
https://github.com/timfish/sentry-electron-renderer-profiling-test

yarn && yarn start to see the output.

It's worth noting that in the case of this basic app, and in many Electron apps, Node integration is enabled in the renderer processes which gives you full Node mixed into the browser context! This is not the recommended way to use Electron now, especially if you're loading remote content, but for many apps this is less of a concern. Historically this has caused issues with libraries that do any kind of Node detection but I don't think this is the case here.

@timfish
Copy link
Collaborator Author

timfish commented Dec 11, 2023

There is nothing wrong with profiling, the issue is how we route envelopes through the apps main process!

@AbhiPrasad
Copy link
Member

@timfish
Copy link
Collaborator Author

timfish commented Dec 11, 2023

No, that's all working in the renderer/browser process.

The issue is that we intercept all events and transactions and capture them through the main/node process so they have the full content. At this point, the profiles are being stripped off:

function handleEnvelope(options: ElectronMainOptionsInternal, env: Uint8Array | string, contents?: WebContents): void {
const envelope = parseEnvelope(env, new TextEncoder(), new TextDecoder());
const eventAndAttachments = eventFromEnvelope(envelope);
if (eventAndAttachments) {
const [event, attachments] = eventAndAttachments;
captureEventFromRenderer(options, event, attachments, contents);
} else {
const normalizedEnvelope = normalizeUrlsInReplayEnvelope(envelope, app.getAppPath());
// Pass other types of envelope straight to the transport
void getCurrentHub().getClient()?.getTransport()?.send(normalizedEnvelope);
}
}

We want to maintain passing through the main process event pipeline so events from both processes have the same context. However, there's no way to pass the profiles (or envelope items other than attachment) through. Replays work since they are a completely separate envelope which can be directly forwarded.

Possible solutions:

  • In the JavaScript repo, add something to EventHint that allows passing profiles or other envelope items through with captured events
  • When we receive an event in the main process with a profile
    • Remove and cache the profile
    • Re-add the profile context
    • Re-add the profile envelope when the event comes back through the main process event pipeline
  • Send the profiles in a separate envelope?

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

Successfully merging a pull request may close this issue.

3 participants