getsentry / sentry-cocoa

The official Sentry SDK for iOS, tvOS, macOS, watchOS.
https://sentry.io/for/cocoa/
MIT License
804 stars 317 forks source link

Stack trace symbols missing after upgrading to 8.9.0 or later #3409

Open marcelofabri opened 11 months ago

marcelofabri commented 11 months ago

Platform

iOS

Installed

Carthage

Version

8.9.0

Steps to Reproduce

We tried to update from 7.3.0 to the latest version (8.15.x) but our stacktraces don't show desymbolicated entries anymore.

After digging more, I've realized:

  1. 8.9.0 is the first version that broke this
  2. our setup is kind of weird

Weird setup

I assume this is because we didn't have ways to properly disable certain features that we don't want (ie we don't want any swizzling), so our setup looks like this (using 8.8.0 which is the last version we could upgrade to):

let options = Options()
options.dsn = config.dsn
options.attachStacktrace = false
options.enableSwizzling = false
options.enableCrashHandler = false

// most of these should be covered by `enableSwizzling`, but let's be safe:
options.enableTracing = false
options.enableNetworkTracking = false
options.enableNetworkBreadcrumbs = false
options.enableFileIOTracing = false
options.enableCoreDataTracing = false
options.enableAutoPerformanceTracing = false
options.enableUserInteractionTracing = false
options.enableAutoBreadcrumbTracking = false
options.enablePreWarmedAppStartTracing = false
options.enableUIViewControllerTracing = false

sentryClient = SentryClient(options: options)

Note that attachStacktrace = false, but that's not the reason things are not working since we call the private method to attach stack trace only when we want (see https://github.com/getsentry/sentry-cocoa/issues/3386 for more context).

We also don't call SentrySDK.start(options: options) and instead use our own SentryClient (because of the requirement above). As far as I can tell, this is what breaks desymbolication.

In an ideal world, we would:

  1. Have official support for configuring whether to attach or not a stacktrace to a given event (https://github.com/getsentry/sentry-cocoa/issues/2325)
  2. SentryClient probably shouldn't be exposed publicly so people don't end up with a setup similar to ours

Given that the hints API is probably a few months away, I wonder if there's an interim solution. Here're the options I thought:

Expected Result

Stack traces should be desymbolicated

Actual Result

Stack traces are not desymbolicated

Note: I'm writing this issue as a more technical complement of a support email I've sent. In the email there are links to the actual events in Sentry.

Are you willing to submit a PR?

No response

armcknight commented 11 months ago

Hi @marcelofabri , would you mind sending those links to me at andrew.mcknight@sentry.io so I can have a look?

I would be surprised though if this client configuration you're using results in sending stacktraces that are unsymbolicated. I'd think it more likely that configuration effects whether stacktraces are either sent or not sent. But if one is sent, and it's not symbolicated, my guess is something is wrong with dSYM upload/processing.

In any case, happy to have a look at the issues you have showing the problem!

brustolin commented 11 months ago

Hello @marcelofabri, are you testing this during debug? If so, we removed local symbolication to reduce in device processing. You can enable this by setting options.debug = true don't forget to change this for release.

Your app will also be symbolicated if you upload debug symbols, but we understand this is not practical during development.

marcelofabri commented 11 months ago

Hi @marcelofabri , would you mind sending those links to me at andrew.mcknight@sentry.io so I can have a look?

I would be surprised though if this client configuration you're using results in sending stacktraces that are unsymbolicated. I'd think it more likely that configuration effects whether stacktraces are either sent or not sent. But if one is sent, and it's not symbolicated, my guess is something is wrong with dSYM upload/processing.

So we definitely see the stack trace but without symbols (sent you the links). I would be surprised if this is something with the dSYM upload/processing since:

  1. we haven't changed anything on our side (I generated the builds in the exact same way)
  2. calling SentrySDK.start(options: options) makes it work again

Hello @marcelofabri, are you testing this during debug? If so, we removed local symbolication to reduce in device processing. You can enable this by setting options.debug = true don't forget to change this for release.

Your app will also be symbolicated if you upload debug symbols, but we understand this is not practical during development.

No, these are release builds. Note that calling SentrySDK.start(options: options) makes it work again.

brustolin commented 11 months ago

Note that calling SentrySDK.start(options: options) makes it work again.

I didn't get this, were you not calling SentrySDK.start before? This is required for the SDK to work.

marcelofabri commented 11 months ago

Note that calling SentrySDK.start(options: options) makes it work again.

I didn't get this, were you not calling SentrySDK.start before? This is required for the SDK to work.

No, we were using SentryClient directly since we want to call the private method that allows us to conditionally attach stack traces.

For us to be able to use SentrySDK’s interface, we’d need a way to either get the SentryClient instance from it or ideally official support for hints.

brustolin commented 11 months ago

Interesting. I don't know a reason for symbolication not work when you don't start SentrySDK, we would need to investigate this.

PS: You can get SentryClient from SentryHub if you manually expose the currentHub from SentrySDK, and client from SentryHub. This is a workaround, we don't recommend this, adding hints is in our backlog.

philipphofmann commented 11 months ago

I can easily reproduce this with our iOS-Swift sample app. I removed starting the SDK from the AppDelegate and replaced it with

    let options = Options()
    options.dsn = dsn
    options.attachStacktrace = false
    options.enableSwizzling = false
    options.enableCrashHandler = false

    // most of these should be covered by `enableSwizzling`, but let's be safe:
    options.enableTracing = false
    options.enableNetworkTracking = false
    options.enableNetworkBreadcrumbs = false
    options.enableFileIOTracing = false
    options.enableCoreDataTracing = false
    options.enableAutoPerformanceTracing = false
    options.enableUserInteractionTracing = false
    options.enableAutoBreadcrumbTracking = false
    options.enablePreWarmedAppStartTracing = false
    options.enableUIViewControllerTracing = false

    let client = SentryClient(options: options)

    do {
        try RandomErrorGenerator.generate()
    } catch {
        let scope = Scope()
        let user = User()
        user.email = "philipp.hofmann@example.com"
        scope.setUser(user)
        client?.capture(error: error, scope: scope)
    }

    client?.flush(timeout: 1.0)

Then, I run a release build on a simulator, upload the debug symbols via an Xcode Build Phase, and get an event in Sentry with redacted frames.

CleanShot 2023-11-23 at 15 47 48@2x

When I started to debug this, I found out that in SentryCrashStackEntryMapper.sentryCrashStackEntryToSentryFrame the stackentry only has the address but not imageName, imageAdress, etc.

CleanShot 2023-11-23 at 15 49 51@2x

I guess as the code snippet doesn't start SentryCrash, some parts for getting the imageName, imageAddress, etc., are not initialized properly when retrieving the stack trace in SentryClient.