diff --git a/docs/organization/early-adopter-features/index.mdx b/docs/organization/early-adopter-features/index.mdx index d48883befdc29..9289046a2fc61 100644 --- a/docs/organization/early-adopter-features/index.mdx +++ b/docs/organization/early-adopter-features/index.mdx @@ -23,3 +23,4 @@ Limitations: - [Span Summary](/product/insights/overview/transaction-summary/#span-summary) - [Dynamic Alerts](/product/alerts/create-alerts/metric-alert-config/#dynamic-alerts) - [New Trace Explorer With Span Metrics](/product/explore/new-trace-explorer/) +- [Size Analysis](/product/size-analysis/) diff --git a/docs/platforms/android/size-analysis/index.mdx b/docs/platforms/android/size-analysis/index.mdx new file mode 100644 index 0000000000000..120fd02c90495 --- /dev/null +++ b/docs/platforms/android/size-analysis/index.mdx @@ -0,0 +1,38 @@ +--- +title: Size Analysis +sidebar_title: Size Analysis +sidebar_order: 5200 +description: Upload Android builds to Sentry for Size Analysis. +--- + + + +[Size Analysis](/product/size-analysis) helps monitor your mobile app's size in pre-production to prevent unexpected size increases (regressions) from reaching users. Aside from being courteous to your users, a smaller app size helps boost installation and retention rates, especially for customers with limited storage or slower connections. + +## Getting Started + +**Accepted Formats**: AAB (preferred) | APK + +**Upload Mechanisms**: [Gradle](#uploading-with-gradle) | [Sentry CLI](#uploading-with-the-sentry-cli) + +### Uploading With Gradle + + + +### Uploading With the Sentry CLI + + + +## Upload Metadata + + + +### Build Configuration + + + +## What's Next? + +We strongly recommend integrating Size Analysis into your CI pipeline. Follow our guide on [getting set up in CI](/product/size-analysis/integrating-into-ci/). + + diff --git a/docs/platforms/android/size-analysis/insights.mdx b/docs/platforms/android/size-analysis/insights.mdx new file mode 100644 index 0000000000000..8c1bd1b1ffd6d --- /dev/null +++ b/docs/platforms/android/size-analysis/insights.mdx @@ -0,0 +1,108 @@ +--- +title: Insights +sidebar_order: 5250 +description: Preview how Size Analysis reports highlight Android build trends. +--- + +Size Analysis Insights point out opportunities to reduce your Android app's size. They spot patterns like duplicate files, oversized media, or unneeded assets, and list exactly what to fix along with the estimated size savings. + +## Android Insights + +Below are a list of available insights for Android builds, followed by more details about each insight: + +| Insight | What it flags | +| --------------------------------------------------------- | --------------------------------------------------------------------- | +| [Duplicate Files](#duplicate-files) | Flags identical payloads so you can drop the duplicates | +| [Large Images](#large-images) | Surfaces oversized image assets worth recompressing or resizing. | +| [Large Videos](#large-videos) | Highlights video files that are bigger than typical delivery budgets. | +| [WebP Optimization](#webp-optimization) | Tests PNG/JPEG bitmaps to see if lossless WebP would shrink them. | +| [Large Audio](#large-audio) | Surfaces hefty audio tracks that could be recompressed or trimmed. | +| [Hermes Debug Info (RN Only)](#hermes-debug-info-rn-only) | Points to bundled Hermes bytecode still carrying debugger metadata. | + +### Duplicate Files + +**What it is**: Finds matching files or directories inside `assets/`, `res/`, or embedded libraries. Duplicate files are determined by examining the file hash, ensuring these are truly duplicates and not just similar files or the same file name. + +**How to fix**: Keep one copy and remove or dedupe the rest. For resource folders, consolidate the asset into a shared module or asset pack so the APK only bundles it once. + +### Large Images + +**What it is**: Flags image files larger than 10 MB. + +**How to fix**: Compress images with lossless WebP or resize them before bundling. + + +**Options:** + +- Use Android Studio: right-click an image → **Convert to WebP** → select **Lossless**. +- Use the command line: + + ```bash + # Install cwebp + brew install webp + + # Convert PNG to lossless WebP + cwebp -lossless input.png -o output.webp + + # Convert JPEG to lossless WebP + cwebp -lossless input.jpg -o output.webp + ``` + +Large hero images or splash screens may also load more efficiently if served over the network instead of being bundled with the app. + +### Large Videos + +**What it is**: Highlights bundled video assets above 10 MB. + +**How to fix**: Re-encode them to H.264 or HEVC with a lower bitrate, shorten the clip, or host the video remotely and stream it on demand. To shrink a clip in place, try FFmpeg: + +```bash +ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset slow -c:a copy output.mp4 +``` + +Lower the `-crf` value for higher quality (and larger files), or raise it for smaller files. + +### WebP Optimization + +**What it is**: Tests every PNG, BMP, JPG, or JPEG (excluding `.9.png`) against lossless WebP conversion. If the WebP variant saves at least 500 bytes, the insight lists the asset. + +**How to fix**: Convert the listed bitmap to lossless WebP and update its references. Pick one of the paths below. + +#### Option 1: Android Studio + +1. In Android Studio, right-click the image. +2. Choose **Convert to WebP…**. +3. Select **Lossless** (API 18+ supports it) and review the preview. + +#### Option 2: Command line + +```bash +# Install cwebp +brew install webp + +# Convert PNG to lossless WebP +cwebp -lossless input.png -o output.webp + +# Convert JPEG to lossless WebP +cwebp -lossless input.jpg -o output.webp +``` + +> Lossless WebP with alpha requires `minSdkVersion` ≥ 18. For older devices, keep PNG fallbacks for assets that rely on transparency. + +### Large Audio + +**What it is**: Surfaces audio files larger than 5 MB across `res/raw`, `assets`, or libraries. + +**How to fix**: Re-encode them at a lower bitrate or modern format using FFmpeg or your DAW, trim unused segments, or stream long-form media instead of bundling it. A quick FFmpeg recompress: + +```bash +ffmpeg -i input.wav -c:a aac -b:a 128k output.m4a +``` + +You can tweak the bitrate (`b:a`) to balance quality vs. size. Higher bitrates (192k-256k) will be higher quality, but larger size. Lower bitrates (96k-128k) will be lower quality, but smaller size. If your audio file is voice-only, you can use a lower bitrate with little degradation in quality. Music files may benefit from a higher bitrate. + +### Hermes Debug Info (RN Only) + +**What it is**: Detects Hermes bytecode bundles that still contain debug info sections. + +**How to fix**: Build the React Native bundle in release mode (`react-native bundle --dev false` or the Gradle release task) so Hermes strips debug sections before packaging. diff --git a/docs/platforms/apple/guides/ios/size-analysis/images/exported-symbols.png b/docs/platforms/apple/guides/ios/size-analysis/images/exported-symbols.png new file mode 100644 index 0000000000000..ada4f65af4de7 Binary files /dev/null and b/docs/platforms/apple/guides/ios/size-analysis/images/exported-symbols.png differ diff --git a/docs/platforms/apple/guides/ios/size-analysis/images/strip-symbols.png b/docs/platforms/apple/guides/ios/size-analysis/images/strip-symbols.png new file mode 100644 index 0000000000000..4d6aa4b0f2efd Binary files /dev/null and b/docs/platforms/apple/guides/ios/size-analysis/images/strip-symbols.png differ diff --git a/docs/platforms/apple/guides/ios/size-analysis/index.mdx b/docs/platforms/apple/guides/ios/size-analysis/index.mdx new file mode 100644 index 0000000000000..b2a1da43524ef --- /dev/null +++ b/docs/platforms/apple/guides/ios/size-analysis/index.mdx @@ -0,0 +1,51 @@ +--- +title: Size Analysis +sidebar_order: 5200 +description: Upload iOS builds to Sentry for size analysis. +--- + + + +[Size Analysis](/product/size-analysis) helps monitor your mobile app's size in pre-production to prevent unexpected size increases (regressions) from reaching users. Aside from being courteous to your users, a smaller app size helps boost installation and retention rates, especially for customers with limited storage or slower connections. + +## Getting Started + +**Accepted Formats**: XCArchive (preferred) | IPA + +**Upload Mechanisms**: [Fastlane Plugin](#uploading-with-fastlane) (version 1.34.0 or higher) *or* [Sentry CLI](#uploading-with-the-sentry-cli) + +### Uploading With Fastlane + + + +### Uploading with the Sentry CLI + + + +## Upload Metadata + + + +### Build Configuration + + + +## Understanding App Size + +### What We're Measuring + + + +### App Thinning + + + +### App Store Connect File Sizes + + + +## What's Next? + +We strongly recommend integrating Size Analysis into your CI pipeline. Follow our guide on [getting set up in CI](/product/size-analysis/integrating-into-ci/). + + diff --git a/docs/platforms/apple/guides/ios/size-analysis/insights.mdx b/docs/platforms/apple/guides/ios/size-analysis/insights.mdx new file mode 100644 index 0000000000000..96f3192b85e0a --- /dev/null +++ b/docs/platforms/apple/guides/ios/size-analysis/insights.mdx @@ -0,0 +1,308 @@ +--- +title: Insights +sidebar_order: 5250 +description: See how Size Analysis surfaces trends for your iOS builds. +--- + +Size Analysis Insights point out opportunities to reduce your iOS app's size. They spot patterns like duplicate files, oversized media, or unneeded assets, and list exactly what to fix along with the estimated size savings. + +## iOS Insights + +Below are a list of available insights for iOS builds, followed by more details about each insight: + +| Insight | What it flags | +| ----------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| [Strip Debug Symbols](#strip-debug-symbols) | Binaries that include removable debug sections or symbols. | +| [Duplicate Files](#duplicate-files) | Identical files where the extras can be removed. | +| [Image Optimization](#image-optimization) | Oversized PNG/JPEG/HEIC assets and recommends minifying or converting to HEIC. | +| [Alternate Icon Optimization](#alternate-icon-optimization) | Alternate app icons that can be downscaled and recompressed. | +| [Loose Images](#loose-images) | Scaled @1x/@2x/@3x images that should be moved into asset catalogs to qualify for app thinning. | +| [Small Files](#small-files) | Tiny files wasting space because of the 4KB filesystem block size. | +| [Unnecessary Files](#unnecessary-files) | Docs, scripts, configs, or other build leftovers in the bundle. | +| [Large Images](#large-images) | Image files that are a good candidate for on-demand delivery. | +| [Large Videos](#large-videos) | Video files that are a good candidate for on-demand delivery. | +| [Localized Strings](#localized-strings) | Localized strings that can use a more efficient format. | +| [Minify Localized Strings](#minify-localized-strings) | Localized string files that contain removable whitespace and comments. | +| [Main Binary Export Metadata](#main-binary-export-metadata) | Binaries that include removable export tries. | +| [Hermes Debug Info (RN Only)](#hermes-debug-info-rn-only) | Hermes bytecode files that include removable debug info. | + +### Strip Debug Symbols + +**What it is**: Debug info and symbols are only used during development and should not be shipped to users. + +**How to fix**: Strip symbols from release builds and instead use debug symbols in separate dSYM files for crash reporters. + + + Stripping symbols before creating a dSYM breaks crash symbolication. Confirm + your release build still produces and uploads dSYMs (or another crash reporter + has them) before stripping. + + +In Xcode ensure your release configuration sets the `Debug Information Format` build setting to `DWARF with dSYM`. + +The `strip` command can then remove the extra information: + +```bash +strip -rSTx AppBinary -o AppBinaryStripped +``` + +To automate stripping in your project after building, add a Run Script phase that skips non-release builds and leaves Apple-signed frameworks untouched: + + + This script will strip the main app binary along with any binaries in the + `Frameworks/` directory. This is a sample script that **may require + adjustments** for your project. + + +```bash +#!/bin/bash +set -e + +echo "Starting the symbol stripping process..." + +if [ "Release" = "${CONFIGURATION}" ]; then + echo "Configuration is Release." + + # Path to the app directory + APP_DIR_PATH="${BUILT_PRODUCTS_DIR}/${EXECUTABLE_FOLDER_PATH}" + echo "App directory path: ${APP_DIR_PATH}" + + # Strip main binary + echo "Stripping main binary: ${APP_DIR_PATH}/${EXECUTABLE_NAME}" + strip -rSTx "${APP_DIR_PATH}/${EXECUTABLE_NAME}" + if [ $? -eq 0 ]; then + echo "Successfully stripped main binary." + else + echo "Failed to strip main binary." >&2 + fi + + # Path to the Frameworks directory + APP_FRAMEWORKS_DIR="${APP_DIR_PATH}/Frameworks" + echo "Frameworks directory path: ${APP_FRAMEWORKS_DIR}" + + # Strip symbols from frameworks, if Frameworks/ exists at all + # ... as long as the framework is NOT signed by Apple + if [ -d "${APP_FRAMEWORKS_DIR}" ]; then + echo "Frameworks directory exists. Proceeding to strip symbols from frameworks." + find "${APP_FRAMEWORKS_DIR}" -type f -perm +111 -maxdepth 2 -mindepth 2 -exec bash -c ' + codesign -v -R="anchor apple" "{}" &> /dev/null || + ( + echo "Stripping {}" && + if [ -w "{}" ]; then + strip -rSTx "{}" + if [ $? -eq 0 ]; then + echo "Successfully stripped {}" + else + echo "Failed to strip {}" >&2 + fi + else + echo "Warning: No write permission for {}" + fi + ) + ' \; + if [ $? -eq 0 ]; then + echo "Successfully stripped symbols from frameworks." + else + echo "Failed to strip symbols from some frameworks." >&2 + fi + else + echo "Frameworks directory does not exist. Skipping framework stripping." + fi +else + echo "Configuration is not Release. Skipping symbol stripping." +fi + +echo "Symbol stripping process completed." +``` + +Because Xcode generates dSYMs from the unstripped binary, list the dSYM as an Input File so the script runs after Xcode finishes generating it: + +``` +${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${EXECUTABLE_NAME} +``` + +![Example of Input File =600x](./images/strip-symbols.png) + +### Duplicate Files + +**What it is**: Finds identical files bundled more than once. + +**How to fix**: Use dynamic frameworks to share assets between multiple targets. Here's an [example a post](https://www.emergetools.com/blog/posts/make-your-ios-app-smaller-with-dynamic-frameworks) walking through how to do this for an SPM project. + +### Image Optimization + +**What it is**: Surfaces PNG, JPEG, or HEIC assets that can be minified or converted. + +**How to fix**: Pick one of these workflows, then replace the source asset with the optimized version. If you convert to HEIC, update the asset catalog reference. + +#### Option 1: Use Imagemin (CLI) + +```bash +# Install imagemin-cli +npm install -g imagemin-cli + +# Optimize PNG with quality 85 +npx imagemin input.png --plugin=pngquant --pngquant.quality=0.85-0.85 > output.png + +# Optimize JPEG with quality 85 +npx imagemin input.jpg --plugin=mozjpeg --plugin.mozjpeg.quality=85 > output.jpg +``` + +#### Option 2: Use ImageOptim (GUI) + +Download ImageOptim for macOS, drag your images into the window, and let it recompress them with lossy settings. + +#### Option 3: Convert to HEIC + +Open the image in Preview, choose `File → Export`, pick `HEIC`, and save. Replace the original file and update any references. + +### Alternate Icon Optimization + +**What it is**: Alternate app icons are only ever shown on the home screen which requires 180x180 pixels. These images can be downsized to 180x180 and then upsampled back to 1024x1024 to reduce size. + +**How to fix**: Run one of the scripts below to resize to homescreen quality and save an optimized copy. Then update the alternate icon entry in your `.xcassets` catalog (and Info.plist if you change the filename). + +1. Save the script as `optimize.sh`. +2. Run `source optimize.sh`. +3. Call `optimize_icon YourIcon.png`. + +```bash +#!/bin/bash +optimize_icon() { + local input="$1" + local output="$(basename "$input" | sed 's/\.[^.]*$//')_optimized.heic" + + [ ! -f "$input" ] && echo "❌ File not found: $input" && return 1 + + echo "🔄 Optimizing $(basename "$input")..." + + sips --resampleWidth 180 "$input" \ + --out /tmp/icon.png >/dev/null 2>&1 || return 1 + sips --resampleWidth 1024 /tmp/icon.png \ + -s format heic -s formatOptions 85 \ + --out "$output" >/dev/null 2>&1 + + rm /tmp/icon.png + + if [ -f "$output" ]; then + local saved=$(( ($(stat -f%z "$input") - $(stat -f%z "$output")) / 1024 )) + echo "✅ Saved ${saved}KB → $output" + else + echo "❌ Optimization failed" + return 1 + fi +} +``` + +Update the Info.plist alternate icon entry to point at the new `.heic` file. + +### Loose Images + +**What it is**: Finds scaled @1x/@2x/@3x images stored outside of asset catalogs. This prevents app thinning from removing variants not needed for the user's device. + +**How to fix**: Move each image set into an asset catalog in Xcode. + +### Small Files + +**What it is**: Each file on iOS takes up a minimum of 4KB due to the filesystem's block size. Files smaller than this limit will take up more storage on disk than expected. Every file inside the app also has code signature overhead which can add up with many files. + +**How to fix**: Group small files into asset catalogs, archives, or databases so multiple entries share the same file on disk. + +### Unnecessary Files + +**What it is**: Files such as READMEs, docs, scripts, configs, and similar build leftovers do not need to be included in the app bundle. + +**How to fix**: Drop these files from the Copy Bundle Resources phase or exclude them with `EXCLUDED_SOURCE_FILE_NAMES` before archiving. + +### Large Images + +**What it is**: Image assets larger than 10 MB are not recommended to be bundled in your app. Often times images are only shown to a subset of users and could instead be shown on-demand. Large images also take up considerable amount of memory when displayed and can lead to Out of Memory crash reports. + +**How to fix**: host and load the image with a CDN. Also check if the image has been minified and is in the appropriate format for the best compression. + +### Large Videos + +**What it is**: Video assets larger than 10 MB are not recommended to be bundled in your app. Often times videos are only shown to a subset of users and could instead be shown on-demand. + +**How to fix**: host and stream the content instead of bundling it, or re-encode them with H.264 or HEVC at a lower bitrate or resolution. + +### Minify Localized Strings + +**What it is**: Xcode localized strings files often include translator comments, whitespace, binary encodings, and other non-runtime text that can be safely stripped. + +**How to fix**: Start with low-effort cleanup, then automate comment stripping if you still ship large payloads. + +#### Option 1: Keep the format lean + +- Encode localized strings as plain text (`"key" = "value";`), not binary plists. Set **Strings File Output Encoding** (`STRINGS_FILE_OUTPUT_ENCODING`) to **UTF-8** in Xcode. + +#### Option 2: Strip comments automatically + +String files can have comments that ship with the bundle. They help during translation but take space in production. A typical comment may look like: + +```text +/* Title for the expired code alert. */ +"code_expired" = "Code Expired"; +``` + +You can automatically strip comments by adding a Run Script build phase that converts each `.strings` file to JSON, rewrites it without comments, and leaves a compact UTF-8 file behind: + +1. In Xcode, open **Build Phases → + → New Run Script Phase** and place it after the localized resources build step. +2. Set the shell to your Python 3 binary (for Homebrew on Apple Silicon: `/opt/homebrew/bin/python3`). +3. Paste the script below. + +```python +#!/usr/bin/env python3 +import json +import os +import subprocess + +def minify(file_path: str) -> None: + subprocess.run(["plutil", "-convert", "json", file_path], check=True) + + with open(file_path, "r", encoding="utf-8") as source: + data = json.load(source) + + with open(file_path, "w", encoding="utf-8") as target: + for key, value in data.items(): + target.write(f'"{key}" = "{value}";\n') + +for root, _, files in os.walk(os.environ["BUILT_PRODUCTS_DIR"], followlinks=True): + for filename in files: + if filename.endswith(".strings"): + path = os.path.join(root, filename) + print(f"Minifying {path}") + minify(path) +``` + +This script strips comments and blank lines after the files are generated, so keep the original annotated copies under version control for translators. + +#### Option 3: Integrate SmallStrings library + +[SmallStrings](https://github.com/EmergeTools/SmallStrings/) can result in savings up to 90% of the original localization size, but is only recommended for apps with a lot of translations due to the effort required. + +### Main Binary Export Metadata + +**What it is**: Binaries that act as entrypoints for your app, such as your main app binary or watchOS app binary, are not linked against by other binaries. This means the export trie information is unnecessary and can be removed. + +**How to fix**: Maintain a minimal allowlist so only required entry points stay exported. + +1. Create a text file in your project, for example `Config/ExportedSymbols.txt` +2. Add `_main` on its own line +3. If you rely on other dynamic lookups, list those symbols too +4. In Xcode, set **Build Settings → Linking → Exported Symbols File** to the new file’s path + +![Example of Exported Symbols File](./images/exported-symbols.png) + +Xcode now limits the export trie to just that allowlist. + +### Hermes Debug Info (React Native) + +**What it is**: Debug information is only needed during development and should not be shipped to users. + +**How to fix**: Enable [Source maps](https://reactnative.dev/docs/debugging-release-builds) when building your release app. + + + Stripping debug information breaks crash symbolication. Source maps need to be + uploaded separately to your crash reporter. + diff --git a/docs/platforms/dart/guides/flutter/size-analysis/index.mdx b/docs/platforms/dart/guides/flutter/size-analysis/index.mdx new file mode 100644 index 0000000000000..253b64cf450a5 --- /dev/null +++ b/docs/platforms/dart/guides/flutter/size-analysis/index.mdx @@ -0,0 +1,47 @@ +--- +title: Size Analysis +sidebar_order: 5200 +description: Upload Flutter builds to Sentry for size analysis. +--- + + + +[Size Analysis](/product/size-analysis) helps monitor your mobile app's size in pre-production to prevent unexpected size increases (regressions) from reaching users. Aside from being courteous to your users, a smaller app size helps boost installation and retention rates, especially for customers with limited storage or slower connections. + +## Getting Started - iOS + +**Accepted Upload Formats**: XCArchive (preferred) | IPA + +**Upload Mechanisms**: [Sentry CLI](#uploading-ios-builds-with-the-sentry-cli) | [Fastlane](#uploading-ios-builds-with-fastlane) + +### Uploading iOS Builds With the Sentry CLI + + + +### Uploading iOS Builds With Fastlane + + + +## Getting Started - Android + +**Accepted Upload Formats**: AAB (preferred) | APK + +**Upload Mechanisms**: [Sentry CLI](#uploading-android-builds-with-the-sentry-cli) | [Gradle](#uploading-android-builds-with-gradle) + +### Uploading Android builds with the Sentry CLI + + + +### Uploading Android Builds With Gradle + + + +## Upload Metadata + + + +### Build Configuration + + + + diff --git a/docs/platforms/dart/guides/flutter/size-analysis/insights.mdx b/docs/platforms/dart/guides/flutter/size-analysis/insights.mdx new file mode 100644 index 0000000000000..48a62cab9e4f6 --- /dev/null +++ b/docs/platforms/dart/guides/flutter/size-analysis/insights.mdx @@ -0,0 +1,12 @@ +--- +title: Insights +sidebar_order: 5250 +description: Preview how Size Analysis highlights Flutter build trends. +--- + +Size Analysis Insights point out opportunities to reduce your Flutter app's size. They spot patterns like duplicate files, oversized media, or unneeded assets, and list exactly what to fix along with the estimated size savings. + +For insights available for Flutter builds, see the following pages: + +- [Android insights](/platforms/android/size-analysis/insights/) +- [iOS insights](/platforms/apple/guides/ios/size-analysis/insights/) diff --git a/docs/platforms/react-native/size-analysis/index.mdx b/docs/platforms/react-native/size-analysis/index.mdx new file mode 100644 index 0000000000000..20b02bd600bd1 --- /dev/null +++ b/docs/platforms/react-native/size-analysis/index.mdx @@ -0,0 +1,48 @@ +--- +title: Size Analysis +sidebar_title: Size Analysis +sidebar_order: 5200 +description: Upload React Native iOS and Android builds to Sentry for size analysis. +--- + + + +[Size Analysis](/product/size-analysis) helps monitor your mobile app's size in pre-production to prevent unexpected size increases (regressions) from reaching users. Aside from being courteous to your users, a smaller app size helps boost installation and retention rates, especially for customers with limited storage or slower connections. + +## Getting Started - iOS + +**Accepted Upload Formats**: XCArchive (preferred) | IPA + +**Upload Mechanisms**: [Sentry CLI](#uploading-ios-builds-with-the-sentry-cli) | [Fastlane](#uploading-ios-builds-with-fastlane) + +### Uploading iOS Builds With the Sentry CLI + + + +### Uploading iOS Builds With Fastlane + + + +## Getting Started - Android + +**Accepted Upload Formats**: AAB (preferred) | APK + +**Upload Mechanisms**: [Sentry CLI](#uploading-android-builds-with-the-sentry-cli) | [Gradle](#uploading-android-builds-with-gradle) + +### Uploading Android builds with the Sentry CLI + + + +### Uploading Android Builds With Gradle + + + +## Upload Metadata + + + +### Build Configuration + + + + diff --git a/docs/platforms/react-native/size-analysis/insights.mdx b/docs/platforms/react-native/size-analysis/insights.mdx new file mode 100644 index 0000000000000..19af1cee070d7 --- /dev/null +++ b/docs/platforms/react-native/size-analysis/insights.mdx @@ -0,0 +1,12 @@ +--- +title: Insights +sidebar_order: 5250 +description: See how Size Analysis surfaces trends for React Native builds. +--- + +Size Analysis Insights point out opportunities to reduce your React Native app's size. They spot patterns like duplicate files, oversized media, or unneeded assets, and list exactly what to fix along with the estimated size savings. + +For insights available for React Native builds, see the following pages: + +- [Android insights](/platforms/android/size-analysis/insights/) +- [iOS insights](/platforms/apple/guides/ios/size-analysis/insights/) diff --git a/docs/product/size-analysis/images/build-comparison.png b/docs/product/size-analysis/images/build-comparison.png new file mode 100644 index 0000000000000..e7b3efb318bf0 Binary files /dev/null and b/docs/product/size-analysis/images/build-comparison.png differ diff --git a/docs/product/size-analysis/images/build-details.png b/docs/product/size-analysis/images/build-details.png new file mode 100644 index 0000000000000..39b4738b4e94e Binary files /dev/null and b/docs/product/size-analysis/images/build-details.png differ diff --git a/docs/product/size-analysis/images/insights.png b/docs/product/size-analysis/images/insights.png new file mode 100644 index 0000000000000..6166c170c14d7 Binary files /dev/null and b/docs/product/size-analysis/images/insights.png differ diff --git a/docs/product/size-analysis/images/status-check-inline.png b/docs/product/size-analysis/images/status-check-inline.png new file mode 100644 index 0000000000000..8fd8c7a85f433 Binary files /dev/null and b/docs/product/size-analysis/images/status-check-inline.png differ diff --git a/docs/product/size-analysis/images/status-check.png b/docs/product/size-analysis/images/status-check.png new file mode 100644 index 0000000000000..6a1becb81145a Binary files /dev/null and b/docs/product/size-analysis/images/status-check.png differ diff --git a/docs/product/size-analysis/index.mdx b/docs/product/size-analysis/index.mdx new file mode 100644 index 0000000000000..aae8e9f63c529 --- /dev/null +++ b/docs/product/size-analysis/index.mdx @@ -0,0 +1,63 @@ +--- +title: Size Analysis +sidebar_order: 136 +description: Monitor mobile builds for size changes before they reach users. +--- + + + +Size Analysis monitors your mobile app size to prevent regressions before they reach users. Upload builds from CI to spot regressions early, understand what's inside each bundle, and keep release artifacts lean. + +## Why Track App Size? + +- Faster downloads reduce install drop-off +- Install size is linked to uninstall rates, particularly for customers with limited storage or slower connections +- Size bloat can have downstream technical impact: longer build times, startup times, code complexity, etc. + +## Features + +### Build Details + +Size Analysis breaks down your mobile app so you can see exactly where size is coming from. It surfaces Insights that recommend concrete fixes, such as compressing images or stripping debug info. + +![Build details screenshot placeholder](./images/build-details.png) + +Size Analysis also provides actionable insights on how you can reduce your app's size. Insights are tailored to each platform. Dive deeper in: + +![Build details screenshot placeholder =600x](./images/insights.png) + +- [Android](/platforms/android/size-analysis/insights/) +- [iOS](/platforms/apple/guides/ios/size-analysis/insights/) +- [React Native](/platforms/react-native/size-analysis/insights/) +- [Flutter](/platforms/dart/guides/flutter/size-analysis/insights/) + +### Build Comparison + +Compare any two builds to see what changed, review module-level diffs, and confirm that optimizations worked. + +![Build comparison screenshot placeholder](./images/build-comparison.png) + +### Status Checks + +Integrate into CI Size Analysis results on pull requests. You can track size on every commit to ensure there are no unnecessary size increases. + +![Status check screenshot placeholder](./images/status-check.png) + +Learn how to set it up in the [CI integration guide](/product/size-analysis/integrating-into-ci/). + +## Upload Guides + +You can follow the platform guides to learn how to upload builds for Size Analysis: + +- [Android](/platforms/android/size-analysis/) +- [iOS](/platforms/apple/guides/ios/size-analysis/) +- [React Native](/platforms/react-native/size-analysis/) +- [Flutter](/platforms/dart/guides/flutter/size-analysis/) + +### Upload Metadata + +Below is the metadata included in your build, regardless of the platform. + + + + diff --git a/docs/product/size-analysis/integrating-into-ci.mdx b/docs/product/size-analysis/integrating-into-ci.mdx new file mode 100644 index 0000000000000..af8ffc5a62d5b --- /dev/null +++ b/docs/product/size-analysis/integrating-into-ci.mdx @@ -0,0 +1,99 @@ +--- +title: Integrating Into CI +sidebar_order: 40 +description: Set up the integration in CI to receive automated size change notifications +--- + + + +## Github + +The GitHub integration brings Size Analysis directly into your pull request workflow by adding status checks. This alerts developers to the size impact their code changes have on the app build, and can optionally block the pull request from being merged on large size increases. + +### Installation + +1. Install the Sentry Github App by following the installation instructions in the [GitHub integration documentation](https://docs.sentry.io/organization/integrations/source-code-mgmt/github/). + + a. If you have previously installed the Sentry App, ensure you have accepted the latest permissions in order to receive Status Checks. + +2. Set up Size Analysis by following the guide for [iOS](/platforms/apple/guides/ios/size-analysis/) or [Android](/platforms/android/size-analysis/). + +3. Create a workflow to upload base branch builds. + + + We recommend uploading Release builds in CI since they are representative of + what your end users see and provide cleaner diffs. + + +Size Analysis works by comparing a head vs a base build, similar to how code review compares your new code to the baseline code. First, we need to upload base builds: + +```yml {filename:sentry_size_analysis_main.yml} +name: Sentry Size Analysis Upload + +on: + push: + branches: [main] // or whatever is used + +jobs: + build_and_upload: + // ... +``` + +Confirm that builds uploaded from this workflow have the correct `sha` metadata value, as well as no `base_sha` being set. + +4. Create a workflow to upload pull request builds. + +Next, we need the head build uploads: + +```yml {filename:sentry_size_analysis_pull_request.yml} +name: Sentry Size Analysis Upload + +on: + pull_request: + branches: [main] // or whatever is used + +jobs: + build_and_upload: + // ... +``` + +Confirm that builds uploaded from this workflow have the correct `sha` and `base_sha` metadata values. + +5. Confirm the status check appears + +After configuring both workflows and sending the correct metadata, the status check should appear on every commit: + +![Example Status Check =600x](./images/status-check-inline.png) + +6. View the detailed breakdown + +Clicking on the "Details" button above should bring you to a more detailed breakdown of the changes. + +![Example Status Check](./images/status-check.png) + +## Troubleshooting + +### Not Seeing Status Checks + +Check that: + +- The Sentry GitHub App is installed and has access to your repository +- You're correctly uploading builds for size analysis from all base branch builds +- You're correctly uploading builds for size analysis from the PR branch. +- Your builds that you want to compare have the same build configuration (for example, both are `Release` builds) +- Your builds contain all the [required metadata](/product/size-analysis/#upload-metadata) + +### Missing Base Build + +The first time you set up Size Analysis, your main branch may not have any builds yet: + +1. Merge a PR or push to your main branch to trigger a build +2. Future PRs will be able to compare against this base build + +### Unexpected Size Changes Show in the Comparison + +This could be due to a few things: + +1. The wrong base build is being selected. Check that the Git information in both head/base builds match what you expect for your pull request. +2. The compiler optimized code in a different way. The analysis is being performed on the compiled output of the app, and sometimes the compiler can optimize code in slightly different ways depending on your code changes, for example with function outlining. +3. The build environment is different between head/base builds. For iOS analyses, make sure the same version of Xcode is being used for both the builds. diff --git a/includes/size-analysis/app-store-connect-file-sizes.mdx b/includes/size-analysis/app-store-connect-file-sizes.mdx new file mode 100644 index 0000000000000..ed04ceb71ef0f --- /dev/null +++ b/includes/size-analysis/app-store-connect-file-sizes.mdx @@ -0,0 +1 @@ +App Store Connect has a feature for `App File Sizes` which provides a report of your app size thinned for various device types. While we strive to be consistent with these numbers, you may see differences between the reported Sentry size and the Apple size. It's important to note that the reported Apple sizes are not consistent with the rest of their tooling, such as the Size Report generated by Xcode, and these are all estimated sizes. You can [learn more about these differences here](https://github.com/EmergeTools/app-store-size-example) for additional information. diff --git a/includes/size-analysis/app-thinning.mdx b/includes/size-analysis/app-thinning.mdx new file mode 100644 index 0000000000000..497b2f9fef7e2 --- /dev/null +++ b/includes/size-analysis/app-thinning.mdx @@ -0,0 +1,22 @@ +App Thinning is Apple's technology that automatically optimizes the delivery of iOS apps to reduce their download size for end users. When your app is uploaded to the App Store, Apple creates device-specific variants that only include the resources needed for each device type. For example, an iPhone SE doesn't need images intended for iPads. + +Sentry Size Analysis **does not perform any app thinning** as part of the analysis, the underlying app is untouched and results shown as-is. + +If you want results targeting a specific device type (recommended), apply app thinning **before** uploading to Sentry. This can be configured via Export Options when building the app. First create an `export_options.plist` file with the desired device type: + +```xml {filename:export_options.plist} + + + + +method +ad-hoc +team_id +your-team-id +thinning +iPhone17,1 + + +``` + +And then pass this file to `xcodebuild` via the `-exportOptionsPlist export_options.plist` flag when building the app. This will produce a `app-thinning.plist` file in your build directory with information on the created app variants and where they are located on disk. Pick the appropriate IPA when uploading to Sentry. diff --git a/includes/size-analysis/build-configuration-android.mdx b/includes/size-analysis/build-configuration-android.mdx new file mode 100644 index 0000000000000..219abae1f2adb --- /dev/null +++ b/includes/size-analysis/build-configuration-android.mdx @@ -0,0 +1,3 @@ +Build configuration metadata keeps comparisons scoped to like-for-like builds. For example, on a PR status check, the comparison will only be made for builds with the same build configuration. + +The Android Gradle plugin sends the build variant (for example, `freeDebug` or `paidRelease`). diff --git a/includes/size-analysis/build-configuration-general.mdx b/includes/size-analysis/build-configuration-general.mdx new file mode 100644 index 0000000000000..bd2dbf03fcd28 --- /dev/null +++ b/includes/size-analysis/build-configuration-general.mdx @@ -0,0 +1 @@ +Build configuration metadata keeps comparisons scoped to like-for-like builds. The Android Gradle plugin sends the build variant (for example, `freeDebug` or `paidRelease`). On iOS, set this to your Xcode build configuration, such as `Debug`, `Staging`, or `Release`. diff --git a/includes/size-analysis/build-configuration-ios.mdx b/includes/size-analysis/build-configuration-ios.mdx new file mode 100644 index 0000000000000..e789efec9f44c --- /dev/null +++ b/includes/size-analysis/build-configuration-ios.mdx @@ -0,0 +1,3 @@ +Features such as automatically comparing the head build against the base build **will only compare builds of the same build configuration**. This is important to consider when setting up Size Analysis in your CI. For example, `Release` and `Debug` builds can be drastically different depending on the compiler and linker settings used during the build process. Trying to compare the two would give unexpected results. + +Sometimes this is expected though, say you want to test the impact of converting your project to use Bazel (e.g. `Release` vs `Release-Bazel`). In this case, it's still possible to perform a manual comparison of builds with different build configurations. diff --git a/includes/size-analysis/ea.mdx b/includes/size-analysis/ea.mdx new file mode 100644 index 0000000000000..edb2ff4483c3c --- /dev/null +++ b/includes/size-analysis/ea.mdx @@ -0,0 +1,5 @@ + + +Size Analysis is currently in Early Access. To access, turn on Early Adopter in your settings. + + diff --git a/includes/size-analysis/github-only.mdx b/includes/size-analysis/github-only.mdx new file mode 100644 index 0000000000000..86c1448809911 --- /dev/null +++ b/includes/size-analysis/github-only.mdx @@ -0,0 +1 @@ +GitHub is currently the only supported integration for alerts. diff --git a/includes/size-analysis/images/android-metadata.png b/includes/size-analysis/images/android-metadata.png new file mode 100644 index 0000000000000..ecb49e94ad966 Binary files /dev/null and b/includes/size-analysis/images/android-metadata.png differ diff --git a/includes/size-analysis/images/ios-metadata.png b/includes/size-analysis/images/ios-metadata.png new file mode 100644 index 0000000000000..06a1c269641c7 Binary files /dev/null and b/includes/size-analysis/images/ios-metadata.png differ diff --git a/includes/size-analysis/upload-cli-android.mdx b/includes/size-analysis/upload-cli-android.mdx new file mode 100644 index 0000000000000..5fade679987d7 --- /dev/null +++ b/includes/size-analysis/upload-cli-android.mdx @@ -0,0 +1,18 @@ +1. Install the [sentry-cli](/cli/) + +2. Authenticate the Sentry CLI by [following these steps](https://docs.sentry.io/cli/configuration/#to-authenticate-manually) + +3. Build your app to create an AAB (preferred) or APK + +4. Invoke the following CLI command to trigger the upload: + +```bash +sentry-cli build upload app.aab \ + --org your-org \ + --project your-project \ + --build-configuration Release +``` + +5. After an upload has successfully processed, confirm the metadata is correct in the Sentry UI + +![Upload metadata =400x](./images/android-metadata.png) diff --git a/includes/size-analysis/upload-cli-ios.mdx b/includes/size-analysis/upload-cli-ios.mdx new file mode 100644 index 0000000000000..7195a67d15f00 --- /dev/null +++ b/includes/size-analysis/upload-cli-ios.mdx @@ -0,0 +1,18 @@ +1. Install the [sentry-cli](/cli/) + +2. Authenticate the Sentry CLI by [following these steps](https://docs.sentry.io/cli/configuration/#to-authenticate-manually) + +3. Build your app to create an XCArchive (preferred) or IPA + +4. Invoke the following CLI command to trigger the upload: + +```bash +sentry-cli build upload app.xcarchive \ + --org your-org \ + --project your-project \ + --build-configuration Release +``` + +5. After an upload has successfully processed, confirm the metadata is correct in the Sentry UI + +![Upload metadata =400x](./images/ios-metadata.png) diff --git a/includes/size-analysis/upload-fastlane.mdx b/includes/size-analysis/upload-fastlane.mdx new file mode 100644 index 0000000000000..d412d23c3ac4c --- /dev/null +++ b/includes/size-analysis/upload-fastlane.mdx @@ -0,0 +1,56 @@ +The Fastlane plugin can be used to upload XCArchive or IPA builds to Sentry. On GitHub Actions, Fastlane will automatically detect your [build's metadata](#upload-metadata) and include it in the upload. In other Continuous Integration (CI) environments, you may need to manually set metadata values. + +1. Configure the [Sentry Fastlane plugin](/platforms/apple/guides/ios/upload-debug-symbols/fastlane/) (version `1.34.0` or higher): + + ```ruby + bundle exec fastlane add_plugin fastlane-plugin-sentry + ``` + +2. Set up `SENTRY_AUTH_TOKEN` in your environment (you can generate a token [here](https://sentry.sentry.io/settings/auth-tokens/)) + +3. In `FastFile`, add a call to `sentry_upload_build` after your build step: + + ```ruby {filename:Fastfile} + lane :upload_to_sentry do + build_ios_app( + scheme: 'YourScheme', + configuration: 'Release', + ) + sentry_upload_build( + org_slug: 'your-org', + project_slug: 'your-project', + build_configuration: 'Release' # Adjust to your configuration + ) + end + ``` + +4. After an upload has successfully processed, confirm the metadata is correct in the Sentry UI + +![Upload metadata =400x](./images/ios-metadata.png) + +The Fastlane plugin automatically detects all build metadata. If needed, the metadata values can be overridden by passing parameters to `sentry_upload_build`: + +```ruby {filename:Fastfile} +lane :upload_to_sentry do + build_ios_app( + scheme: 'YourScheme', + configuration: 'Release', + ) + sentry_upload_build( + org_slug: 'your-org', + project_slug: 'your-project', + build_configuration: 'Release', + # Optional metadata overrides: + head_sha: 'abc123', + base_sha: 'def456', + vcs_provider: 'github', + head_repo_name: 'organization/repository', + base_repo_name: 'organization/repository', + head_ref: 'feature-branch', + base_ref: 'main', + pr_number: '42' + ) +end +``` + +See the [Fastlane repo](https://github.com/getsentry/sentry-fastlane-plugin) for more information. diff --git a/includes/size-analysis/upload-gradle.mdx b/includes/size-analysis/upload-gradle.mdx new file mode 100644 index 0000000000000..eea1ed4846457 --- /dev/null +++ b/includes/size-analysis/upload-gradle.mdx @@ -0,0 +1,100 @@ +The Gradle plugin automatically detects build metadata from your git repository. On GitHub Actions, all metadata is automatically detected. On other CI systems, you may need to manually set some values using the [`vcsInfo`](https://developer.android.com/reference/tools/gradle-api/8.8/com/android/build/api/dsl/VcsInfo) extension. + +1. Configure the [Sentry Android Gradle plugin](/platforms/android/configuration/gradle/) with at least version `6.0.0-alpha.6` + +2. Set the auth token as an environment variable to be used when running your release build. + + + +```bash +export SENTRY_AUTH_TOKEN=___ORG_AUTH_TOKEN___ +``` + +3. Enable uploading for size analysis for CI builds. + + ```kotlin {filename:build.gradle.kts} + sentry { + sizeAnalysis { + enabled = providers.environmentVariable("GITHUB_ACTIONS").isPresent + } + } + ``` + + ```groovy {filename:build.gradle} + sentry { + sizeAnalysis { + enabled = providers.environmentVariable("GITHUB_ACTIONS").present + } + } + ``` + +4. Invoke the following Gradle tasks to build your app and trigger the upload. + + ```aab {filename:aab} + ./gradlew bundleRelease + ``` + + ```apk {filename:apk} + ./gradlew assembleRelease + ``` + +5. After an upload has successfully processed, confirm the metadata is correct in the Sentry UI + +![Upload metadata =400x](./images/android-metadata.png) + +### Overriding Metadata + +The Gradle plugin automatically detects build metadata from your git repository. On GitHub Actions, all metadata is automatically detected. On other CI systems, you may need to manually set some values using the (`vcsInfo`)[https://developer.android.com/reference/tools/gradle-api/8.8/com/android/build/api/dsl/VcsInfo] extension. + +Configure overrides in your Gradle build configuration: + +```kotlin {filename:build.gradle.kts} +sentry { + sizeAnalysis { + enabled = providers.environmentVariable("GITHUB_ACTIONS").isPresent + } + + vcsInfo { + headSha.set("abc123") + baseSha.set("def456") + vcsProvider.set("github") + headRepoName.set("organization/repository") + baseRepoName.set("organization/repository") + headRef.set("feature-branch") + baseRef.set("main") + prNumber.set(42) + } +} +``` + +```groovy {filename:build.gradle} +sentry { + sizeAnalysis { + enabled = providers.environmentVariable("GITHUB_ACTIONS").present + } + + vcsInfo { + headSha = 'abc123' + baseSha = 'def456' + vcsProvider = 'github' + headRepoName = 'organization/repository' + baseRepoName = 'organization/repository' + headRef = 'feature-branch' + baseRef = 'main' + prNumber = 42 + } +} +``` + +Available `vcsInfo` properties: + +| Property | Type | Description | +| -------------- | ------ | --------------------------------- | +| `headSha` | String | Current commit SHA | +| `baseSha` | String | Base commit SHA (for comparison) | +| `vcsProvider` | String | VCS provider (e.g., "github") | +| `headRepoName` | String | Repository name (org/repo format) | +| `baseRepoName` | String | Base repository name | +| `headRef` | String | Branch or tag name | +| `baseRef` | String | Base branch name | +| `prNumber` | Int | Pull request number | diff --git a/includes/size-analysis/upload-metadata.mdx b/includes/size-analysis/upload-metadata.mdx new file mode 100644 index 0000000000000..131638219d35a --- /dev/null +++ b/includes/size-analysis/upload-metadata.mdx @@ -0,0 +1,15 @@ +We use build metadata to organize builds in the UI and ensure correct comparisons. + +| Field | Description | +| ----------------------- | --------------------------------------------------------------------------------------------------------- | +| `org`\* | Sentry organization slug | +| `project`\* | Sentry project slug | +| `build-configuration`\* | Build configuration describing how the app was built, for example `Release` or `Debug` or `Release-Bazel` | +| `head-sha` | Current commit SHA | +| `base-sha` | Base commit SHA (for comparisons, recommended to use the branch's merge-base) | +| `head-repo-name` | Repository name (`org/repo`) | +| `pr-number` | Pull request number | +| `head-ref` | Branch or tag name | +| `base-ref` | Base branch name | + +\* _required field_ diff --git a/includes/size-analysis/what-were-measuring.mdx b/includes/size-analysis/what-were-measuring.mdx new file mode 100644 index 0000000000000..84012a98cac07 --- /dev/null +++ b/includes/size-analysis/what-were-measuring.mdx @@ -0,0 +1,15 @@ +Size analysis breaks down compiled files to show you the size contribution of resources and source code. + +**Assets** +Assets such as images, colors and .plist configuration files can come in different variants for different devices. This could be different images for each screen density, or even different configurations depending on the GPU class. If a build is uploaded without first being thinned, you may see multiple copies of your images (ex. different idiom and colorspace values), another reason why we strongly suggest app thinning as a precursor to uploading. + +It's also worth noting that storing an image in an asset catalog will allow them to be further compressed. This is why you may see a smaller size for an image in the treemap versus what you might see in your file system. + +**Colors** +Colors are commonly stored in Asset Catalogs to provide different themes for light and dark mode. Individually these have a very small contribution to app size, but together they can add up. If your Asset Catalog contains colors, they will be grouped into a single block that indicates the number of colors in the catalog and the sum of their size contributions. + +**Packed Assets** +Asset Catalogs group similar icons into a compressed format known as a Packed Asset. This is much smaller than storing each icon individually, and is one of the great advantages of Asset Catalogs. However, we won't show you a breakdown of these blocks because the compression applied means there isn't a clear size contribution from each icon. + +**Binary** +Size analysis also breaks down your binary file into logical groups based on their size. If you don't upload dSYMs, or your app is encrypted, we will break the binary into the segments and sections that characterize the file. If you upload a .xcarchive with dSYMs, size analysis will break the binary into individual source files that can be properly attributed to binary size. diff --git a/platform-includes/debug-symbols-apple/_default.mdx b/platform-includes/debug-symbols-apple/_default.mdx index 5173dddb3956f..0235ece2bc0df 100644 --- a/platform-includes/debug-symbols-apple/_default.mdx +++ b/platform-includes/debug-symbols-apple/_default.mdx @@ -165,7 +165,7 @@ You can add `--force-foreground` argument to sentry-cli to help you debug any er [//]: # "removes the leading $." ```text -${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME} +${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${EXECUTABLE_NAME} ``` 4. Set `ENABLE_USER_SCRIPT_SANDBOXING` in your Xcode project settings to `NO`.