react-nativesentryreact-native-sentry

How to setup Sentry-cli source maps with react-native


Introduction

Hi, I'm trying to get Sentry to recognise our sourcemaps in a react-native project, but I can't get it working.

The artifacts are uploading - I can see them in the WebUI, but the events lack context/mapping:

Question

Can anyone see any problems in my setup?

Thanks!

 Background

Assumptions

Xcode build phase

During the XCode build phase we already bundle the DSym.

In this script, I'm trying to pull out the bundled js and sourcemap, and uploading it.

Script

#!/bin/bash
# WARNING: Run directly from Xcode

# For testing of Xcode bundling/sentry locally, set to "true"
DEBUG_FORCE_BUNDLING="true"

printf "Xcode: Bundle react-native and upload to Sentry"

source ../scripts/xcode/utils/node_activate.sh

# Create bundle and sourcemap
export NODE_BINARY=node
export SENTRY_PROPERTIES=sentry.properties
DEST=$CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH
export EXTRA_PACKAGER_ARGS="--sourcemap-output $DEST/main.bundle.map.js";
if [ "${CONFIGURATION}" = "Release" ]; then
    FORCE_BUNDLING="$DEBUG_FORCE_BUNDLING" \
    ../node_modules/@sentry/cli/sentry-cli react-native xcode \
    ../node_modules/react-native/scripts/react-native-xcode.sh
else
   FORCE_BUNDLING="$DEBUG_FORCE_BUNDLING" \
   ../node_modules/@sentry/cli/sentry-cli react-native xcode \
   ../node_modules/react-native/scripts/react-native-xcode.sh
fi

# Copy bundle & sourcemap
mkdir -p ../.xcodebuild
cp $DEST/main.jsbundle ../.xcodebuild/index.bundle # rename?
cp $DEST/main.bundle.map.js ../.xcodebuild
echo "Size of file $(wc -c ../.xcodebuild/index.bundle)" # RENAME!?
echo "Size of sourcemap $(wc -c ../.xcodebuild/main.bundle.map.js)"

# Upload sentry release
# https://docs.sentry.io/cli/releases/#creating-releases
APP_IDENTIFIER="com.mycompany.app"
VERSION="1.4.21"
RELEASE_NAME="$APP_IDENTIFIER-$VERSION"
DISTRIBUTION_NAME="2400"

function sentry_release {
    npx sentry-cli releases \
        files $RELEASE_NAME \
        $1 $2 $3
        --dist $DISTRIBUTION_NAME \
        --strip-prefix ".build" \
        --ignore node_modules \
        --rewrite "$(pwd)"

}

sentry_release upload ../.xcodebuild/index.bundle '~/index.bundle'
echo "sentry_release upload"

sentry_release upload-sourcemaps ../.xcodebuild/main.bundle.map.js
echo "sentry_release upload-sourcemaps"

echo `date`
echo "DONE"

Note: The important bit of node_modules/react-native/scripts/react-native-xcode.sh is:

BUNDLE_FILE="$DEST/main.jsbundle"

echo "BUNDLE_FILE: $BUNDLE_FILE" > ~/bh/react-native-native/bundle.log

"$NODE_BINARY" $NODE_ARGS "$CLI_PATH" $BUNDLE_COMMAND \
  $CONFIG_ARG \
  --entry-file "$ENTRY_FILE" \
  --platform ios \
  --dev $DEV \
  --reset-cache \
  --bundle-output "$BUNDLE_FILE" \
  --assets-dest "$DEST" \
  $EXTRA_PACKAGER_ARGS

Script output

Xcode: Upload Debug Symbols to SentryNow using node v11.11.0 (npm v6.7.0)
FORCE_BUNDLING enabled; continuing to bundle.
warning: the transform cache was reset.
Loading dependency graph, done.
info Writing bundle output to:, /Users/me/Library/Developer/Xcode/DerivedData/TheApp-cvfhlrosjrphnjdcngyqxnlmjjbb/Build/Products/Debug-iphonesimulator/TheApp.app/main.jsbundle
info Writing sourcemap output to:, /Users/me/Library/Developer/Xcode/DerivedData/TheApp-cvfhlrosjrphnjdcngyqxnlmjjbb/Build/Products/Debug-iphonesimulator/TheApp.app/main.bundle.map.js
info Done writing bundle output
info Done writing sourcemap output
info Copying 109 asset files
info Done copying assets
Size of file  8477623 ../.xcodebuild/index.bundle
Size of sourcemap  15378754 ../.xcodebuild/main.bundle.map.js
A 560eaee15f0c1ccb5a57b68b5dc1b4944cff84d2  (8477623 bytes)
sentry_release upload
> Analyzing 1 sources
> Adding source map references
> Uploading source maps for release com.mycompany.app-1.4.21

Source Map Upload Report
  Source Maps
    ~/main.bundle.map.js
sentry_release upload-sourcemaps
Fri May 3 15:50:26 BST 2019
DONE

Sentry event JSON

Trimmed some breadcrumbs/callstack:

// 20190503154011
// https://sentry.mycompany.com/mycompany/react-native-app/issues/4205/events/396945/json/

{
  "id": "1c754ed7d651445eb48ed79c995073e2",
  "project": 11,
  "release": "com.mycompany.app-1.4.21",
  "platform": "cocoa",
  "culprit": "crash(app:///index.bundle)",
  "message": "Error Sentry: TEST crash crash(app:///index.bundle)",
  "datetime": "2019-05-03T14:32:25.000000Z",
  "time_spent": null,
  "tags": [
    [
      "logger",
      "javascript"
    ],
    [
      "sentry:user",
      "id:b5f212b4-9112-4253-86cc-11583ac1945a"
    ],
    [
      "sentry:release",
      "com.mycompany.app-1.4.21"
    ],
    [
      "level",
      "fatal"
    ],
    [
      "device",
      "iPhone9,1"
    ],
    [
      "device.family",
      "iOS"
    ],
    [
      "os",
      "iOS 12.1"
    ],
    [
      "os.name",
      "iOS"
    ],
    [
      "os.rooted",
      "no"
    ]
  ],
  "contexts": {
    "device": {
      "model_id": "simulator",
      "family": "iOS",
      "simulator": true,
      "type": "device",
      "storage_size": 499963170816,
      "free_memory": 274915328,
      "memory_size": 17179869184,
      "boot_time": "2019-04-29T07:53:06Z",
      "timezone": "GMT+1",
      "model": "iPhone9,1",
      "usable_memory": 16463810560,
      "arch": "x86"
    },
    "app": {
      "app_version": "1.4.21",
      "app_name": "MyApp",
      "device_app_hash": "<device_app_hash>",
      "app_id": "<app_id>",
      "app_build": "2400",
      "app_start_time": "2019-05-03T14:31:33Z",
      "app_identifier": "com.mycompany.app",
      "type": "default",
      "build_type": "simulator"
    },
    "os": {
      "rooted": false,
      "kernel_version": "Darwin Kernel Version 17.7.0: Thu Jun 21 22:53:14 PDT 2018; root:xnu-4570.71.2~1/RELEASE_X86_64",
      "version": "12.1",
      "build": "17G65",
      "type": "os",
      "name": "iOS"
    }
  },
  "errors": [
    {
      "type": "invalid_attribute",
      "name": "dist"
    }
  ],
  "extra": {
    "session:duration": 52129
  },
  "fingerprint": [
    "{{ default }}"
  ],
  "metadata": {
    "type": "Error",
    "value": "Sentry: TEST crash"
  },
  "received": 1556893946.0,
  "sdk": {
    "client_ip": "109.69.86.251",
    "version": "0.42.0",
    "name": "sentry.javascript.react-native"
  },
  "sentry.interfaces.Breadcrumbs": {
    "values": [
      {
        "category": "console",
        "timestamp": 1556893700.0,
        "message": "%c prev state color: #9E9E9E; font-weight: bold [object Object]",
        "type": "default"
      },
      {
        "category": "console",
        "timestamp": 1556893941.0,
        "message": "%c prev state color: #9E9E9E; font-weight: bold [object Object]",
        "type": "default"
      },
      {
        "category": "console",
        "timestamp": 1556893941.0,
        "message": "%c next state color: #4CAF50; font-weight: bold [object Object]",
        "type": "default"
      },
      {
        "category": "sentry",
        "timestamp": 1556893945.0,
        "message": "Error: Sentry: TEST crash",
        "type": "default",
        "level": "fatal"
      }
    ]
  },
  "sentry.interfaces.Exception": {
    "exc_omitted": null,
    "values": [
      {
        "stacktrace": {
          "frames": [
            {
              "function": "callFunctionReturnFlushedQueue",
              "platform": "javascript",
              "abs_path": "app:///[native code]",
              "in_app": false,
              "filename": "app:///[native code]"
            },
            {
              "function": "touchableHandlePress",
              "abs_path": "app:///index.bundle",
              "in_app": false,
              "platform": "javascript",
              "lineno": 64988,
              "colno": 47,
              "filename": "app:///index.bundle"
            },
            {
              "function": "crash",
              "abs_path": "app:///index.bundle",
              "in_app": false,
              "platform": "javascript",
              "lineno": 93710,
              "colno": 22,
              "filename": "app:///index.bundle"
            }
          ],
          "has_system_frames": false,
          "frames_omitted": null
        },
        "mechanism": null,
        "raw_stacktrace": null,
        "value": "Sentry: TEST crash",
        "thread_id": 99,
        "module": null,
        "type": "Error"
      }
    ]
  },
  "sentry.interfaces.User": {
    "id": "b5f212b4-9112-4253-86cc-11583ac1945a"
  },
  "type": "error",
  "version": "7"
}

Artifacts

Web UI

Cut and pasted from Release artifacts page:

Release com.mycompany.app-1.4.21

Artifacts
NAME                    SIZE
~/index.bundle          8.1 MB
~/main.bundle.map.js    14.7 MB

sourceMappingURL

$ tail -c 50 .xcodebuild/main.jsbundle
//# sourceMappingURL=main.bundle.map.js

Solution

  • After MONTHS, we realised we had to write client code to knit in the Distribution and Release....

        const configureSentry = () => {
            Sentry.config(config.sentry.dsn).install();
            Sentry.setDist(DeviceInfo.getBuildNumber());
            Sentry.setRelease(DeviceInfo.getBundleId() + '-' + DeviceInfo.getVersion());
        };