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

Migrating to v3 #370

Closed
timfish opened this issue Oct 3, 2021 · 31 comments
Closed

Migrating to v3 #370

timfish opened this issue Oct 3, 2021 · 31 comments

Comments

@timfish
Copy link
Collaborator

timfish commented Oct 3, 2021

v3 of the Electron SDK includes significant changes to simplify usage and improve maintainability and bundler support. Migration should still be relatively painless!

  • If you have trouble migrating, please respond in this issue
  • If you find bugs with v3 or you can see areas where it can be improved, please open a new issue

For some advanced technical detail, you may want to check out the relevant Proposal and Pull Request.

New Features:

  • Session tracking now enabled by default
  • Preload script no longer required for most scenarios
  • Optional relative imports for main/renderer/preload entry points
  • Offline support
  • Additional device context
  • Minidumps for GPU crashes
  • Browser Tracing now compatible

Major breaking changes:

  • Native crashes now consider sampleRate and beforeSend
  • Configuration through integrations rather than options

Session Tracking

Session tracking is now enabled by default so you will see Release Health data. Session tracking is via the MainProcessSession integration which as the name suggests, tracks sessions as per the main process lifetime.

Sentry.init({
  dsn: '__DSN__',
  release: '__RELEASE__'
});

If you don't want to track sessions, this can be disabled by setting autoSessionTracking to false.

Sentry.init({
  dsn: '__DSN__',
  autoSessionTracking: false
});

If you have a use case where sessions should be tracked in a different way, please open an issue!

Relative Imports

The SDK uses multiple package.json fields to ensure that bundlers automatically pickup the the correct entry point for each Electron process when using the root import (const Sentry = require('@sentry/electron') or import * as Sentry from '@sentry/electron'). This allows you to have a sentry.js with your Sentry configuration imported into every process.

However, not all bundlers are created equal and you may want to add specific integrations to only one of the Electron processes.

To support more complex configurations, you can now skip this automatic bundler target detection and import the process specific code directly:

Main Process

const Sentry = require('@sentry/electron/main');
// or
import * as Sentry from '@sentry/electron/main';

Renderer Process

const Sentry = require('@sentry/electron/renderer');
// or
import * as Sentry from '@sentry/electron/renderer';

Preload Code

require('@sentry/electron/preload');
// or
import '@sentry/electron/preload';

Offline Support

The ElectronOfflineNetTransport is now the default transport. It wraps ElectronNetTransport and saves payloads to disk if they cannot be sent

Additional device context

The default enabled AdditionalContext integration includes additional device context like screen resolution and memory usage.

Browser Tracing

The significant refactor now allows the use of Sentry browser tracing in the renderer process:

main.js

import * as Sentry from '@sentry/electron/main';

Sentry.init({
  dsn: '__DSN__'
}); 

renderer.js

import * as Sentry from '@sentry/electron/renderer';
import { Integrations } from '@sentry/tracing';

Sentry.init({
  integrations: [new Integrations.BrowserTracing()],
  tracesSampleRate: 1.0,
}); 

Preload Scripts

As of 3.0.0-beta.2 a preload script is no longer required for Electron >= v5

Native Crashes, sampleRate and beforeSend

Previously, the SDK did not consider sampleRate when sending native crash events and it was not possible to intercept them via the beforeSend hook. Theses are now correctly handled.

Integrations over Options

Previously, the Electron SDK had various configuration options. Most of these have moved to integrations.

With v3, the only Electron specific configuration options are in the main process and are detailed below:

export interface ElectronMainOptions extends NodeOptions {
  /**
   * Inter-process communication mode to receive event and scope from renderers
   *
   * IPCMode.Classic - Configures Electron IPC
   * IPCMode.Protocol - Configures a custom protocol
   * IPCMode.Both - Configures both IPC and custom protocol
   *
   * Defaults to IPCMode.Both for maximum compatibility
   */
  ipcMode: IPCMode;
  /**
   * A function that returns an array of Electron session objects
   *
   * These sessions are used to configure communication between the Electron
   * main and renderer processes.
   *
   * Defaults to () => [session.defaultSession]
   */
  getSessions: () => Session[];
  /**
   * Callback to allow custom naming of renderer processes.
   *
   * If the callback is not set, or it returns `undefined`, the default naming
   * scheme is used.
   */
  getRendererName?: (contents: WebContents) => string | undefined;
}

Native Crash Reporting

For native crash reporting, you have three options

  1. SentryMinidump integration (default)
    Uploads minidump files via the Sentry Envelope endpoint with full breadcrumbs and context
  2. ElectronMinidump integration
    Uploads minidumps via Crashpad/Breakpad built in uploader with partial context
import { init, Integrations} from '@sentry/electron';

init({
  dsn: '__DSN__',
  // Adding the ElectronMinidump integration like this 
  // ensures that it is the first integrations to be initialized
  integrations: defaultIntegrations => {
    return [new Integrations.ElectronMinidump(), ...defaultIntegrations]
  }
}); 
  1. No native crash reporting (remove the SentryMinidump integration)
import { init, Integrations } from '@sentry/electron';

init({
  dsn: '__DSN__',
  integrations: defaultIntegrations => {
    return ...defaultIntegrations.filter(i => i.name != Integrations.SentryMinidump.Id);
  }
}); 

WebContents 'unresponsive' Events

By default, the ElectronEvents integrations captures events for unresponsive Electron renderers. If you would like to disable this:

import { init, Integrations } from '@sentry/electron';

init({
  dsn: '__DSN__',
  integrations: [new Integrations.ElectronEvents({ unresponsive: false }];
}); 
@timfish timfish changed the title [WIP] v3 migration guide v3 migration guide Oct 5, 2021
@timfish timfish changed the title v3 migration guide Migrating to v3 Oct 5, 2021
@Joelkang
Copy link

Thanks for the detailed writeup Tim. I'm not migrating, but trying to integrate sentry for the first time and came across this thread. Unfortunately I wasn't successful at making it work.

I kept getting this error, and my preload script wouldn't build:

preload script must have absolute path: ./node_modules/@sentry/electron/esm/preload/index.js

I'm on Electron: 15.2.0 and using electron-forge 6.0.0-beta.61, including the webpack plugin.
I dont think electron forge's webpack plugin is particularly unique, but as far as I understand, it bundles everything into the output files, so there's no node_modules at runtime--though that path might just be a module id so maybe that's a red herring.

fwiw I've tried:

  • adding @sentry/electron/preload/index.js to the forge prefixEntries array, which basically just concats those files before the preload's source file as a webpack entry file.
  • adding a specific webpack.resolve.alias in the renderer webpack config to try and resolve sentry to an absolute path
  • adding externals: { electron: 'commonjs electron' } to the renderer webpack config (which I got from a different issue)

Happy to provide any other info that can help

@timfish
Copy link
Collaborator Author

timfish commented Oct 26, 2021

I'm currently working on improving the tests and adding more examples.

Here you can see the Electron Forge Webpack example:
https://github.com/timfish/sentry-electron/tree/recipes/examples/electron-forge-webpack

@AbhiPrasad AbhiPrasad pinned this issue Nov 10, 2021
@varunsrin

This comment has been minimized.

@timfish

This comment has been minimized.

@timfish

This comment has been minimized.

@varunsrin

This comment has been minimized.

@timfish

This comment has been minimized.

@Kyusung4698

This comment has been minimized.

@timfish

This comment has been minimized.

@Kyusung4698

This comment has been minimized.

@timfish

This comment has been minimized.

@artplan1

This comment has been minimized.

@timfish

This comment has been minimized.

@artplan1

This comment has been minimized.

@timfish

This comment has been minimized.

@artplan1

This comment has been minimized.

@timfish

This comment has been minimized.

@timfish
Copy link
Collaborator Author

timfish commented Jan 11, 2022

There are new features and bug fixes in the latest (3.0.0-beta.4) release!

@Kyusung4698
Copy link

Thanks for the new release! I'm getting quite a few 400 errors after upgrading to the 3.0.0-beta.4 release within the module itself. Is this known? There is not much information provided what the cause of the failed request is. Could you @timfish have a look?

    "metadata": {
        "display_title_with_tree_label": false,
        "filename": "app:https:///node_modules/@sentry/electron/main/transports/electron-net.js",
        "function": "ClientRequest.<anonymous>",
        "type": "Error",
        "value": "HTTP Error (400)"
    },
    "sdk": {
        "name": "sentry.javascript.electron",
        "version": "3.0.0-beta.4",
        "integrations": [
            "ElectronBreadcrumbs",
            "ElectronMinidump",
            "CaptureConsole",
            "Net",
            "MainContext",
            "ChildProcess",
            "OnUncaughtException",
            "PreloadInjection",
            "AdditionalContext",
            "InboundFilters",
            "FunctionToString",
            "Console",
            "Http",
            "OnUnhandledRejection",
            "LinkedErrors",
            "MainProcessSession"
        ],
        "packages": [
            {
                "name": "npm:@sentry/electron",
                "version": "3.0.0-beta.4"
            }
        ]
    }

@timfish
Copy link
Collaborator Author

timfish commented Jan 17, 2022

I would love to fix any potential issues with the latest SDK before it makes it to a stable release!

However, I have not personally observed the issues you're reporting and I haven't seen it with any of the e2e tests.

I need more information or a repository that reproduces the issue!

Where is the JSON you've included coming from?

@Kyusung4698
Copy link

Kyusung4698 commented Jan 17, 2022

I took the JSON from an event in sentry and extracted the relevant parts. I wasn't able to reproduce it locally, only seeing those errors in our sentry issue list.
image

@timfish
Copy link
Collaborator Author

timfish commented Jan 17, 2022

Ah ok, so these events are making it to Sentry but they probably shouldn't be.

The latest beta includes offline support which means that events that cannot be sent are saved to disk and sent when a connection is detected. It's highly likely that your app was getting HTTP errors at this point in v2 of the SDK, but they would have never have made it to Sentry because the server was not accessible.

@AbhiPrasad how do you think I should go about improving this? Simply never queue errors originating from the transport?

Outside of SDK transport errors, the offline support is going to increase the number of errors users get due to intermittent/bad connections. Other than make this more clear in the docs, is there anything else we should to to improve this?

@Kyusung4698
Copy link

Kyusung4698 commented Jan 17, 2022

@timfish That's maybe a wild guess but we sometimes return null in beforeSend in order to not process spammy events. Could it be that if the network connection is unstable a 'null' event is stored on disk and then, once the connection is back, send as 'null' event resulting in the BadRequest response?

We actually filter any network error, as those are not actable for us.

export function beforeSend(
    event: Sentry.Event,
    hint: Sentry.EventHint
): Sentry.Event {
    if (`${hint.originalException}`.includes('net::ERR_')) {
        console.debug('[sentry] Ignored network error event.');
        return null;
    }
    return event;
}

@timfish
Copy link
Collaborator Author

timfish commented Jan 17, 2022

The offline transport (ElectronOfflineNetTransport) is simply a wrapper around the original transport (ElectronNetTransport) that queues events that fail to send.

If beforeSend returns null, the event will be rejected by @sentry/core and is never passed to the transport for sending.

@AbhiPrasad
Copy link
Member

how do you think I should go about improving this? Simply never queue errors originating from the transport?

I can't ever see a case where these errors are of high value to users, I would just filter them out if possible. We do have the SentryError class for similar logic in the core JS SDK.

@chetbox
Copy link
Contributor

chetbox commented Feb 4, 2022

Thanks for this handy guide!

From the above it seems like ipcMode and getSessions have default values but the Typescript types require that specified.

Example with @sentry/electron v2 we have:

  SentryElectron.init({
    dsn: ...,
    release: ...
  });

The same works with v3, but the Typescript types insist that ipcMode and getSessions are defined, even though they seem to have defaults in the implementation:

Type '{ dsn: string; release: string; environment: "production" | "development"; ignoreErrors: string[]; normalizeDepth: number; }' is missing the following properties from type 'ElectronOptions': ipcMode, getSessionsts(2345)

Everything seems to work fine without ipcMode and getSessions.

@timfish
Copy link
Collaborator Author

timfish commented Feb 4, 2022

Thanks for reporting this @chetbox, these should be optional!

@chetbox
Copy link
Contributor

chetbox commented Feb 4, 2022

Thanks for reporting this @chetbox, these should be optional!

Cheers for confirming so quick @timfish! There a PR here: #412

@timfish
Copy link
Collaborator Author

timfish commented Feb 4, 2022

Many thanks for the PRs!

@timfish
Copy link
Collaborator Author

timfish commented Feb 16, 2022

3.0.0 has now been released and this migration guide has moved to here.

@timfish timfish closed this as completed Feb 16, 2022
evereq added a commit to ever-co/ever-gauzy that referenced this issue May 24, 2022
@acsant
Copy link

acsant commented Jul 20, 2022

Thanks for the detailed writeup Tim. I'm not migrating, but trying to integrate sentry for the first time and came across this thread. Unfortunately I wasn't successful at making it work.

I kept getting this error, and my preload script wouldn't build:

preload script must have absolute path: ./node_modules/@sentry/electron/esm/preload/index.js

I'm on Electron: 15.2.0 and using electron-forge 6.0.0-beta.61, including the webpack plugin. I dont think electron forge's webpack plugin is particularly unique, but as far as I understand, it bundles everything into the output files, so there's no node_modules at runtime--though that path might just be a module id so maybe that's a red herring.

fwiw I've tried:

  • adding @sentry/electron/preload/index.js to the forge prefixEntries array, which basically just concats those files before the preload's source file as a webpack entry file.
  • adding a specific webpack.resolve.alias in the renderer webpack config to try and resolve sentry to an absolute path
  • adding externals: { electron: 'commonjs electron' } to the renderer webpack config (which I got from a different issue)

Happy to provide any other info that can help

Facing this issue as well

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

No branches or pull requests

8 participants