diff --git a/.github/file-filters.yml b/.github/file-filters.yml index 186bba5caf2..db1d7c71e02 100644 --- a/.github/file-filters.yml +++ b/.github/file-filters.yml @@ -74,11 +74,13 @@ run_api_stability_for_prs: &run_api_stability_for_prs - "scripts/build-xcframework-slice.sh" - "scripts/assemble-xcframework.sh" - "scripts/update-api.sh" + - "scripts/extract-objc-api.sh" - "scripts/ci-diagnostics.sh" # API files - "sdk_api.json" - "sdk_api_sentryswiftui.json" + - "sdk_api_objc.json" # Build configuration - "Makefile" diff --git a/.github/workflows/api-stability.yml b/.github/workflows/api-stability.yml index 1f1ebf9dfb6..aefee0e1b5a 100644 --- a/.github/workflows/api-stability.yml +++ b/.github/workflows/api-stability.yml @@ -48,6 +48,7 @@ jobs: run: | mv sdk_api.json sdk_api_base.json mv sdk_api_sentryswiftui.json sdk_api_sentryswiftui_base.json + mv sdk_api_objc.json sdk_api_objc_base.json ./scripts/update-api.sh - name: Diagnose breaking changes for Sentry @@ -87,6 +88,18 @@ jobs: cat sentryswiftui_result.json exit 1 fi + + - name: Diagnose breaking changes for SentryObjC + if: always() + run: | + if diff -q "sdk_api_objc_base.json" "sdk_api_objc.json" > /dev/null; then + echo "No SentryObjC API changes detected." + else + echo "❌ SentryObjC public API changes are detected. If they're intended run "make generate-public-api" and commit the changes." + diff "sdk_api_objc_base.json" "sdk_api_objc.json" || true + exit 1 + fi + - name: Run CI Diagnostics if: failure() run: ./scripts/ci-diagnostics.sh diff --git a/.github/workflows/assemble-xcframework-sentryobjc.yml b/.github/workflows/assemble-xcframework-sentryobjc.yml new file mode 100644 index 00000000000..97ff36ad132 --- /dev/null +++ b/.github/workflows/assemble-xcframework-sentryobjc.yml @@ -0,0 +1,146 @@ +name: Assemble SentryObjC XCFramework + +on: + workflow_call: + inputs: + sdks: + description: |- + Comma-separated list of SDK slices to assemble. + required: false + type: string + default: "iphoneos,iphonesimulator,macosx,maccatalyst,appletvos,appletvsimulator,watchos,watchsimulator,xros,xrsimulator" + + signed: + description: |- + Whether or not the assembled XCFramework should be signed. + required: false + type: boolean + default: false + + release-version: + description: |- + For release workflows, the version to inject into the SDK. + required: false + type: string + +jobs: + assemble-xcframework-sentryobjc: + name: SentryObjC + runs-on: macos-15 + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - run: ./scripts/ci-select-xcode.sh 16.4 + shell: bash + + - name: Setup Ruby + uses: ruby/setup-ruby@4eb9f110bac952a8b68ecf92e3b5c7a987594ba6 # v1.292.0 + if: ${{ inputs.signed }} + with: + bundler-cache: true + + - name: "Download Fastlane Certificate" + if: ${{ inputs.signed }} + run: bundle exec fastlane prepare_xcframework_signing + env: + FASTLANE_KEYCHAIN_PASSWORD: ${{ secrets.FASTLANE_KEYCHAIN_PASSWORD }} + MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} + + # Download all three sets of static library slices. + # Each artifact contains a {sdk}.xcarchive.zip for one platform. + - name: Download Sentry static slices + uses: actions/download-artifact@v8 + with: + pattern: xcframework-sentry-static-slice-* + path: xcframework-slices/sentry-static + + - name: Download SentryObjCBridge slices + uses: actions/download-artifact@v8 + with: + pattern: xcframework-sentryobjc-bridge-slice-* + path: xcframework-slices/sentryobjc-bridge + + - name: Download SentryObjC slices + uses: actions/download-artifact@v8 + with: + pattern: xcframework-sentryobjc-objc-slice-* + path: xcframework-slices/sentryobjc-objc + + # Unzip slices into the directory layout expected by + # build-xcframework-sentryobjc-standalone.sh: + # XCFrameworkBuildPath/archive/Sentry/{sdk}.xcarchive/... + # XCFrameworkBuildPath/archive/SentryObjCBridge/{sdk}.xcarchive/... + # XCFrameworkBuildPath/archive/SentryObjC/{sdk}.xcarchive/... + - name: Arrange slice archives + shell: bash + env: + SDKS: ${{ inputs.sdks }} + run: | + set -euo pipefail + mkdir -p XCFrameworkBuildPath/archive + + arrange_slices() { + local variant_id="$1" + local slice_dir="$2" + local archive_name="$3" + + IFS=',' read -r -a sdk_list <<< "$SDKS" + for sdk in "${sdk_list[@]}"; do + artifact_dir="${slice_dir}/xcframework-${variant_id}-slice-${sdk}" + zip_file=$(find "$artifact_dir" -name "*.xcarchive.zip" -type f | head -1) + if [ -z "$zip_file" ]; then + echo "ERROR: No xcarchive.zip found in $artifact_dir" + exit 1 + fi + # Unzip into a temp location, then move the xcarchive into place + unzip_dir="/tmp/sentryobjc-unzip-${variant_id}-${sdk}" + rm -rf "$unzip_dir" + mkdir -p "$unzip_dir" + unzip -q "$zip_file" -d "$unzip_dir" + # The zip contains {sdk}.xcarchive/ (created with --keepParent) + mkdir -p "XCFrameworkBuildPath/archive/${archive_name}" + mv "$unzip_dir/${sdk}.xcarchive" "XCFrameworkBuildPath/archive/${archive_name}/${sdk}.xcarchive" + rm -rf "$unzip_dir" + done + } + + arrange_slices "sentry-static" "xcframework-slices/sentry-static" "Sentry" + arrange_slices "sentryobjc-bridge" "xcframework-slices/sentryobjc-bridge" "SentryObjCBridge" + arrange_slices "sentryobjc-objc" "xcframework-slices/sentryobjc-objc" "SentryObjC" + + echo "Archive layout:" + find XCFrameworkBuildPath/archive -maxdepth 3 -type d | head -30 + + - name: Link and assemble SentryObjC XCFramework + env: + SDKS: ${{ inputs.sdks }} + run: ./scripts/build-xcframework-sentryobjc-standalone.sh "$SDKS" + shell: bash + + - name: Validate XCFramework structure + run: ./scripts/validate-xcframework-format.sh "SentryObjC.xcframework" + shell: bash + + - name: Zip XCFramework + env: + SIGNED: ${{ inputs.signed }} + run: | + if [ "$SIGNED" = "true" ]; then + ./scripts/compress-xcframework.sh --sign SentryObjC + else + ./scripts/compress-xcframework.sh --not-signed SentryObjC + fi + shell: bash + + - name: Upload XCFramework + uses: actions/upload-artifact@v7 + with: + overwrite: true + name: xcframework-${{github.sha}}-sentryobjc + if-no-files-found: error + path: SentryObjC.xcframework.zip + + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh diff --git a/.github/workflows/build-xcframework-variant-slices.yml b/.github/workflows/build-xcframework-variant-slices.yml index 5f06e26b493..fe90a24d176 100644 --- a/.github/workflows/build-xcframework-variant-slices.yml +++ b/.github/workflows/build-xcframework-variant-slices.yml @@ -100,9 +100,10 @@ jobs: run: ./scripts/build-xcframework-slice.sh "$MATRIX_SDK" "$INPUT_NAME" "$INPUT_SUFFIX" "$INPUT_MACHO_TYPE" "$INPUT_CONFIG_SUFFIX" shell: bash - # The SentrySwiftUI archive build also builds Sentry.framework as a byproduct of the dependency. We need to remove that to avoid downstream assembly tasks from tripping on these extra files. In the future we could investigate using this byproduct instead of running a separate task for Sentry.framework, or use the one already built by that other task instead of rebuilding it here. - - name: Remove Sentry.framework from SentrySwiftUI build - if: inputs.name == 'SentrySwiftUI' + # Targets that depend on Sentry also build Sentry.framework as a byproduct. + # Remove it to avoid downstream assembly tasks from tripping on extra files. + - name: Remove Sentry.framework byproduct + if: inputs.name == 'SentrySwiftUI' || inputs.name == 'SentryObjCBridge' || inputs.name == 'SentryObjC' env: GITHUB_WORKSPACE: ${{ github.workspace }} run: | @@ -110,6 +111,16 @@ jobs: find "$GITHUB_WORKSPACE/XCFrameworkBuildPath/archive" -name "Sentry.framework.dSYM" -print0 | xargs -t0 rm -rf shell: bash + # SentryObjC depends on SentryObjCBridge, which gets built as a byproduct. + - name: Remove SentryObjCBridge.framework byproduct + if: inputs.name == 'SentryObjC' + env: + GITHUB_WORKSPACE: ${{ github.workspace }} + run: | + find "$GITHUB_WORKSPACE/XCFrameworkBuildPath/archive" -name "SentryObjCBridge.framework" -print0 | xargs -t0 rm -rf + find "$GITHUB_WORKSPACE/XCFrameworkBuildPath/archive" -name "SentryObjCBridge.framework.dSYM" -print0 | xargs -t0 rm -rf + shell: bash + # the upload action broke symlinks in the mac sdk slice's xcarchive - name: Zip xcarchive env: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e62c3793f94..2e204e0d225 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -104,6 +104,8 @@ jobs: config: Debug - scheme: iOS-ObjectiveC config: Debug + - scheme: iOS-ObjectiveCpp-NoModules + config: Debug - scheme: SPM config: Debug - scheme: DistributionSample diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1722911bd27..e0aebbe097a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -114,6 +114,19 @@ jobs: matrix: variant: ${{ fromJson(needs.setup-matrix.outputs.variants) }} + assemble-sentryobjc: + needs: [files-changed, build-xcframework-variant-slices, setup-matrix] + # Run the job only for PRs with related changes or non-PR events. + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_release_for_prs == 'true' + name: Assemble SentryObjC XCFramework + uses: ./.github/workflows/assemble-xcframework-sentryobjc.yml + secrets: inherit + with: + # Only sign the XCFramework on releases + signed: ${{ github.event_name != 'pull_request' }} + release-version: ${{ github.event.inputs.version }} + sdks: ${{ needs.setup-matrix.outputs.sdk-list-string }} + validate-xcframework: name: Validate XCFramework runs-on: macos-15 @@ -414,6 +427,7 @@ jobs: files-changed, build-xcframework-variant-slices, assemble-xcframework-variant, + assemble-sentryobjc, validate-xcframework, validate-spm, validate-spm-dynamic, diff --git a/.gitignore b/.gitignore index 57a3f2e6855..dc76d75c617 100644 --- a/.gitignore +++ b/.gitignore @@ -105,12 +105,7 @@ Samples/watchOS-Swift/watchOS-Swift.xcodeproj TestSamples/SwiftUICrashTest/SwiftUICrashTest.xcodeproj TestSamples/SwiftUITestSample/SwiftUITestSample.xcodeproj -Sentry.xcframework* -Sentry-Dynamic.xcframework* -Sentry-Dynamic-WithARM64e.xcframework* -SentrySwiftUI.xcframework* -Sentry-WithoutUIKitOrAppKit.xcframework* -Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework* +*.xcframework* current_package_diff.patch diff --git a/CHANGELOG.md b/CHANGELOG.md index dd76570173c..cec6120e7b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased +- Add SentryObjC wrapper SDK to provide pure Objective-C compatibility layer that wraps the main Sentry SDK with stable, documented Objective-C interfaces. (#7598) + This SDK is designed for projects that require strict Objective-C compatibility without Swift dependencies. + ### Features - Add `SentrySDK.lastRunStatus` to distinguish unknown, no-crash and crash (#7469) diff --git a/Makefile b/Makefile index bd39d9057d1..0c992ee393f 100644 --- a/Makefile +++ b/Makefile @@ -219,6 +219,31 @@ build-signed-xcframework: build-xcframework-sample: xcodebuild -project "Samples/XCFramework-Validation/XCFramework.xcodeproj" -configuration Release CODE_SIGNING_ALLOWED="NO" build +## Build SentryObjC framework for iOS Simulator +# +# Builds the SentryObjC framework target for iOS Simulator. +# This is the Objective-C wrapper framework that provides a stable ABI for ObjC++ consumers. +# The target must first be added to the Xcode project using: bundle exec ruby scripts/add-sentryobjc-target.rb +.PHONY: build-sentryobjc +build-sentryobjc: + @echo "--> Building SentryObjC for iOS Simulator" + set -o pipefail && xcodebuild build \ + -project Sentry.xcodeproj \ + -scheme SentryObjC \ + -destination 'platform=iOS Simulator,OS=$(IOS_SIMULATOR_OS),name=$(IOS_DEVICE_NAME)' \ + -configuration Release \ + CODE_SIGNING_ALLOWED="NO" 2>&1 | xcbeautify --preserve-unbeautified + +## Build SentryObjC XCFramework for distribution (iOS only) +# +# Creates SentryObjC XCFramework for iOS platforms (device + simulator). +# Uses the existing xcframework build infrastructure. +# Outputs to XCFrameworkBuildPath/SentryObjC.xcframework. +.PHONY: build-sentryobjc-xcframework +build-sentryobjc-xcframework: + @echo "--> Creating SentryObjC xcframework (iOS only)" + ./scripts/build-xcframework-variant.sh SentryObjC '' mh_dylib '' iOSOnly '' + # ============================================================================ # SAMPLE APPS # ============================================================================ @@ -230,6 +255,7 @@ build-xcframework-sample: build-samples: \ build-sample-DistributionSample \ build-sample-iOS-ObjectiveC \ + build-sample-iOS-ObjectiveCpp-NoModules \ build-sample-iOS-Swift \ build-sample-iOS-Swift6 \ build-sample-iOS-SwiftUI \ @@ -324,9 +350,8 @@ build-sample-visionOS-SwiftUI-SPM: ## Build the iOS-ObjectiveCpp-NoModules sample app # -# Builds the ObjC++ without-modules sample that reproduces #4543. -# This target is expected to FAIL until the pure ObjC SDK wrapper (#6342) -# is implemented. Use it to verify the fix. +# Builds the ObjC++ without-modules sample that uses SentryObjC (#6342). +# Uses #import for ObjC++ without -fmodules. .PHONY: build-sample-iOS-ObjectiveCpp-NoModules build-sample-iOS-ObjectiveCpp-NoModules: xcodegen --spec Samples/iOS-ObjectiveCpp-NoModules/iOS-ObjectiveCpp-NoModules.yml diff --git a/Package.swift b/Package.swift index 9bc15aca029..fc06609162e 100644 --- a/Package.swift +++ b/Package.swift @@ -96,7 +96,19 @@ targets += [ name: "SentryObjCInternal", dependencies: ["SentrySwift"], path: "Sources", - exclude: ["Sentry/SentryDummyPublicEmptyClass.m", "Sentry/SentryDummyPrivateEmptyClass.m", "Swift", "SentrySwiftUI", "Resources", "Configuration", "SentryCppHelper", "SentryDistribution", "SentryDistributionTests"], + exclude: [ + "Sentry/SentryDummyPublicEmptyClass.m", + "Sentry/SentryDummyPrivateEmptyClass.m", + "Swift", + "SentrySwiftUI", + "Resources", + "Configuration", + "SentryCppHelper", + "SentryDistribution", + "SentryDistributionTests", + "SentryObjC", + "SentryObjCBridge" + ], cSettings: [ .headerSearchPath("Sentry"), .headerSearchPath("SentryCrash/Recording"), @@ -107,6 +119,28 @@ targets += [ .headerSearchPath("SentryCrash/Reporting/Filters/Tools")]) ] +// Swift bridge that exposes SDK functionality to pure ObjC code (no modules) +products.append(.library(name: "SentryObjC", targets: ["SentryObjCInternal", "SentryObjCBridge", "SentryObjC"])) +targets += [ + .target( + name: "SentryObjCBridge", + dependencies: ["SentryObjCInternal"], + path: "Sources/SentryObjCBridge", + swiftSettings: [ + .unsafeFlags(["-enable-library-evolution"]) + ]), + + .target( + name: "SentryObjC", + dependencies: ["SentryObjCBridge"], + path: "Sources/SentryObjC", + publicHeadersPath: "Public", + cSettings: [ + .headerSearchPath("Public") + ] + ) +] + let package = Package( name: "Sentry", platforms: [.iOS(.v15), .macOS(.v10_14), .tvOS(.v15), .watchOS(.v8), .visionOS(.v1)], diff --git a/Package@swift-6.1.swift b/Package@swift-6.1.swift index f66e93f1098..177e705bb3b 100644 --- a/Package@swift-6.1.swift +++ b/Package@swift-6.1.swift @@ -97,7 +97,19 @@ targets += [ name: "SentryObjCInternal", dependencies: ["SentrySwift"], path: "Sources", - exclude: ["Sentry/SentryDummyPublicEmptyClass.m", "Sentry/SentryDummyPrivateEmptyClass.m", "Swift", "SentrySwiftUI", "Resources", "Configuration", "SentryCppHelper", "SentryDistribution", "SentryDistributionTests"], + exclude: [ + "Sentry/SentryDummyPublicEmptyClass.m", + "Sentry/SentryDummyPrivateEmptyClass.m", + "Swift", + "SentrySwiftUI", + "Resources", + "Configuration", + "SentryCppHelper", + "SentryDistribution", + "SentryDistributionTests", + "SentryObjC", + "SentryObjCBridge" + ], cSettings: [ .headerSearchPath("Sentry"), .headerSearchPath("SentryCrash/Recording"), @@ -110,6 +122,28 @@ targets += [ ]) ] +// Swift bridge that exposes SDK functionality to pure ObjC code (no modules) +products.append(.library(name: "SentryObjC", targets: ["SentryObjCInternal", "SentryObjCBridge", "SentryObjC"])) +targets += [ + .target( + name: "SentryObjCBridge", + dependencies: ["SentryObjCInternal"], + path: "Sources/SentryObjCBridge", + swiftSettings: [ + .unsafeFlags(["-enable-library-evolution"]) + ]), + + .target( + name: "SentryObjC", + dependencies: ["SentryObjCBridge"], + path: "Sources/SentryObjC", + publicHeadersPath: "Public", + cSettings: [ + .headerSearchPath("Public") + ] + ) +] + let package = Package( name: "Sentry", platforms: [.iOS(.v15), .macOS(.v10_14), .tvOS(.v15), .watchOS(.v8), .visionOS(.v1)], diff --git a/Samples/iOS-ObjectiveCpp-NoModules/App/Sources/AppDelegate.mm b/Samples/iOS-ObjectiveCpp-NoModules/App/Sources/AppDelegate.mm index df8ffdc0b40..650ae2a39db 100644 --- a/Samples/iOS-ObjectiveCpp-NoModules/App/Sources/AppDelegate.mm +++ b/Samples/iOS-ObjectiveCpp-NoModules/App/Sources/AppDelegate.mm @@ -1,17 +1,9 @@ -// Demonstrates the issue from #4543 / #6342: Using Sentry from Objective-C++ -// with CLANG_ENABLE_MODULES=NO. We must use #import instead of @import. -// -// With modules disabled, #import does NOT expose Swift APIs -// (SentrySDK, SentryOptions, options.sessionReplay). We intentionally do NOT -// include Sentry-Swift.h here because that fails with forward declaration -// errors (UIView, UIWindowLevel, etc.) when included from .mm files without -// modules. So we only have #import and the build fails with -// "use of undeclared identifier 'SentrySDK'" - reproducing the issue. -// -// The sample will NOT build until the pure ObjC SDK wrapper (#6342) is implemented. +// Uses Sentry from Objective-C++ with CLANG_ENABLE_MODULES=NO via the pure +// ObjC wrapper (SentryObjC). Import the umbrella header to access SentrySDK, +// SentryOptions, sessionReplay, etc. without requiring Swift modules. #import "AppDelegate.h" -#import +#import #import @implementation AppDelegate @@ -19,14 +11,11 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Fails: SentrySDK undeclared - #import does not expose - // Swift APIs when CLANG_ENABLE_MODULES=NO (SDK 8.54+). [SentrySDK startWithConfigureOptions:^(SentryOptions *options) { options.dsn = @"https://6cc9bae94def43cab8444a99e0031c28@o447951.ingest.sentry.io/5428557"; options.debug = YES; options.tracesSampleRate = @1.0; - // This fails: options.sessionReplay not exposed without @import options.sessionReplay.sessionSampleRate = 0; options.sessionReplay.onErrorSampleRate = 1; }]; diff --git a/Samples/iOS-ObjectiveCpp-NoModules/App/Sources/ViewController.mm b/Samples/iOS-ObjectiveCpp-NoModules/App/Sources/ViewController.mm index a01c9c455cf..2a05cf6c407 100644 --- a/Samples/iOS-ObjectiveCpp-NoModules/App/Sources/ViewController.mm +++ b/Samples/iOS-ObjectiveCpp-NoModules/App/Sources/ViewController.mm @@ -1,9 +1,7 @@ -// Objective-C++ file - same module restrictions as AppDelegate.mm. -// Cannot use @import Sentry here; must use #import. -// No Sentry-Swift.h - would cause forward declaration errors from .mm without modules. +// Objective-C++ file - uses SentryObjC for full SDK access without modules. #import "ViewController.h" -#import +#import #import @implementation ViewController @@ -11,7 +9,6 @@ @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; - // Fails: SentrySDK undeclared with #import alone [SentrySDK addBreadcrumb:[[SentryBreadcrumb alloc] init]]; } diff --git a/Samples/iOS-ObjectiveCpp-NoModules/README.md b/Samples/iOS-ObjectiveCpp-NoModules/README.md index b8bb46e9074..1144f9ddce3 100644 --- a/Samples/iOS-ObjectiveCpp-NoModules/README.md +++ b/Samples/iOS-ObjectiveCpp-NoModules/README.md @@ -1,6 +1,8 @@ # iOS-ObjectiveCpp-NoModules -This sample replicates the issue documented in [getsentry/sentry-cocoa#4543](https://github.com/getsentry/sentry-cocoa/issues/4543): **using the Sentry SDK from Objective-C++ when `-fmodules` and `-fcxx-modules` are not supported.** +This sample demonstrates **using the Sentry SDK from Objective-C++ when `-fmodules` and `-fcxx-modules` are not supported**. + +Originally documented the issue in [getsentry/sentry-cocoa#4543](https://github.com/getsentry/sentry-cocoa/issues/4543). Now demonstrates the solution via **SentryObjC**. ## Problem @@ -18,21 +20,33 @@ With modules disabled: **Result:** `SentrySDK`, `SentryOptions`, `options.sessionReplay` and other Swift-bridged APIs are unavailable. The SDK is effectively unusable from ObjC++ without modules. -## This Sample +## Solution: SentryObjC -- Uses **Objective-C++** (`.mm` files) for AppDelegate and ViewController -- Sets **`CLANG_ENABLE_MODULES = NO`** in the build configuration -- Uses only `#import ` in `.mm` files (does **not** import `Sentry-Swift.h`) -- Demonstrates that Swift-bridged APIs like `SentrySDK` and `options.sessionReplay` are unavailable from ObjC++ without modules +The **SentryObjC** product (introduced in [#6342](https://github.com/getsentry/sentry-cocoa/issues/6342)) provides a pure Objective-C wrapper around the main SDK: + +```objc +#import // Pure ObjC - no Swift modules required -**Build status:** The sample **does NOT build** and reproduces the issue. With only `#import ` (no `Sentry-Swift.h`), the compiler reports `error: use of undeclared identifier 'SentrySDK'`. Attempting to include `#import ` in this setup (see comments in `AppDelegate.mm` / `ViewController.mm`) fails with forward declaration errors when used from `.mm` files without modules. The sample exists to: +[SentryObjCSDK startWithConfigureOptions:^(SentryOptions *options) { + options.dsn = @"..."; + options.tracesSampleRate = @1.0; + options.sessionReplay.sessionSampleRate = 0; // All Swift APIs now available! +}]; +``` + +**Key differences from the main Sentry framework:** -1. Document the exact pattern that fails for ObjC++ consumers in production -2. Serve as a test case for the fix in [getsentry/sentry-cocoa#6342](https://github.com/getsentry/sentry-cocoa/issues/6342) +- ✅ Pure Objective-C public interface +- ✅ No Swift modules or `Sentry-Swift.h` required +- ✅ Works in Objective-C++ (`.mm` files) without modules +- ✅ Full access to all SDK features (SentrySDK, SentryOptions, sessionReplay, etc.) -## Planned Fix (#6342) +## This Sample -Issue [#6342](https://github.com/getsentry/sentry-cocoa/issues/6342) proposes a **pure Objective-C SDK wrapper** that can be imported without modules. Once implemented, this sample should build successfully. +- Uses **Objective-C++** (`.mm` files) for AppDelegate and ViewController +- Sets **`CLANG_ENABLE_MODULES = NO`** in the build configuration +- Depends on **SentryObjC** (SPM product) and imports `#import ` +- Builds successfully with full access to SentrySDK, SentryOptions, sessionReplay, etc. ## Generating the Project @@ -44,5 +58,5 @@ xcodegen generate Or from the repo root: ```bash -make xcode-ci # regenerates all sample projects including this one +make build-sample-iOS-ObjectiveCpp-NoModules ``` diff --git a/Samples/iOS-ObjectiveCpp-NoModules/iOS-ObjectiveCpp-NoModules.yml b/Samples/iOS-ObjectiveCpp-NoModules/iOS-ObjectiveCpp-NoModules.yml index d41005b0bbd..1b06659493a 100644 --- a/Samples/iOS-ObjectiveCpp-NoModules/iOS-ObjectiveCpp-NoModules.yml +++ b/Samples/iOS-ObjectiveCpp-NoModules/iOS-ObjectiveCpp-NoModules.yml @@ -1,14 +1,8 @@ # yaml-language-server: $schema=../../schema/xcodegen.schema.json # -# This sample replicates the issue from #4543: using Sentry from Objective-C++ -# without modules (-fmodules / -fcxx-modules). Many projects (React Native ≤0.76, -# Haxe, custom build systems) cannot enable modules and must use #import instead -# of @import. With CLANG_ENABLE_MODULES=NO, Swift APIs (SentrySDK, sessionReplay, -# etc.) are not available via #import alone. -# -# This sample does NOT build with the current SDK. It exists to: -# - Document the exact failure mode for ObjC++ consumers -# - Serve as a test case for the fix in #6342 (pure ObjC SDK wrapper) +# This sample uses Sentry from Objective-C++ without modules (-fmodules / +# -fcxx-modules). It depends on SentryObjC, the pure ObjC wrapper that exposes +# the full SDK API via #import . # # See README.md in this directory for details. @@ -18,9 +12,9 @@ generateEmptyDirectories: true configs: Debug: debug Release: release -projectReferences: +packages: Sentry: - path: ../../Sentry.xcodeproj + path: ../.. options: bundleIdPrefix: io.sentry targets: @@ -58,8 +52,8 @@ targets: group: App/Configurations buildPhase: none dependencies: - - target: Sentry/Sentry - - target: Sentry/SentrySwiftUI + - package: Sentry + product: SentryObjC configFiles: Debug: App/Configurations/iOS-ObjectiveCpp-NoModules.xcconfig Release: App/Configurations/iOS-ObjectiveCpp-NoModules.xcconfig diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 834c69f6bed..62333ae1414 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -400,6 +400,12 @@ D4B339FA2EA7823000359F3A /* SentryTestUtilsDynamic.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D84DAD4D2B17428D003CF120 /* SentryTestUtilsDynamic.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; D4CBA2472DE06D0200581618 /* libSentryTestUtils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8431F00A29B284F200D8DC56 /* libSentryTestUtils.a */; }; D4CBA2532DE06D1600581618 /* TestConstantTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CBA2512DE06D1600581618 /* TestConstantTests.swift */; }; + D4D86BAE2F6D4D2A0078153D /* Sentry.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63AA759B1EB8AEF500D153DE /* Sentry.framework */; }; + D4D86BAF2F6D4D2A0078153D /* Sentry.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 63AA759B1EB8AEF500D153DE /* Sentry.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + D4D86BB32F6D4D2E0078153D /* SentryObjCBridge.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D4D86B9D2F6D4CF00078153D /* SentryObjCBridge.framework */; }; + D4D86BB42F6D4D2E0078153D /* SentryObjCBridge.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D4D86B9D2F6D4CF00078153D /* SentryObjCBridge.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + D4D86BB82F6D4E780078153D /* Sentry.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63AA759B1EB8AEF500D153DE /* Sentry.framework */; }; + D4D86BB92F6D4E780078153D /* Sentry.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 63AA759B1EB8AEF500D153DE /* Sentry.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; D4DEE6592E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4DEE6582E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m */; }; D4E9420C2E9D1D8000DB7521 /* TestSessionReplayEnvironmentCheckerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4E9420B2E9D1D7600DB7521 /* TestSessionReplayEnvironmentCheckerTests.swift */; }; D4ECA4012E3CBEDE00C757EA /* SentryDummyPublicEmptyClass.m in Sources */ = {isa = PBXBuildFile; fileRef = D4ECA4002E3CBEDE00C757EA /* SentryDummyPublicEmptyClass.m */; }; @@ -563,6 +569,27 @@ remoteGlobalIDString = 8431F00929B284F200D8DC56; remoteInfo = SentryTestUtils; }; + D4D86BB02F6D4D2A0078153D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6327C5CA1EB8A783004E799B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 63AA759A1EB8AEF500D153DE; + remoteInfo = Sentry; + }; + D4D86BB52F6D4D2E0078153D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6327C5CA1EB8A783004E799B /* Project object */; + proxyType = 1; + remoteGlobalIDString = D4D86B9C2F6D4CF00078153D; + remoteInfo = SentryObjCBridge; + }; + D4D86BBA2F6D4E780078153D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 6327C5CA1EB8A783004E799B /* Project object */; + proxyType = 1; + remoteGlobalIDString = 63AA759A1EB8AEF500D153DE; + remoteInfo = Sentry; + }; D8199DC429376FC10074249E /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6327C5CA1EB8A783004E799B /* Project object */; @@ -591,6 +618,29 @@ name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; + D4D86BB22F6D4D2A0078153D /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + D4D86BAF2F6D4D2A0078153D /* Sentry.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + D4D86BB72F6D4D2E0078153D /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + D4D86BB42F6D4D2E0078153D /* SentryObjCBridge.framework in Embed Frameworks */, + D4D86BB92F6D4E780078153D /* Sentry.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; D84DAD5D2B1742C1003CF120 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -630,13 +680,18 @@ 03F84D3027DD4191008FE43F /* SentrySamplingProfiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SentrySamplingProfiler.cpp; path = Sources/Sentry/SentrySamplingProfiler.cpp; sourceTree = SOURCE_ROOT; }; 03F84D3127DD4191008FE43F /* SentryBacktrace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SentryBacktrace.cpp; path = Sources/Sentry/SentryBacktrace.cpp; sourceTree = SOURCE_ROOT; }; 03F9D37B2819A65C00602916 /* SentryProfilerTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryProfilerTests.mm; sourceTree = ""; }; + 04A5EF59986C8131EFFC8A18 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 0948AEC80B17C011B2A15FC3 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS18.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 0A2D8DA6289BC905008720F6 /* SentryViewHierarchyProviderHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryViewHierarchyProviderHelper.h; path = include/SentryViewHierarchyProviderHelper.h; sourceTree = ""; }; 0A2D8DA7289BC905008720F6 /* SentryViewHierarchyProviderHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryViewHierarchyProviderHelper.m; sourceTree = ""; }; 0A56DA5E28ABA01B00C400D5 /* SentryTransactionContext+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryTransactionContext+Private.h"; path = "include/SentryTransactionContext+Private.h"; sourceTree = ""; }; 0A9E917028DC7E7000FB4182 /* SentryInternalCDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryInternalCDefines.h; path = include/SentryInternalCDefines.h; sourceTree = ""; }; + 1275E5EA5712B13FE13C519A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 15E0A8E9240F2C8F00F044E3 /* SentrySerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentrySerialization.h; path = include/SentrySerialization.h; sourceTree = ""; }; 15E0A8EC240F2CB000F044E3 /* SentrySerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentrySerialization.m; sourceTree = ""; }; + 305C03575735126DAA59146C /* SentryObjC.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SentryObjC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 33EB2A8F2C3411AE004FED3D /* SentryWithoutUIKit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryWithoutUIKit.h; path = Public/SentryWithoutUIKit.h; sourceTree = ""; }; + 4688371380F1360CC363010F /* SentryObjC.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SentryObjC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 4BAD9EEF039B46468356FDDF /* SentryDefaultTelemetryProcessorTransport.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDefaultTelemetryProcessorTransport.m; sourceTree = ""; }; 620379DA2AFE1415005AC0C1 /* SentryBuildAppStartSpans.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryBuildAppStartSpans.h; path = include/SentryBuildAppStartSpans.h; sourceTree = ""; }; 620379DC2AFE1432005AC0C1 /* SentryBuildAppStartSpans.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryBuildAppStartSpans.m; sourceTree = ""; }; @@ -818,6 +873,7 @@ 63FE705C20DA4C1000CDBAE8 /* SentryCrashInstallation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashInstallation.m; sourceTree = ""; }; 63FE706320DA4C1000CDBAE8 /* SentryCrashInstallation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashInstallation.h; path = ../../Sentry/include/SentryCrashInstallation.h; sourceTree = ""; }; 63FE706920DA4C1000CDBAE8 /* SentryCrashInstallation+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SentryCrashInstallation+Private.h"; path = "../../Sentry/include/SentryCrashInstallation+Private.h"; sourceTree = ""; }; + 6E190D66E13B263953A7FB3A /* SentryObjC.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SentryObjC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 71F11CDEF5952DF5CC69AC74 /* SentryCrashUUIDConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashUUIDConversion.h; path = ../../../Sentry/include/SentryCrashUUIDConversion.h; sourceTree = ""; }; 7B0DC72D288698F70039995F /* NSMutableDictionary+Sentry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "NSMutableDictionary+Sentry.h"; path = "include/NSMutableDictionary+Sentry.h"; sourceTree = ""; }; 7B0DC72E288698F70039995F /* NSMutableDictionary+Sentry.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSMutableDictionary+Sentry.m"; sourceTree = ""; }; @@ -990,6 +1046,7 @@ 85AE23B0FFFD4830A3D05EBB /* SentryAppStartMeasurementProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryAppStartMeasurementProvider.h; path = include/SentryAppStartMeasurementProvider.h; sourceTree = ""; }; 861265F72404EC1500C4AFDE /* SentryArray.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryArray.h; path = include/SentryArray.h; sourceTree = ""; }; 861265F82404EC1500C4AFDE /* SentryArray.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryArray.m; sourceTree = ""; }; + 8A6D033C024728C84FA8E42C /* SentryObjC.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SentryObjC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 8E133FA025E72DEF00ABD0BF /* SentrySamplingContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySamplingContext.m; sourceTree = ""; }; 8E133FA525E72EB400ABD0BF /* SentrySamplingContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentrySamplingContext.h; path = Public/SentrySamplingContext.h; sourceTree = ""; }; 8E4A037725F6F52100000D77 /* SentrySampleDecision.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySampleDecision.h; path = Public/SentrySampleDecision.h; sourceTree = ""; }; @@ -1026,12 +1083,15 @@ 92D957722E05A44600E20E66 /* SentryAsyncLog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAsyncLog.m; sourceTree = ""; }; 92D957762E05A4F300E20E66 /* SentryAsyncLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryAsyncLog.h; path = include/SentryAsyncLog.h; sourceTree = ""; }; 92F6726A29C8B7B000BFD34D /* SentryUser+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SentryUser+Private.h"; path = "include/SentryUser+Private.h"; sourceTree = ""; }; + A2E9E5F3F15C3455036C5A19 /* SentryObjC.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SentryObjC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A5C5018284FB49D69B453DFE /* SentryDefaultTelemetryProcessorTransport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDefaultTelemetryProcessorTransport.h; path = include/SentryDefaultTelemetryProcessorTransport.h; sourceTree = ""; }; A71411BCABB1428EB4403ADF /* SentryAppStartMeasurementProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAppStartMeasurementProvider.m; sourceTree = ""; }; A8AFFCCC29069C3E00967CD7 /* SentryHttpStatusCodeRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryHttpStatusCodeRange.h; path = Public/SentryHttpStatusCodeRange.h; sourceTree = ""; }; A8AFFCCE2906C03700967CD7 /* SentryRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryRequest.h; path = Public/SentryRequest.h; sourceTree = ""; }; A8F17B2D2901765900990B25 /* SentryRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryRequest.m; sourceTree = ""; }; A8F17B332902870300990B25 /* SentryHttpStatusCodeRange.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryHttpStatusCodeRange.m; sourceTree = ""; }; + D269D1832ED1DD86DF4AF78A /* SentryObjC.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SentryObjC.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D36813946B580095D0A8C6D2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; D41A231A2F3B2A3800F279C9 /* SentrySwiftUIExports.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySwiftUIExports.swift; sourceTree = ""; }; D43A2A0F2DD47FB700114724 /* SentryWeakMap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryWeakMap.h; path = include/SentryWeakMap.h; sourceTree = ""; }; D43A2A112DD47FCE00114724 /* SentryWeakMap.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryWeakMap.m; sourceTree = ""; }; @@ -1053,6 +1113,7 @@ D4A2360A2D5F84FA00D55C58 /* SwiftUITestSample_Base.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = SwiftUITestSample_Base.xctestplan; sourceTree = ""; }; D4CBA2432DE06D0200581618 /* SentryTestUtilsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SentryTestUtilsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; D4CBA2512DE06D1600581618 /* TestConstantTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestConstantTests.swift; sourceTree = ""; }; + D4D86B9D2F6D4CF00078153D /* SentryObjCBridge.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SentryObjCBridge.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D4DEE6582E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryProfileTimeseriesTests.m; sourceTree = ""; }; D4E9420B2E9D1D7600DB7521 /* TestSessionReplayEnvironmentCheckerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSessionReplayEnvironmentCheckerTests.swift; sourceTree = ""; }; D4ECA3FF2E3CBEDE00C757EA /* SentryDummyPrivateEmptyClass.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDummyPrivateEmptyClass.m; sourceTree = ""; }; @@ -1104,6 +1165,9 @@ D8CB7416294724CC00A5F964 /* SentryEnvelopeAttachmentHeader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryEnvelopeAttachmentHeader.m; sourceTree = ""; }; D8CB74182947285A00A5F964 /* SentryEnvelopeItemHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryEnvelopeItemHeader.h; path = include/SentryEnvelopeItemHeader.h; sourceTree = ""; }; D8CB741A2947286500A5F964 /* SentryEnvelopeItemHeader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryEnvelopeItemHeader.m; sourceTree = ""; }; + DCD018246A89E739EB736605 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + E4DEF1CD8F6FCE9782AA347F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + E7065229B5DF395E94BF6842 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; F400C0CC2F368A8B0042712D /* SentryProfilerSampleCreation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryProfilerSampleCreation.m; sourceTree = ""; }; F400C0D32F368A980042712D /* SentryProfilerSampleCreation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryProfilerSampleCreation.h; path = Sources/Sentry/include/SentryProfilerSampleCreation.h; sourceTree = SOURCE_ROOT; }; F40B7BB42F22E00200771198 /* SentryCoreDataSwizzlingHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCoreDataSwizzlingHelper.m; sourceTree = ""; }; @@ -1155,6 +1219,72 @@ /* End PBXFileReference section */ /* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + D4CB399B2F6AEF99005250F2 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + publicHeaders = ( + Public/PrivateSentrySDKOnly.h, + Public/SentryAppStartMeasurement.h, + Public/SentryAttachment.h, + Public/SentryAttribute.h, + Public/SentryAttributeContent.h, + Public/SentryBaggage.h, + Public/SentryBreadcrumb.h, + Public/SentryDebugMeta.h, + Public/SentryDefines.h, + Public/SentryEnvelope.h, + Public/SentryEnvelopeHeader.h, + Public/SentryEnvelopeItem.h, + Public/SentryError.h, + Public/SentryEvent.h, + Public/SentryException.h, + Public/SentryFeedback.h, + Public/SentryFeedbackSource.h, + Public/SentryFrame.h, + Public/SentryGeo.h, + Public/SentryHttpStatusCodeRange.h, + Public/SentryId.h, + Public/SentryLevel.h, + Public/SentryLog.h, + Public/SentryLogger.h, + Public/SentryLogLevel.h, + Public/SentryMeasurementUnit.h, + Public/SentryMechanism.h, + Public/SentryMechanismContext.h, + Public/SentryMessage.h, + Public/SentryMetric.h, + Public/SentryMetricsApi.h, + Public/SentryMetricValue.h, + Public/SentryNSError.h, + Public/SentryObjC.h, + Public/SentryOptions.h, + Public/SentryRedactRegionType.h, + Public/SentryReplayApi.h, + Public/SentryReplayOptions.h, + Public/SentryRequest.h, + Public/SentrySampleDecision.h, + Public/SentrySamplingContext.h, + Public/SentryScope.h, + Public/SentrySDK.h, + Public/SentrySerializable.h, + Public/SentrySpan.h, + Public/SentrySpanContext.h, + Public/SentrySpanId.h, + Public/SentrySpanStatus.h, + Public/SentryStacktrace.h, + Public/SentryThread.h, + Public/SentryTraceContext.h, + Public/SentryTraceHeader.h, + Public/SentryTransactionContext.h, + Public/SentryTransactionNameSource.h, + Public/SentryUnit.h, + Public/SentryUser.h, + SentryMetricsApiImpl.h, + ); + target = 6ECCF11F627ECB41E3A0C7E3 /* SentryObjC */; + }; FAB1CD142F458DA50000CC24 /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = { isa = PBXFileSystemSynchronizedBuildFileExceptionSet; additionalCompilerFlagsByRelativePath = { @@ -1170,12 +1300,23 @@ /* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ /* Begin PBXFileSystemSynchronizedRootGroup section */ + D4CB395D2F6AEEE6005250F2 /* SentryObjC */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (D4CB399B2F6AEF99005250F2 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = SentryObjC; sourceTree = ""; }; + D4CB39972F6AEF01005250F2 /* SentryObjCBridge */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = SentryObjCBridge; sourceTree = ""; }; FA2111C32F22CE8C00DFFABE /* Swift */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = Swift; sourceTree = ""; }; FAB1188E2F4633F40000CC24 /* SentryTestUtils */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = SentryTestUtils; sourceTree = ""; }; FAB1CB682F458C680000CC24 /* SentryTests */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (FAB1CD142F458DA50000CC24 /* PBXFileSystemSynchronizedBuildFileExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = SentryTests; sourceTree = ""; }; /* End PBXFileSystemSynchronizedRootGroup section */ /* Begin PBXFrameworksBuildPhase section */ + 54CAC80331DB858C5A6B20A9 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D4D86BB32F6D4D2E0078153D /* SentryObjCBridge.framework in Frameworks */, + D4D86BB82F6D4E780078153D /* Sentry.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 63AA75971EB8AEF500D153DE /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1223,6 +1364,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D4D86B9A2F6D4CF00078153D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D4D86BAE2F6D4D2A0078153D /* Sentry.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D8199DA729376E9B0074249E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1354,6 +1503,13 @@ 84F994E52A6894B500EC0190 /* CoreData.framework */, 6387B82F1ED851970045A84C /* libz.tbd */, 6304360D1EC05CEF00C4D3FA /* libz.tbd */, + F261834AAD86E04585A25701 /* iOS */, + DCD018246A89E739EB736605 /* Foundation.framework */, + 1275E5EA5712B13FE13C519A /* Foundation.framework */, + 04A5EF59986C8131EFFC8A18 /* Foundation.framework */, + D36813946B580095D0A8C6D2 /* Foundation.framework */, + E4DEF1CD8F6FCE9782AA347F /* Foundation.framework */, + E7065229B5DF395E94BF6842 /* Foundation.framework */, ); name = Frameworks; sourceTree = ""; @@ -1388,6 +1544,13 @@ 8431F00A29B284F200D8DC56 /* libSentryTestUtils.a */, D84DAD4D2B17428D003CF120 /* SentryTestUtilsDynamic.framework */, D4CBA2432DE06D0200581618 /* SentryTestUtilsTests.xctest */, + 4688371380F1360CC363010F /* SentryObjC.framework */, + A2E9E5F3F15C3455036C5A19 /* SentryObjC.framework */, + D269D1832ED1DD86DF4AF78A /* SentryObjC.framework */, + 8A6D033C024728C84FA8E42C /* SentryObjC.framework */, + 305C03575735126DAA59146C /* SentryObjC.framework */, + 6E190D66E13B263953A7FB3A /* SentryObjC.framework */, + D4D86B9D2F6D4CF00078153D /* SentryObjCBridge.framework */, ); name = Products; sourceTree = ""; @@ -1514,6 +1677,8 @@ D8199DB329376ECC0074249E /* SentrySwiftUI */, 63AA75A31EB8AFDF00D153DE /* Configuration */, D8B0542F2A7D35F10056BAF6 /* Resources */, + D4CB39972F6AEF01005250F2 /* SentryObjCBridge */, + D4CB395D2F6AEEE6005250F2 /* SentryObjC */, ); path = Sources; sourceTree = ""; @@ -2274,6 +2439,14 @@ path = Resources; sourceTree = ""; }; + F261834AAD86E04585A25701 /* iOS */ = { + isa = PBXGroup; + children = ( + 0948AEC80B17C011B2A15FC3 /* Foundation.framework */, + ); + name = iOS; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -2527,6 +2700,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 68DF8535FD783AA6C3895154 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8431F00629B284F200D8DC56 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -2534,6 +2714,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D4D86B982F6D4CF00078153D /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D8199DA529376E9B0074249E /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; @@ -2598,6 +2785,30 @@ productReference = 63AA76651EB8CB2F00D153DE /* SentryTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + 6ECCF11F627ECB41E3A0C7E3 /* SentryObjC */ = { + isa = PBXNativeTarget; + buildConfigurationList = A984B37ED2025FF89BFE60B5 /* Build configuration list for PBXNativeTarget "SentryObjC" */; + buildPhases = ( + 68DF8535FD783AA6C3895154 /* Headers */, + C738AC0EF1AD72299702CD0E /* Sources */, + 54CAC80331DB858C5A6B20A9 /* Frameworks */, + 2A78FC2266684907CD8A349A /* Resources */, + D4D86BB72F6D4D2E0078153D /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D4D86BB62F6D4D2E0078153D /* PBXTargetDependency */, + D4D86BBB2F6D4E780078153D /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + D4CB395D2F6AEEE6005250F2 /* SentryObjC */, + ); + name = SentryObjC; + productName = SentryObjC; + productReference = 6E190D66E13B263953A7FB3A /* SentryObjC.framework */; + productType = "com.apple.product-type.framework"; + }; 8431EECF29B27B1100D8DC56 /* SentryProfilerTests */ = { isa = PBXNativeTarget; buildConfigurationList = 8431EFD429B27B1100D8DC56 /* Build configuration list for PBXNativeTarget "SentryProfilerTests" */; @@ -2657,6 +2868,31 @@ productReference = D4CBA2432DE06D0200581618 /* SentryTestUtilsTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; + D4D86B9C2F6D4CF00078153D /* SentryObjCBridge */ = { + isa = PBXNativeTarget; + buildConfigurationList = D4D86BAC2F6D4CF00078153D /* Build configuration list for PBXNativeTarget "SentryObjCBridge" */; + buildPhases = ( + D4D86B982F6D4CF00078153D /* Headers */, + D4D86B992F6D4CF00078153D /* Sources */, + D4D86B9A2F6D4CF00078153D /* Frameworks */, + D4D86B9B2F6D4CF00078153D /* Resources */, + D4D86BB22F6D4D2A0078153D /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + D4D86BB12F6D4D2A0078153D /* PBXTargetDependency */, + ); + fileSystemSynchronizedGroups = ( + D4CB39972F6AEF01005250F2 /* SentryObjCBridge */, + ); + name = SentryObjCBridge; + packageProductDependencies = ( + ); + productName = SentryObjCBridge; + productReference = D4D86B9D2F6D4CF00078153D /* SentryObjCBridge.framework */; + productType = "com.apple.product-type.framework"; + }; D8199DA929376E9B0074249E /* SentrySwiftUI */ = { isa = PBXNativeTarget; buildConfigurationList = D8199DB229376E9B0074249E /* Build configuration list for PBXNativeTarget "SentrySwiftUI" */; @@ -2700,7 +2936,7 @@ 6327C5CA1EB8A783004E799B /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 2610; + LastSwiftUpdateCheck = 2630; LastUpgradeCheck = 1400; ORGANIZATIONNAME = Sentry; TargetAttributes = { @@ -2725,6 +2961,9 @@ D4CBA2422DE06D0200581618 = { CreatedOnToolsVersion = 16.3; }; + D4D86B9C2F6D4CF00078153D = { + CreatedOnToolsVersion = 26.3; + }; D8199DA929376E9B0074249E = { CreatedOnToolsVersion = 14.1; }; @@ -2759,6 +2998,8 @@ 8431F00929B284F200D8DC56 /* SentryTestUtils */, D84DAD4C2B17428D003CF120 /* SentryTestUtilsDynamic */, D4CBA2422DE06D0200581618 /* SentryTestUtilsTests */, + 6ECCF11F627ECB41E3A0C7E3 /* SentryObjC */, + D4D86B9C2F6D4CF00078153D /* SentryObjCBridge */, ); }; /* End PBXProject section */ @@ -2802,6 +3043,13 @@ /* End PBXReferenceProxy section */ /* Begin PBXResourcesBuildPhase section */ + 2A78FC2266684907CD8A349A /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 63AA75991EB8AEF500D153DE /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -2833,6 +3081,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D4D86B9B2F6D4CF00078153D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D8199DA829376E9B0074249E /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -3110,6 +3365,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + C738AC0EF1AD72299702CD0E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D4CBA23F2DE06D0200581618 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -3126,6 +3388,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + D4D86B992F6D4CF00078153D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; D8199DA629376E9B0074249E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -3170,6 +3439,21 @@ target = 8431F00929B284F200D8DC56 /* SentryTestUtils */; targetProxy = D4CBA2482DE06D0200581618 /* PBXContainerItemProxy */; }; + D4D86BB12F6D4D2A0078153D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 63AA759A1EB8AEF500D153DE /* Sentry */; + targetProxy = D4D86BB02F6D4D2A0078153D /* PBXContainerItemProxy */; + }; + D4D86BB62F6D4D2E0078153D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D4D86B9C2F6D4CF00078153D /* SentryObjCBridge */; + targetProxy = D4D86BB52F6D4D2E0078153D /* PBXContainerItemProxy */; + }; + D4D86BBB2F6D4E780078153D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 63AA759A1EB8AEF500D153DE /* Sentry */; + targetProxy = D4D86BBA2F6D4E780078153D /* PBXContainerItemProxy */; + }; D8199DC529376FC10074249E /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 63AA759A1EB8AEF500D153DE /* Sentry */; @@ -3183,6 +3467,159 @@ /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ + 1F1573C6B67DA6FCDE1D0DAA /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = NO; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/Sources/SentryObjC/Public", + ); + INFOPLIST_FILE = Sources/SentryObjC/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = Sources/SentryObjC/Public/module.modulemap; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryObjC; + PRODUCT_MODULE_NAME = SentryObjC; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Headers"; + SDKROOT = iphoneos; + SKIP_INSTALL = NO; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 1FC88A1423B083B126005FD4 /* TestCI */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = NO; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/Sources/SentryObjC/Public", + ); + INFOPLIST_FILE = Sources/SentryObjC/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = Sources/SentryObjC/Public/module.modulemap; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryObjC; + PRODUCT_MODULE_NAME = SentryObjC; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Headers"; + SDKROOT = iphoneos; + SKIP_INSTALL = NO; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = TestCI; + }; + 336BE9E1AF54344405C97C1B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = NO; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/Sources/SentryObjC/Public", + ); + INFOPLIST_FILE = Sources/SentryObjC/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = Sources/SentryObjC/Public/module.modulemap; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryObjC; + PRODUCT_MODULE_NAME = SentryObjC; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Headers"; + SDKROOT = iphoneos; + SKIP_INSTALL = NO; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 57D5E87B3F6B3FCA00B009CD /* DebugWithoutUIKit */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = NO; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/Sources/SentryObjC/Public", + ); + INFOPLIST_FILE = Sources/SentryObjC/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = Sources/SentryObjC/Public/module.modulemap; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryObjC; + PRODUCT_MODULE_NAME = SentryObjC; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Headers"; + SDKROOT = iphoneos; + SKIP_INSTALL = NO; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = DebugWithoutUIKit; + }; 6327C5E51EB8A783004E799B /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = D8BD2E27292D1F7300D96C6A /* SDK.xcconfig */; @@ -3304,6 +3741,45 @@ }; name = Release; }; + 7730A78F9BA71FFF63B1841A /* ReleaseWithoutUIKit */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = NO; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/Sources/SentryObjC/Public", + ); + INFOPLIST_FILE = Sources/SentryObjC/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = Sources/SentryObjC/Public/module.modulemap; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryObjC; + PRODUCT_MODULE_NAME = SentryObjC; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Headers"; + SDKROOT = iphoneos; + SKIP_INSTALL = NO; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = ReleaseWithoutUIKit; + }; 7BFC80A8282B736400E83A05 /* TestCI */ = { isa = XCBuildConfiguration; baseConfigurationReference = D8BD2E27292D1F7300D96C6A /* SDK.xcconfig */; @@ -4067,7 +4543,545 @@ }; name = ReleaseWithoutUIKit; }; - D8079A6727178911004B0F61 /* Test */ = { + D4D86BA12F6D4CF00078153D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 97JCY7859U; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Sentry. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryObjCBridge; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + D4D86BA22F6D4CF00078153D /* DebugWithoutUIKit */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = 97JCY7859U; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Sentry. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryObjCBridge; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = DebugWithoutUIKit; + }; + D4D86BA32F6D4CF00078153D /* Test */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 97JCY7859U; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Sentry. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryObjCBridge; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Test; + }; + D4D86BA42F6D4CF00078153D /* TestCI */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 97JCY7859U; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Sentry. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryObjCBridge; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = TestCI; + }; + D4D86BA52F6D4CF00078153D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 97JCY7859U; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Sentry. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryObjCBridge; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + D4D86BA62F6D4CF00078153D /* ReleaseWithoutUIKit */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + CURRENT_PROJECT_VERSION = 1; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = 97JCY7859U; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2026 Sentry. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryObjCBridge; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = macosx; + SKIP_INSTALL = YES; + STRING_CATALOG_GENERATE_SYMBOLS = YES; + SWIFT_APPROACHABLE_CONCURRENCY = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INSTALL_MODULE = YES; + SWIFT_INSTALL_OBJC_HEADER = NO; + SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = ReleaseWithoutUIKit; + }; + D8079A6727178911004B0F61 /* Test */ = { isa = XCBuildConfiguration; baseConfigurationReference = D8BD2E27292D1F7300D96C6A /* SDK.xcconfig */; buildSettings = { @@ -4128,6 +5142,44 @@ }; name = Test; }; + D80A9691B772CACC215F6CF7 /* Test */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = NO; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "$(SRCROOT)/Sources/SentryObjC/Public", + ); + INFOPLIST_FILE = Sources/SentryObjC/Info.plist; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 15.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MODULEMAP_FILE = Sources/SentryObjC/Public/module.modulemap; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryObjC; + PRODUCT_MODULE_NAME = SentryObjC; + PRODUCT_NAME = "$(TARGET_NAME)"; + PUBLIC_HEADERS_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Headers"; + SDKROOT = iphoneos; + SKIP_INSTALL = NO; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Test; + }; D8199DAE29376E9B0074249E /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = D8199DCF29376FF40074249E /* SentrySwiftUI.xcconfig */; @@ -4698,6 +5750,19 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + A984B37ED2025FF89BFE60B5 /* Build configuration list for PBXNativeTarget "SentryObjC" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 336BE9E1AF54344405C97C1B /* Release */, + 1F1573C6B67DA6FCDE1D0DAA /* Debug */, + 57D5E87B3F6B3FCA00B009CD /* DebugWithoutUIKit */, + D80A9691B772CACC215F6CF7 /* Test */, + 1FC88A1423B083B126005FD4 /* TestCI */, + 7730A78F9BA71FFF63B1841A /* ReleaseWithoutUIKit */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; D4CBA2502DE06D0200581618 /* Build configuration list for PBXNativeTarget "SentryTestUtilsTests" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -4711,6 +5776,19 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + D4D86BAC2F6D4CF00078153D /* Build configuration list for PBXNativeTarget "SentryObjCBridge" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D4D86BA12F6D4CF00078153D /* Debug */, + D4D86BA22F6D4CF00078153D /* DebugWithoutUIKit */, + D4D86BA32F6D4CF00078153D /* Test */, + D4D86BA42F6D4CF00078153D /* TestCI */, + D4D86BA52F6D4CF00078153D /* Release */, + D4D86BA62F6D4CF00078153D /* ReleaseWithoutUIKit */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; D8199DB229376E9B0074249E /* Build configuration list for PBXNativeTarget "SentrySwiftUI" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Sources/SentryObjC/Info.plist b/Sources/SentryObjC/Info.plist new file mode 100644 index 00000000000..8b5512b8523 --- /dev/null +++ b/Sources/SentryObjC/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + $(CURRENT_PROJECT_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/Sources/SentryObjC/Public/PrivateSentrySDKOnly.h b/Sources/SentryObjC/Public/PrivateSentrySDKOnly.h new file mode 100644 index 00000000000..68d34188203 --- /dev/null +++ b/Sources/SentryObjC/Public/PrivateSentrySDKOnly.h @@ -0,0 +1,30 @@ +#import + +@class SentryEnvelope; +@class SentryOptions; + +NS_ASSUME_NONNULL_BEGIN + +/** + * SPI (System Programming Interface) for hybrid SDK wrappers. + * + * This class exposes internal SDK functionality needed by + * React Native, Flutter, .NET, Unity, and Unreal SDK wrappers. + */ +@interface PrivateSentrySDKOnly : NSObject + ++ (void)setSdkName:(NSString *)sdkName; ++ (void)setSdkName:(NSString *)sdkName andVersionString:(NSString *)versionString; ++ (NSString *)getSdkName; ++ (NSString *)getSdkVersionString; + +@property (class, nonatomic, readonly, copy) SentryOptions *options; + ++ (void)captureEnvelope:(SentryEnvelope *)envelope; ++ (void)storeEnvelope:(SentryEnvelope *)envelope; + +@property (class, nonatomic, readonly, copy) NSString *installationID; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryAppStartMeasurement.h b/Sources/SentryObjC/Public/SentryAppStartMeasurement.h new file mode 100644 index 00000000000..440ca1b3991 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryAppStartMeasurement.h @@ -0,0 +1,61 @@ +#import + +#import "SentryDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +#if SENTRY_OBJC_UIKIT_AVAILABLE + +/** + * App start type classification for performance tracking. + */ +typedef NS_ENUM(NSUInteger, SentryAppStartType) { + /// App was already in memory (backgrounded or suspended). + SentryAppStartTypeWarm, + /// App was not in memory and had to be loaded from disk. + SentryAppStartTypeCold, + /// Start type could not be determined. + SentryAppStartTypeUnknown, +}; + +/** + * App start measurement for performance monitoring. + * + * @warning Not available in DebugWithoutUIKit / ReleaseWithoutUIKit configurations. + */ +@interface SentryAppStartMeasurement : NSObject + +SENTRY_NO_INIT + +/// The type of app start (cold, warm, or unknown). +@property (readonly, nonatomic, assign) SentryAppStartType type; + +/// Whether the app was pre-warmed by the system before launch. +@property (readonly, nonatomic, assign) BOOL isPreWarmed; + +/// Total duration of the app start in seconds. +@property (readonly, nonatomic, assign) NSTimeInterval duration; + +/// Timestamp when the app process started. +@property (readonly, nonatomic, strong) NSDate *appStartTimestamp; + +/// System timestamp (mach_absolute_time) when runtime initialization began. +@property (readonly, nonatomic, assign) uint64_t runtimeInitSystemTimestamp; + +/// Timestamp when Objective-C runtime initialization began. +@property (readonly, nonatomic, strong) NSDate *runtimeInitTimestamp; + +/// Timestamp when static module initializers (+load methods) were invoked. +@property (readonly, nonatomic, strong) NSDate *moduleInitializationTimestamp; + +/// Timestamp when the Sentry SDK was initialized. +@property (readonly, nonatomic, strong) NSDate *sdkStartTimestamp; + +/// Timestamp when application:didFinishLaunchingWithOptions: completed. +@property (readonly, nonatomic, strong) NSDate *didFinishLaunchingTimestamp; + +@end + +#endif // SENTRY_OBJC_UIKIT_AVAILABLE + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryAttachment.h b/Sources/SentryObjC/Public/SentryAttachment.h new file mode 100644 index 00000000000..a5eafc25a80 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryAttachment.h @@ -0,0 +1,141 @@ +#import + +#import "SentryDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Attachment type for downstream SDKs. + */ +typedef NS_ENUM(NSInteger, SentryAttachmentType) { + /** General event attachment */ + kSentryAttachmentTypeEventAttachment, + /** View hierarchy attachment */ + kSentryAttachmentTypeViewHierarchy +}; + +/** + * Additional file to store alongside an event. + * + * Attachments can be used to send additional files (logs, screenshots, etc.) + * with Sentry events. They can be created from in-memory data or from files + * on disk. + * + * @see SentryScope + */ +@interface SentryAttachment : NSObject + +SENTRY_NO_INIT + +/** + * Creates an attachment from in-memory data. + * + * @param data The file data. + * @param filename The filename to use for this attachment. + * @return A new attachment instance. + */ +- (instancetype)initWithData:(NSData *)data filename:(NSString *)filename; + +/** + * Creates an attachment from in-memory data with a content type. + * + * @param data The file data. + * @param filename The filename to use for this attachment. + * @param contentType MIME type of the attachment (e.g., "text/plain", "image/png"). + * @return A new attachment instance. + */ +- (instancetype)initWithData:(NSData *)data + filename:(NSString *)filename + contentType:(nullable NSString *)contentType; + +/** + * Creates an attachment from a file path. + * + * The filename is derived from the path. + * + * @param path Path to the file to attach. + * @return A new attachment instance. + */ +- (instancetype)initWithPath:(NSString *)path; + +/** + * Creates an attachment from a file path with a custom filename. + * + * @param path Path to the file to attach. + * @param filename The filename to use for this attachment. + * @return A new attachment instance. + */ +- (instancetype)initWithPath:(NSString *)path filename:(NSString *)filename; + +/** + * Creates an attachment from a file path with filename and content type. + * + * @param path Path to the file to attach. + * @param filename The filename to use for this attachment. + * @param contentType MIME type of the attachment. + * @return A new attachment instance. + */ +- (instancetype)initWithPath:(NSString *)path + filename:(NSString *)filename + contentType:(nullable NSString *)contentType; + +/** + * Creates an attachment from in-memory data with full options. + * + * @param data The file data. + * @param filename The filename to use for this attachment. + * @param contentType MIME type of the attachment. + * @param attachmentType The type of attachment. + * @return A new attachment instance. + */ +- (instancetype)initWithData:(NSData *)data + filename:(NSString *)filename + contentType:(nullable NSString *)contentType + attachmentType:(SentryAttachmentType)attachmentType; + +/** + * Creates an attachment from a file path with full options. + * + * @param path Path to the file to attach. + * @param filename The filename to use for this attachment. + * @param contentType MIME type of the attachment. + * @param attachmentType The type of attachment. + * @return A new attachment instance. + */ +- (instancetype)initWithPath:(NSString *)path + filename:(NSString *)filename + contentType:(nullable NSString *)contentType + attachmentType:(SentryAttachmentType)attachmentType; + +/** + * The attachment data, if created from data. + * + * @c nil for path-based attachments. + */ +@property (readonly, nonatomic, strong, nullable) NSData *data; + +/** + * The file path, if created from a path. + * + * @c nil for data-based attachments. + */ +@property (readonly, nonatomic, copy, nullable) NSString *path; + +/** + * The filename for this attachment. + */ +@property (readonly, nonatomic, copy) NSString *filename; + +/** + * MIME type of the attachment. + */ +@property (readonly, nonatomic, copy, nullable) NSString *contentType; + +/** + * The type of this attachment. + */ +@property (readonly, nonatomic) SentryAttachmentType attachmentType; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryAttribute.h b/Sources/SentryObjC/Public/SentryAttribute.h new file mode 100644 index 00000000000..5157e051202 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryAttribute.h @@ -0,0 +1,20 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A typed attribute value for structured logging and metrics. + */ +@interface SentryAttribute : NSObject + +@property (nonatomic, readonly, copy) NSString *type; +@property (nonatomic, readonly, strong) id value; + +- (instancetype)initWithString:(NSString *)value; +- (instancetype)initWithBoolean:(BOOL)value; +- (instancetype)initWithInteger:(NSInteger)value; +- (instancetype)initWithDouble:(double)value; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryAttributeContent.h b/Sources/SentryObjC/Public/SentryAttributeContent.h new file mode 100644 index 00000000000..1fdb6982bbd --- /dev/null +++ b/Sources/SentryObjC/Public/SentryAttributeContent.h @@ -0,0 +1,130 @@ +#import + +#import "SentryDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Type of attribute content value. + */ +typedef NS_ENUM(NSInteger, SentryAttributeContentType) { + /// String value. + SentryAttributeContentTypeString, + /// Boolean value. + SentryAttributeContentTypeBoolean, + /// Integer value. + SentryAttributeContentTypeInteger, + /// Double-precision floating point value. + SentryAttributeContentTypeDouble, + /// Array of strings. + SentryAttributeContentTypeStringArray, + /// Array of booleans (as NSNumber). + SentryAttributeContentTypeBooleanArray, + /// Array of integers (as NSNumber). + SentryAttributeContentTypeIntegerArray, + /// Array of doubles (as NSNumber). + SentryAttributeContentTypeDoubleArray +}; + +/** + * Typed attribute content for custom event attributes. + * + * Wraps various value types (string, number, boolean, arrays) with type information + * for structured event data. Use the factory methods to create instances. + */ +@interface SentryAttributeContent : NSObject + +/// The type of value stored in this attribute. +@property (nonatomic, readonly) SentryAttributeContentType type; + +/// The string value, if @c type is @c SentryAttributeContentTypeString. +@property (nonatomic, readonly, nullable) NSString *stringValue; + +/// The boolean value, if @c type is @c SentryAttributeContentTypeBoolean. +@property (nonatomic, readonly) BOOL booleanValue; + +/// The integer value, if @c type is @c SentryAttributeContentTypeInteger. +@property (nonatomic, readonly) NSInteger integerValue; + +/// The double value, if @c type is @c SentryAttributeContentTypeDouble. +@property (nonatomic, readonly) double doubleValue; + +/// The string array value, if @c type is @c SentryAttributeContentTypeStringArray. +@property (nonatomic, readonly, nullable) NSArray *stringArrayValue; + +/// The boolean array value, if @c type is @c SentryAttributeContentTypeBooleanArray. +@property (nonatomic, readonly, nullable) NSArray *booleanArrayValue; + +/// The integer array value, if @c type is @c SentryAttributeContentTypeIntegerArray. +@property (nonatomic, readonly, nullable) NSArray *integerArrayValue; + +/// The double array value, if @c type is @c SentryAttributeContentTypeDoubleArray. +@property (nonatomic, readonly, nullable) NSArray *doubleArrayValue; + +/** + * Creates an attribute with a string value. + * + * @param value The string value. + * @return A new attribute content instance. + */ ++ (instancetype)stringWithValue:(NSString *)value; + +/** + * Creates an attribute with a boolean value. + * + * @param value The boolean value. + * @return A new attribute content instance. + */ ++ (instancetype)booleanWithValue:(BOOL)value; + +/** + * Creates an attribute with an integer value. + * + * @param value The integer value. + * @return A new attribute content instance. + */ ++ (instancetype)integerWithValue:(NSInteger)value; + +/** + * Creates an attribute with a double value. + * + * @param value The double value. + * @return A new attribute content instance. + */ ++ (instancetype)doubleWithValue:(double)value; + +/** + * Creates an attribute with a string array value. + * + * @param value The array of strings. + * @return A new attribute content instance. + */ ++ (instancetype)stringArrayWithValue:(NSArray *)value; + +/** + * Creates an attribute with a boolean array value. + * + * @param value The array of booleans (as @c NSNumber). + * @return A new attribute content instance. + */ ++ (instancetype)booleanArrayWithValue:(NSArray *)value; + +/** + * Creates an attribute with an integer array value. + * + * @param value The array of integers (as @c NSNumber). + * @return A new attribute content instance. + */ ++ (instancetype)integerArrayWithValue:(NSArray *)value; + +/** + * Creates an attribute with a double array value. + * + * @param value The array of doubles (as @c NSNumber). + * @return A new attribute content instance. + */ ++ (instancetype)doubleArrayWithValue:(NSArray *)value; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryBaggage.h b/Sources/SentryObjC/Public/SentryBaggage.h new file mode 100644 index 00000000000..8c4fad6dc66 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryBaggage.h @@ -0,0 +1,107 @@ +#import + +@class SentryId; + +NS_ASSUME_NONNULL_BEGIN + +static NSString *const SENTRY_BAGGAGE_HEADER = @"baggage"; + +/** + * Baggage for distributed tracing propagation. + * + * Carries trace context metadata across service boundaries via HTTP headers. + * Used for correlating traces across distributed systems. + * + * @see SentryTraceContext + */ +@interface SentryBaggage : NSObject + +/// The trace ID for this distributed trace. +@property (nonatomic, readonly) SentryId *traceId; + +/// The Sentry project public key (DSN public key). +@property (nonatomic, readonly) NSString *publicKey; + +/// The release name/version of the application. +@property (nullable, nonatomic, readonly) NSString *releaseName; + +/// The environment name (e.g., "production", "staging"). +@property (nullable, nonatomic, readonly) NSString *environment; + +/// The transaction name being traced. +@property (nullable, nonatomic, readonly) NSString *transaction; + +/// The user ID associated with this trace. +@property (nullable, nonatomic, readonly) NSString *userId; + +/// Random value used for deterministic sampling decisions. +@property (nullable, nonatomic, readonly) NSString *sampleRand; + +/// The sample rate applied to this trace (as a string). +@property (nullable, nonatomic, readonly) NSString *sampleRate; + +/// Whether this trace was sampled (@c "true" or @c "false"). +@property (nullable, nonatomic, strong) NSString *sampled; + +/// Session replay ID if replay is active for this trace. +@property (nullable, nonatomic, strong) NSString *replayId; + +/** + * Creates baggage with trace context. + * + * @param traceId The trace ID. + * @param publicKey The DSN public key. + * @param releaseName The release name. + * @param environment The environment. + * @param transaction The transaction name. + * @param sampleRate The sample rate. + * @param sampled Whether the trace was sampled. + * @param replayId The replay ID. + * @return A new baggage instance. + */ +- (instancetype)initWithTraceId:(SentryId *)traceId + publicKey:(NSString *)publicKey + releaseName:(nullable NSString *)releaseName + environment:(nullable NSString *)environment + transaction:(nullable NSString *)transaction + sampleRate:(nullable NSString *)sampleRate + sampled:(nullable NSString *)sampled + replayId:(nullable NSString *)replayId; + +/** + * Creates baggage with trace context and sample randomness. + * + * @param traceId The trace ID. + * @param publicKey The DSN public key. + * @param releaseName The release name. + * @param environment The environment. + * @param transaction The transaction name. + * @param sampleRate The sample rate. + * @param sampleRand Random value for sampling decisions. + * @param sampled Whether the trace was sampled. + * @param replayId The replay ID. + * @return A new baggage instance. + */ +- (instancetype)initWithTraceId:(SentryId *)traceId + publicKey:(NSString *)publicKey + releaseName:(nullable NSString *)releaseName + environment:(nullable NSString *)environment + transaction:(nullable NSString *)transaction + sampleRate:(nullable NSString *)sampleRate + sampleRand:(nullable NSString *)sampleRand + sampled:(nullable NSString *)sampled + replayId:(nullable NSString *)replayId; + +/** + * Serializes baggage to an HTTP header value. + * + * Merges Sentry baggage with any original baggage from upstream services. + * + * @param originalBaggage Original baggage key-value pairs from upstream. + * @return HTTP header value suitable for the @c baggage header. + */ +- (NSString *)toHTTPHeaderWithOriginalBaggage:(NSDictionary *)originalBaggage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryBreadcrumb.h b/Sources/SentryObjC/Public/SentryBreadcrumb.h new file mode 100644 index 00000000000..9cf1466016c --- /dev/null +++ b/Sources/SentryObjC/Public/SentryBreadcrumb.h @@ -0,0 +1,111 @@ +#import + +#import "SentryLevel.h" +#import "SentrySerializable.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Breadcrumb representing a discrete event that occurred before a Sentry event. + * + * Breadcrumbs are used to create a trail of events leading up to an error or exception. + * They provide context about what the user was doing when the error occurred. + * + * @see SentryScope + */ +@interface SentryBreadcrumb : NSObject + +/** + * Severity level of this breadcrumb. + */ +@property (nonatomic) SentryLevel level; + +/** + * Category of this breadcrumb. + * + * Common categories include "navigation", "http", "user", "console", etc. + */ +@property (nonatomic, copy) NSString *category; + +/** + * Timestamp when this breadcrumb was created. + */ +@property (nonatomic, strong, nullable) NSDate *timestamp; + +/** + * Type of breadcrumb. + * + * Examples: "default", "http", "navigation", "error". The type is used + * to determine the breadcrumb icon in the Sentry UI. + */ +@property (nonatomic, copy, nullable) NSString *type; + +/** + * Human-readable message describing this breadcrumb. + */ +@property (nonatomic, copy, nullable) NSString *message; + +/** + * Origin identifying the source of this breadcrumb. + * + * Hybrid SDKs use this to distinguish native breadcrumbs from those + * created by JavaScript, Flutter, or other layers. + */ +@property (nonatomic, copy, nullable) NSString *origin; + +/** + * Arbitrary additional data associated with this breadcrumb. + * + * This data is displayed in the Sentry UI alongside the breadcrumb. + */ +@property (nonatomic, strong, nullable) NSDictionary *data; + +/** + * Creates a breadcrumb with the specified level and category. + * + * @param level Severity level for this breadcrumb. + * @param category Category string for this breadcrumb. + * @return A new breadcrumb instance. + */ +- (instancetype)initWithLevel:(SentryLevel)level category:(NSString *)category; + +/** + * Creates a breadcrumb with default values. + * + * @return A new breadcrumb instance. + */ +- (instancetype)init; + +/** + * Serializes the breadcrumb to a dictionary. + * + * @return Dictionary representation of the breadcrumb. + */ +- (NSDictionary *)serialize; + +/** + * Compares this breadcrumb with another object for equality. + * + * @param other The object to compare with. + * @return @c YES if the objects are equal, @c NO otherwise. + */ +- (BOOL)isEqual:(nullable id)other; + +/** + * Compares this breadcrumb with another breadcrumb for equality. + * + * @param breadcrumb The breadcrumb to compare with. + * @return @c YES if the breadcrumbs are equal, @c NO otherwise. + */ +- (BOOL)isEqualToBreadcrumb:(SentryBreadcrumb *)breadcrumb; + +/** + * Returns a hash value for this breadcrumb. + * + * @return The hash value. + */ +- (NSUInteger)hash; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryDebugMeta.h b/Sources/SentryObjC/Public/SentryDebugMeta.h new file mode 100644 index 00000000000..1de7a824a78 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryDebugMeta.h @@ -0,0 +1,61 @@ +#import + +#import "SentrySerializable.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Information about a loaded library and its memory address. + * + * Debug metadata helps Sentry symbolicate stack traces by identifying which + * binaries were loaded and where they were mapped in memory. Each entry represents + * one framework, library, or executable. + * + * @see SentryEvent + */ +@interface SentryDebugMeta : NSObject + +/** + * Unique identifier for the debug information (dSYM UUID). + * + * Used to locate the correct debug symbols for symbolication. + */ +@property (nonatomic, copy, nullable) NSString *debugID; + +/** + * Type of debug information. + * + * Typically "macho" for iOS/macOS binaries. + */ +@property (nonatomic, copy, nullable) NSString *type; + +/** + * Size of the binary image in bytes. + */ +@property (nonatomic, copy, nullable) NSNumber *imageSize; + +/** + * Base memory address where the image was loaded. + */ +@property (nonatomic, copy, nullable) NSString *imageAddress; + +/** + * Virtual memory address of the image. + */ +@property (nonatomic, copy, nullable) NSString *imageVmAddress; + +/** + * Path to the binary file. + */ +@property (nonatomic, copy, nullable) NSString *codeFile; + +/** + * Creates a new debug metadata instance. + * + * @return A new debug metadata instance. + */ +- (instancetype)init; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryDefines.h b/Sources/SentryObjC/Public/SentryDefines.h new file mode 100644 index 00000000000..9967b0888b9 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryDefines.h @@ -0,0 +1,64 @@ +#import + +#ifndef TARGET_OS_VISION +# define TARGET_OS_VISION 0 +#endif + +#if TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_VISION +# define SENTRY_OBJC_UIKIT_AVAILABLE 1 +#else +# define SENTRY_OBJC_UIKIT_AVAILABLE 0 +#endif + +#if SENTRY_OBJC_UIKIT_AVAILABLE && !TARGET_OS_VISION +# define SENTRY_OBJC_REPLAY_SUPPORTED 1 +#else +# define SENTRY_OBJC_REPLAY_SUPPORTED 0 +#endif + +@class SentryBreadcrumb; +@class SentryEvent; +@class SentryLog; +@class SentrySamplingContext; +@protocol SentrySpan; + +NS_ASSUME_NONNULL_BEGIN + +typedef SentryBreadcrumb *_Nullable (^SentryBeforeBreadcrumbCallback)( + SentryBreadcrumb *_Nonnull breadcrumb); +typedef SentryEvent *_Nullable (^SentryBeforeSendEventCallback)(SentryEvent *_Nonnull event); +typedef id _Nullable (^SentryBeforeSendSpanCallback)(id _Nonnull span); +typedef SentryLog *_Nullable (^SentryBeforeSendLogCallback)(SentryLog *_Nonnull log); +typedef BOOL (^SentryBeforeCaptureScreenshotCallback)(SentryEvent *_Nonnull event); +typedef void (^SentryOnCrashedLastRunCallback)(SentryEvent *_Nonnull event); +typedef NSNumber *_Nullable (^SentryTracesSamplerCallback)( + SentrySamplingContext *_Nonnull samplingContext); + +#ifdef __cplusplus +# define SENTRY_OBJC_EXTERN extern "C" __attribute__((visibility("default"))) +#else +# define SENTRY_OBJC_EXTERN extern __attribute__((visibility("default"))) +#endif + +#define SENTRY_NO_INIT \ + -(instancetype)init NS_UNAVAILABLE; \ + +(instancetype) new NS_UNAVAILABLE; + +/** + * SentryObjC — Pure Objective-C wrapper for the Sentry SDK. + * + * This module provides a self-contained public interface usable from Objective-C + * and Objective-C++ without requiring Clang modules (-fmodules). Use this when + * integrating Sentry into projects that cannot enable modules (e.g. React Native, + * Haxe, custom build systems). + * + * @discussion Import the umbrella header: + * @code + * #import "SentryObjC.h" + * @endcode + * + * @see SentrySDK For the main SDK entry point. + * @see SentryOptions For configuration options. + */ + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryEnvelope.h b/Sources/SentryObjC/Public/SentryEnvelope.h new file mode 100644 index 00000000000..2378649c0d9 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryEnvelope.h @@ -0,0 +1,20 @@ +#import + +@class SentryEnvelopeHeader; +@class SentryEnvelopeItem; + +NS_ASSUME_NONNULL_BEGIN + +/** + * A Sentry envelope containing one or more items. + */ +@interface SentryEnvelope : NSObject + +@property (nonatomic, readonly, strong) SentryEnvelopeHeader *header; +@property (nonatomic, readonly, copy) NSArray *items; + +- (instancetype)initWithHeader:(SentryEnvelopeHeader *)header singleItem:(SentryEnvelopeItem *)item; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryEnvelopeHeader.h b/Sources/SentryObjC/Public/SentryEnvelopeHeader.h new file mode 100644 index 00000000000..6674b5a4ff6 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryEnvelopeHeader.h @@ -0,0 +1,21 @@ +#import + +@class SentryId; +@class SentryTraceContext; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Header of a Sentry envelope. + */ +@interface SentryEnvelopeHeader : NSObject + +@property (nonatomic, readonly, strong, nullable) SentryId *eventId; +@property (nonatomic, strong, nullable) NSDate *sentAt; + +- (instancetype)initWithId:(nullable SentryId *)eventId + traceContext:(nullable SentryTraceContext *)traceContext; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryEnvelopeItem.h b/Sources/SentryObjC/Public/SentryEnvelopeItem.h new file mode 100644 index 00000000000..05552b8e38b --- /dev/null +++ b/Sources/SentryObjC/Public/SentryEnvelopeItem.h @@ -0,0 +1,17 @@ +#import + +@class SentryAttachment; + +NS_ASSUME_NONNULL_BEGIN + +/** + * An item within a Sentry envelope. + */ +@interface SentryEnvelopeItem : NSObject + +- (nullable instancetype)initWithAttachment:(SentryAttachment *)attachment + maxAttachmentSize:(NSUInteger)maxAttachmentSize; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryError.h b/Sources/SentryObjC/Public/SentryError.h new file mode 100644 index 00000000000..4000efeda50 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryError.h @@ -0,0 +1,87 @@ +#import + +#if TARGET_OS_OSX || TARGET_OS_IOS +# import +#else +typedef int kern_return_t; +#endif + +#import "SentryDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Sentry SDK error codes. + */ +typedef NS_ENUM(NSInteger, SentryError) { + /// Unknown or unclassified error. + kSentryErrorUnknownError = -1, + /// Invalid or malformed DSN string. + kSentryErrorInvalidDsnError = 100, + /// SentryCrash crash handler not installed. + kSentryErrorSentryCrashNotInstalledError = 101, + /// Crash report data is invalid or corrupted. + kSentryErrorInvalidCrashReportError = 102, + /// Failed to compress data for transmission. + kSentryErrorCompressionError = 103, + /// JSON serialization/deserialization failed. + kSentryErrorJsonConversionError = 104, + /// Required directory not found. + kSentryErrorCouldNotFindDirectory = 105, + /// Network request failed. + kSentryErrorRequestError = 106, + /// Event could not be sent to Sentry. + kSentryErrorEventNotSent = 107, + /// File I/O operation failed. + kSentryErrorFileIO = 108, + /// Kernel-level error occurred. + kSentryErrorKernel = 109, +}; + +/** + * Creates an @c NSError from a Sentry error code. + * + * @param error The error code. + * @param description Error description. + * @return An @c NSError instance with domain @c SentryErrorDomain. + */ +SENTRY_OBJC_EXTERN NSError *_Nullable NSErrorFromSentryError( + SentryError error, NSString *description); + +/** + * Creates an @c NSError with an underlying error. + * + * @param error The error code. + * @param description Error description. + * @param underlyingError The underlying cause of this error. + * @return An @c NSError instance with the underlying error in @c userInfo. + */ +SENTRY_OBJC_EXTERN NSError *_Nullable NSErrorFromSentryErrorWithUnderlyingError( + SentryError error, NSString *description, NSError *underlyingError); + +/** + * Creates an @c NSError from an exception. + * + * @param error The error code. + * @param description Error description. + * @param exception The exception that caused this error. + * @return An @c NSError instance with the exception in @c userInfo. + */ +SENTRY_OBJC_EXTERN NSError *_Nullable NSErrorFromSentryErrorWithException( + SentryError error, NSString *description, NSException *exception); + +/** + * Creates an @c NSError from a kernel error code. + * + * @param error The error code. + * @param description Error description. + * @param kernelErrorCode The Mach kernel error code. + * @return An @c NSError instance with the kernel error in @c userInfo. + */ +SENTRY_OBJC_EXTERN NSError *_Nullable NSErrorFromSentryErrorWithKernelError( + SentryError error, NSString *description, kern_return_t kernelErrorCode); + +/// The error domain for Sentry SDK errors. +SENTRY_OBJC_EXTERN NSString *const SentryErrorDomain; + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryEvent.h b/Sources/SentryObjC/Public/SentryEvent.h new file mode 100644 index 00000000000..d2d51f80c8a --- /dev/null +++ b/Sources/SentryObjC/Public/SentryEvent.h @@ -0,0 +1,235 @@ +#import + +#import "SentryDefines.h" +#import "SentryLevel.h" +#import "SentrySerializable.h" + +@class SentryBreadcrumb; +@class SentryDebugMeta; +@class SentryException; +@class SentryId; +@class SentryMessage; +@class SentryRequest; +@class SentryStacktrace; +@class SentryThread; +@class SentryUser; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Event payload sent to Sentry. + * + * Represents an error, exception, or message that will be sent to Sentry. + * Events can be enriched with context from the scope before being sent. + * + * @see SentrySDK + * @see SentryClient + */ +@interface SentryEvent : NSObject + +/** + * Unique identifier for this event. + * + * Automatically generated when the event is created. + */ +@property (nonatomic, strong) SentryId *eventId; + +/** + * Message associated with this event. + * + * Used for message events to provide a formatted message. + */ +@property (nonatomic, strong, nullable) SentryMessage *message; + +/** + * The @c NSError associated with this event. + * + * This property provides convenience access to the error in @c beforeSend. + * It is not directly serialized; errors are converted to exceptions. + */ +@property (nonatomic, copy, nullable) NSError *error; + +/** + * Timestamp when the event occurred. + * + * If not set, defaults to the current time when the event is captured. + */ +@property (nonatomic, strong, nullable) NSDate *timestamp; + +/** + * Timestamp when the event started. + * + * Primarily used for transaction events to indicate when the transaction began. + */ +@property (nonatomic, strong, nullable) NSDate *startTimestamp; + +/** + * Severity level of the event. + * + * Defaults to @c kSentryLevelError. + */ +@property (nonatomic) SentryLevel level; + +/** + * Platform identifier for symbolication. + * + * Always set to "cocoa" for iOS/macOS events. + */ +@property (nonatomic, copy) NSString *platform; + +/** + * Name of the logger that captured this event. + */ +@property (nonatomic, copy, nullable) NSString *logger; + +/** + * Server or device name where the event occurred. + */ +@property (nonatomic, copy, nullable) NSString *serverName; + +/** + * Release version identifier. + * + * @note Filled automatically before the event is sent. + * @warning Usually managed automatically; manual changes not recommended. + */ +@property (nonatomic, copy, nullable) NSString *releaseName; + +/** + * Distribution identifier for this release. + * + * @note Filled automatically before the event is sent. + * @warning Usually managed automatically; manual changes not recommended. + */ +@property (nonatomic, copy, nullable) NSString *dist; + +/** + * Environment name where the event occurred. + */ +@property (nonatomic, copy, nullable) NSString *environment; + +/** + * Name of the transaction associated with this event. + */ +@property (nonatomic, copy, nullable) NSString *transaction; + +/** + * Type of event. + * + * Can be "default", "transaction", or @c nil. + */ +@property (nonatomic, copy, nullable) NSString *type; + +/** + * Key-value tags for categorizing and filtering events. + * + * Tags are searchable in the Sentry UI. + */ +@property (nonatomic, strong, nullable) NSDictionary *tags; + +/** + * Arbitrary extra data associated with the event. + * + * This data is displayed in the Sentry UI but is not indexed for search. + */ +@property (nonatomic, strong, nullable) NSDictionary *extra; + +/** + * SDK metadata. + * + * @warning Usually managed automatically; manual changes not recommended. + */ +@property (nonatomic, strong, nullable) NSDictionary *sdk; + +/** + * List of loaded modules (frameworks/libraries) and their versions. + */ +@property (nonatomic, strong, nullable) NSDictionary *modules; + +/** + * Fingerprint for grouping events. + * + * Events with the same fingerprint are grouped into the same issue. + * If not set, Sentry uses default grouping algorithms. + */ +@property (nonatomic, strong, nullable) NSArray *fingerprint; + +/** + * User information associated with this event. + */ +@property (nonatomic, strong, nullable) SentryUser *user; + +/** + * Additional context data organized by category. + * + * Common categories include "device", "os", "app", "browser", etc. + */ +@property (nonatomic, strong, nullable) + NSDictionary *> *context; + +/** + * List of threads running when the event occurred. + * + * Typically populated for crash events. + */ +@property (nonatomic, strong, nullable) NSArray *threads; + +/** + * List of exceptions associated with this event. + * + * Can contain multiple exceptions for chained or nested errors. + */ +@property (nonatomic, strong, nullable) NSArray *exceptions; + +/** + * Stack trace for this event. + * + * Used when the event represents a single error or exception. + */ +@property (nonatomic, strong, nullable) SentryStacktrace *stacktrace; + +/** + * Debug metadata for symbolication. + * + * Contains information about debug images (binaries) loaded at crash time. + */ +@property (nonatomic, strong, nullable) NSArray *debugMeta; + +/** + * Breadcrumbs that provide context leading up to the event. + * + * Breadcrumbs are a trail of events that occurred before this event. + */ +@property (nonatomic, strong, nullable) NSArray *breadcrumbs; + +/** + * HTTP request information associated with this event. + */ +@property (nonatomic, strong, nullable) SentryRequest *request; + +/** + * Creates a new event with default values. + * + * @return A new event instance. + */ +- (instancetype)init; + +/** + * Creates a new event with the specified severity level. + * + * @param level The severity level for this event. + * @return A new event instance. + */ +- (instancetype)initWithLevel:(SentryLevel)level; + +/** + * Creates a new event from an @c NSError. + * + * @param error The error to create an event from. + * @return A new event instance. + */ +- (instancetype)initWithError:(NSError *)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryException.h b/Sources/SentryObjC/Public/SentryException.h new file mode 100644 index 00000000000..9d9045f8933 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryException.h @@ -0,0 +1,64 @@ +#import + +#import "SentryDefines.h" +#import "SentrySerializable.h" + +@class SentryMechanism; +@class SentryStacktrace; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Exception information for an event. + * + * Represents an exception or error that occurred. Events can contain multiple + * exceptions for chained or nested errors. + * + * @see SentryEvent + */ +@interface SentryException : NSObject + +SENTRY_NO_INIT + +/** + * The exception value (e.g., error message or description). + */ +@property (nonatomic, copy) NSString *value; + +/** + * The exception type (e.g., "NSInvalidArgumentException", "NullPointerException"). + */ +@property (nonatomic, copy) NSString *type; + +/** + * Mechanism describing how the exception was captured. + */ +@property (nonatomic, strong) SentryMechanism *mechanism; + +/** + * Module or package where the exception originated. + */ +@property (nonatomic, copy) NSString *module; + +/** + * ID of the thread where the exception occurred. + */ +@property (nonatomic, copy) NSNumber *threadId; + +/** + * Stack trace associated with this exception. + */ +@property (nonatomic, strong) SentryStacktrace *stacktrace; + +/** + * Creates an exception with the specified value and type. + * + * @param value The exception message or description. + * @param type The exception type name. + * @return A new exception instance. + */ +- (instancetype)initWithValue:(NSString *)value type:(NSString *)type; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryFeedback.h b/Sources/SentryObjC/Public/SentryFeedback.h new file mode 100644 index 00000000000..b164813c8a9 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryFeedback.h @@ -0,0 +1,26 @@ +#import + +#import "SentryFeedbackSource.h" + +@class SentryAttachment; +@class SentryId; + +NS_ASSUME_NONNULL_BEGIN + +/** + * User feedback submission. + */ +@interface SentryFeedback : NSObject + +@property (nonatomic, readonly, strong) SentryId *eventId; + +- (instancetype)initWithMessage:(NSString *)message + name:(nullable NSString *)name + email:(nullable NSString *)email + source:(SentryFeedbackSource)source + associatedEventId:(nullable SentryId *)associatedEventId + attachments:(nullable NSArray *)attachments; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryFeedbackSource.h b/Sources/SentryObjC/Public/SentryFeedbackSource.h new file mode 100644 index 00000000000..92429ab8aa3 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryFeedbackSource.h @@ -0,0 +1,9 @@ +#import + +/** + * Source of a user feedback submission. + */ +typedef NS_ENUM(NSInteger, SentryFeedbackSource) { + SentryFeedbackSourceWidget = 0, + SentryFeedbackSourceCustom +}; diff --git a/Sources/SentryObjC/Public/SentryFrame.h b/Sources/SentryObjC/Public/SentryFrame.h new file mode 100644 index 00000000000..9f38ccf1298 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryFrame.h @@ -0,0 +1,108 @@ +#import + +#import "SentrySerializable.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * A single frame in a stack trace. + * + * Represents one function call in a call stack, including location information, + * source code context, and debugging metadata. + * + * @see SentryStacktrace + */ +@interface SentryFrame : NSObject + +/** + * Address of the symbol for this frame. + */ +@property (nonatomic, copy) NSString *symbolAddress; + +/** + * Source file name where this frame's code is located. + */ +@property (nonatomic, copy) NSString *fileName; + +/** + * Function or method name for this frame. + */ +@property (nonatomic, copy) NSString *function; + +/** + * Module (framework or library) containing this frame's code. + */ +@property (nonatomic, copy) NSString *module; + +/** + * Package or bundle identifier. + */ +@property (nonatomic, copy) NSString *package; + +/** + * Base address of the image (binary) containing this frame. + */ +@property (nonatomic, copy) NSString *imageAddress; + +/** + * Platform identifier for this frame. + */ +@property (nonatomic, copy) NSString *platform; + +/** + * Memory address of the instruction for this frame. + */ +@property (nonatomic, copy) NSString *instructionAddress; + +/** + * Line number in the source file. + */ +@property (nonatomic, copy) NSNumber *lineNumber; + +/** + * Column number in the source line. + */ +@property (nonatomic, copy) NSNumber *columnNumber; + +/** + * Source code line at this frame's location. + */ +@property (nonatomic, copy) NSString *contextLine; + +/** + * Source code lines before the current line (for context). + */ +@property (nonatomic, copy) NSArray *preContext; + +/** + * Source code lines after the current line (for context). + */ +@property (nonatomic, copy) NSArray *postContext; + +/** + * Whether this frame is from application code. + * + * @c YES for app code, @c NO for framework/system code. + */ +@property (nonatomic, copy) NSNumber *inApp; + +/** + * Whether this frame marks the start of the stack. + */ +@property (nonatomic, copy) NSNumber *stackStart; + +/** + * Local variables visible at this frame. + */ +@property (nonatomic, copy) NSDictionary *vars; + +/** + * Creates a new frame with default values. + * + * @return A new frame instance. + */ +- (instancetype)init; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryGeo.h b/Sources/SentryObjC/Public/SentryGeo.h new file mode 100644 index 00000000000..16b0b4b3aaf --- /dev/null +++ b/Sources/SentryObjC/Public/SentryGeo.h @@ -0,0 +1,61 @@ +#import + +#import "SentrySerializable.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Approximate geographical location of the end user or device. + * + * Used to add geographical context to events and users. Location data is + * typically derived from IP addresses or GPS when available. + * + * @see SentryUser + */ +@interface SentryGeo : NSObject + +/** + * Human-readable city name. + */ +@property (nullable, atomic, copy) NSString *city; + +/** + * Two-letter country code (ISO 3166-1 alpha-2). + * + * Examples: "US", "GB", "DE". + */ +@property (nullable, atomic, copy) NSString *countryCode; + +/** + * Human-readable region name or code. + * + * May be a state, province, or administrative region. + */ +@property (nullable, atomic, copy) NSString *region; + +/** + * Compares this geographical location with another object for equality. + * + * @param other The object to compare with. + * @return @c YES if the objects are equal, @c NO otherwise. + */ +- (BOOL)isEqual:(nullable id)other; + +/** + * Compares this geographical location with another location for equality. + * + * @param geo The geographical location to compare with. + * @return @c YES if the locations are equal, @c NO otherwise. + */ +- (BOOL)isEqualToGeo:(SentryGeo *)geo; + +/** + * Returns a hash value for this geographical location. + * + * @return The hash value. + */ +- (NSUInteger)hash; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryHttpStatusCodeRange.h b/Sources/SentryObjC/Public/SentryHttpStatusCodeRange.h new file mode 100644 index 00000000000..6a7fac95ff1 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryHttpStatusCodeRange.h @@ -0,0 +1,27 @@ +#import + +#import "SentryDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * An HTTP status code range. + * + * @see SentryOptions + */ +@interface SentryHttpStatusCodeRange : NSObject + +SENTRY_NO_INIT + +@property (nonatomic, readonly) NSInteger min; +@property (nonatomic, readonly) NSInteger max; + +/** Creates a range with min and max (inclusive). */ +- (instancetype)initWithMin:(NSInteger)min max:(NSInteger)max; + +/** Creates a range for a single status code. */ +- (instancetype)initWithStatusCode:(NSInteger)statusCode; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryId.h b/Sources/SentryObjC/Public/SentryId.h new file mode 100644 index 00000000000..ea3d6eb9447 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryId.h @@ -0,0 +1,38 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A 32-character hexadecimal identifier used for events, traces, and spans. + * + * @see SentryEvent + * @see SentrySpanContext + */ +@interface SentryId : NSObject + +/** A SentryId with an empty UUID "00000000000000000000000000000000". */ +@property (nonatomic, class, readonly, strong) SentryId *empty; + +/** Returns a 32 lowercase character hexadecimal string, e.g. "12c2d058d58442709aa2eca08bf20986". */ +@property (nonatomic, readonly, copy) NSString *sentryIdString; + +/** Creates a SentryId with a random UUID. */ +- (instancetype)init; + +/** Creates a SentryId with the given UUID. */ +- (instancetype)initWithUuid:(NSUUID *)uuid; + +/** + * Creates a SentryId from a 32- or 36-character hexadecimal string. + * + * @param uuidString A string like "12c2d058d58442709aa2eca08bf20986" or + * "12c2d058-d584-4270-9aa2-eca08bf20986". + * @return SentryId.empty for invalid strings. + */ +- (instancetype)initWithUUIDString:(NSString *)uuidString; + +- (BOOL)isEqual:(nullable id)object; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryLevel.h b/Sources/SentryObjC/Public/SentryLevel.h new file mode 100644 index 00000000000..9579a76a2b0 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryLevel.h @@ -0,0 +1,20 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Severity level of an event or breadcrumb. + * + * @see SentryEvent + * @see SentryBreadcrumb + */ +typedef NS_ENUM(NSUInteger, SentryLevel) { + kSentryLevelNone = 0, + kSentryLevelDebug = 1, + kSentryLevelInfo = 2, + kSentryLevelWarning = 3, + kSentryLevelError = 4, + kSentryLevelFatal = 5 +}; + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryLog.h b/Sources/SentryObjC/Public/SentryLog.h new file mode 100644 index 00000000000..0f2c7eb1e96 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryLog.h @@ -0,0 +1,32 @@ +#import + +#import "SentryLogLevel.h" + +@class SentryAttribute; +@class SentryId; +@class SentrySpanId; + +NS_ASSUME_NONNULL_BEGIN + +/** + * A structured log entry. + */ +@interface SentryLog : NSObject + +@property (nonatomic, strong) NSDate *timestamp; +@property (nonatomic, strong) SentryId *traceId; +@property (nonatomic, strong, nullable) SentrySpanId *spanId; +@property (nonatomic, assign) SentryLogLevel level; +@property (nonatomic, copy) NSString *body; +@property (nonatomic, copy) NSDictionary *attributes; +@property (nonatomic, strong, nullable) NSNumber *severityNumber; + +- (instancetype)initWithLevel:(SentryLogLevel)level body:(NSString *)body; +- (instancetype)initWithLevel:(SentryLogLevel)level + body:(NSString *)body + attributes:(NSDictionary *)attributes; +- (void)setAttribute:(nullable SentryAttribute *)attribute forKey:(NSString *)key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryLogLevel.h b/Sources/SentryObjC/Public/SentryLogLevel.h new file mode 100644 index 00000000000..6309fabbfec --- /dev/null +++ b/Sources/SentryObjC/Public/SentryLogLevel.h @@ -0,0 +1,13 @@ +#import + +/** + * Severity levels for structured logging. + */ +typedef NS_ENUM(NSInteger, SentryLogLevel) { + SentryLogLevelTrace = 0, + SentryLogLevelDebug, + SentryLogLevelInfo, + SentryLogLevelWarn, + SentryLogLevelError, + SentryLogLevelFatal +}; diff --git a/Sources/SentryObjC/Public/SentryLogger.h b/Sources/SentryObjC/Public/SentryLogger.h new file mode 100644 index 00000000000..2efba8cd554 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryLogger.h @@ -0,0 +1,109 @@ +#import + +#import "SentryDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Structured logging interface that captures log entries and sends them to Sentry. + * + * Provides severity-based logging methods. Logs are captured as breadcrumbs + * or events depending on severity level and SDK configuration. + * + * @see SentrySDK + */ +@interface SentryLogger : NSObject + +/** + * Logs a trace-level message. + * + * @param body The log message. + */ +- (void)trace:(NSString *)body; + +/** + * Logs a trace-level message with structured attributes. + * + * @param body The log message. + * @param attributes Additional structured data. + */ +- (void)trace:(NSString *)body attributes:(NSDictionary *)attributes; + +/** + * Logs a debug-level message. + * + * @param body The log message. + */ +- (void)debug:(NSString *)body; + +/** + * Logs a debug-level message with structured attributes. + * + * @param body The log message. + * @param attributes Additional structured data. + */ +- (void)debug:(NSString *)body attributes:(NSDictionary *)attributes; + +/** + * Logs an info-level message. + * + * @param body The log message. + */ +- (void)info:(NSString *)body; + +/** + * Logs an info-level message with structured attributes. + * + * @param body The log message. + * @param attributes Additional structured data. + */ +- (void)info:(NSString *)body attributes:(NSDictionary *)attributes; + +/** + * Logs a warning-level message. + * + * @param body The log message. + */ +- (void)warn:(NSString *)body; + +/** + * Logs a warning-level message with structured attributes. + * + * @param body The log message. + * @param attributes Additional structured data. + */ +- (void)warn:(NSString *)body attributes:(NSDictionary *)attributes; + +/** + * Logs an error-level message. + * + * @param body The log message. + */ +- (void)error:(NSString *)body; + +/** + * Logs an error-level message with structured attributes. + * + * @param body The log message. + * @param attributes Additional structured data. + */ +- (void)error:(NSString *)body attributes:(NSDictionary *)attributes; + +/** + * Logs a fatal-level message. + * + * @param body The log message. + */ +- (void)fatal:(NSString *)body; + +/** + * Logs a fatal-level message with structured attributes. + * + * @param body The log message. + * @param attributes Additional structured data. + */ +- (void)fatal:(NSString *)body attributes:(NSDictionary *)attributes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryMeasurementUnit.h b/Sources/SentryObjC/Public/SentryMeasurementUnit.h new file mode 100644 index 00000000000..78ef08fdbfe --- /dev/null +++ b/Sources/SentryObjC/Public/SentryMeasurementUnit.h @@ -0,0 +1,75 @@ +#import + +#import "SentryDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * The unit of measurement of a metric value. + * + * @see SentrySpan + */ +@interface SentryMeasurementUnit : NSObject + +SENTRY_NO_INIT + +/** Returns a custom measurement unit. */ +- (instancetype)initWithUnit:(NSString *)unit; + +/** The string representation of the measurement unit. */ +@property (readonly, copy) NSString *unit; + +/** Untyped value without a unit. */ +@property (class, readonly, copy) SentryMeasurementUnit *none; + +@end + +/** Time duration units. */ +@interface SentryMeasurementUnitDuration : SentryMeasurementUnit + +SENTRY_NO_INIT + +@property (class, readonly, copy) SentryMeasurementUnitDuration *nanosecond; +@property (class, readonly, copy) SentryMeasurementUnitDuration *microsecond; +@property (class, readonly, copy) SentryMeasurementUnitDuration *millisecond; +@property (class, readonly, copy) SentryMeasurementUnitDuration *second; +@property (class, readonly, copy) SentryMeasurementUnitDuration *minute; +@property (class, readonly, copy) SentryMeasurementUnitDuration *hour; +@property (class, readonly, copy) SentryMeasurementUnitDuration *day; +@property (class, readonly, copy) SentryMeasurementUnitDuration *week; + +@end + +/** Size of information units derived from bytes. */ +@interface SentryMeasurementUnitInformation : SentryMeasurementUnit + +SENTRY_NO_INIT + +@property (class, readonly, copy) SentryMeasurementUnitInformation *bit; +@property (class, readonly, copy) SentryMeasurementUnitInformation *byte; +@property (class, readonly, copy) SentryMeasurementUnitInformation *kilobyte; +@property (class, readonly, copy) SentryMeasurementUnitInformation *kibibyte; +@property (class, readonly, copy) SentryMeasurementUnitInformation *megabyte; +@property (class, readonly, copy) SentryMeasurementUnitInformation *mebibyte; +@property (class, readonly, copy) SentryMeasurementUnitInformation *gigabyte; +@property (class, readonly, copy) SentryMeasurementUnitInformation *gibibyte; +@property (class, readonly, copy) SentryMeasurementUnitInformation *terabyte; +@property (class, readonly, copy) SentryMeasurementUnitInformation *tebibyte; +@property (class, readonly, copy) SentryMeasurementUnitInformation *petabyte; +@property (class, readonly, copy) SentryMeasurementUnitInformation *pebibyte; +@property (class, readonly, copy) SentryMeasurementUnitInformation *exabyte; +@property (class, readonly, copy) SentryMeasurementUnitInformation *exbibyte; + +@end + +/** Units of fraction. */ +@interface SentryMeasurementUnitFraction : SentryMeasurementUnit + +SENTRY_NO_INIT + +@property (class, readonly, copy) SentryMeasurementUnitFraction *ratio; +@property (class, readonly, copy) SentryMeasurementUnitFraction *percent; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryMechanism.h b/Sources/SentryObjC/Public/SentryMechanism.h new file mode 100644 index 00000000000..ab9b6b840d9 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryMechanism.h @@ -0,0 +1,75 @@ +#import + +#import "SentryDefines.h" +#import "SentrySerializable.h" + +@class SentryMechanismContext; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Error mechanism describing how the error was produced. + * + * Provides context about how an exception was captured, including whether it was + * handled, what system generated it, and any relevant debugging information. + * + * @see SentryException + */ +@interface SentryMechanism : NSObject + +SENTRY_NO_INIT + +/** + * Mechanism type identifier. + * + * Examples: "generic", "onerror", "promise", "signal". + */ +@property (nonatomic, copy) NSString *type; + +/** + * Human-readable description of the mechanism. + */ +@property (nonatomic, copy, nullable) NSString *desc; + +/** + * Arbitrary data attached to the mechanism. + * + * May contain signal numbers, error codes, or other mechanism-specific data. + */ +@property (nonatomic, strong, nullable) NSDictionary *data; + +/** + * Whether the exception was handled by application code. + * + * @c YES if caught and handled, @c NO if unhandled/fatal. + */ +@property (nonatomic, copy, nullable) NSNumber *handled; + +/** + * Whether the exception was generated synthetically. + * + * @c YES for exceptions created by instrumentation rather than thrown naturally. + */ +@property (nonatomic, copy, nullable) NSNumber *synthetic; + +/** + * URL to documentation about this mechanism. + */ +@property (nonatomic, copy, nullable) NSString *helpLink; + +/** + * Additional metadata about the mechanism. + */ +@property (nullable, nonatomic, strong) SentryMechanismContext *meta; + +/** + * Creates a mechanism with the specified type. + * + * @param type The mechanism type identifier. + * @return A new mechanism instance. + */ +- (instancetype)initWithType:(NSString *)type; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryMechanismContext.h b/Sources/SentryObjC/Public/SentryMechanismContext.h new file mode 100644 index 00000000000..cf241b8810b --- /dev/null +++ b/Sources/SentryObjC/Public/SentryMechanismContext.h @@ -0,0 +1,37 @@ +#import + +#import "SentrySerializable.h" + +@class SentryNSError; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Mechanism metadata with error codes from the runtime or OS. + * + * Provides low-level error details from signals, Mach exceptions, and NSError instances + * that caused an exception. Used for crash report metadata. + * + * @see https://develop.sentry.dev/sdk/event-payloads/exception/#meta-information + */ +@interface SentryMechanismContext : NSObject + +/** + * Creates a new mechanism context. + * + * @return A new instance. + */ +- (instancetype)init; + +/// Signal metadata (signal number, code, address, etc.). +@property (nullable, nonatomic, strong) NSDictionary *signal; + +/// Mach exception metadata (exception type, codes, etc.). +@property (nullable, nonatomic, strong) NSDictionary *machException; + +/// Structured @c NSError information. +@property (nullable, nonatomic, strong) SentryNSError *error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryMessage.h b/Sources/SentryObjC/Public/SentryMessage.h new file mode 100644 index 00000000000..ae376d8399d --- /dev/null +++ b/Sources/SentryObjC/Public/SentryMessage.h @@ -0,0 +1,52 @@ +#import + +#import "SentryDefines.h" +#import "SentrySerializable.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Log message describing an event or error. + * + * Contains a formatted message string that is displayed in Sentry, along with + * an optional unformatted message template and parameters for structured logging. + * + * @see https://develop.sentry.dev/sdk/event-payloads/message/ + */ +@interface SentryMessage : NSObject + +SENTRY_NO_INIT + +/** + * Creates a message with a formatted string. + * + * @param formatted The formatted message string to display. + * @return A new message instance. + */ +- (instancetype)initWithFormatted:(NSString *)formatted; + +/** + * The fully formatted message string. + * + * This is what appears in the Sentry UI. + */ +@property (nonatomic, readonly, copy) NSString *formatted; + +/** + * The unformatted message template. + * + * Used for grouping similar messages with different parameter values. + * Example: "User {user} performed action {action}". + */ +@property (nonatomic, copy) NSString *message; + +/** + * Parameters to substitute into the message template. + * + * Corresponds to placeholders in the @c message template. + */ +@property (nonatomic, strong) NSArray *params; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryMetric.h b/Sources/SentryObjC/Public/SentryMetric.h new file mode 100644 index 00000000000..11b3b239b66 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryMetric.h @@ -0,0 +1,46 @@ +#import + +#import "SentryDefines.h" + +@class SentryId; +@class SentrySpanId; +@class SentryMetricValue; +@class SentryAttributeContent; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Custom metric for application performance monitoring. + * + * Represents a single metric data point with optional trace correlation and attributes. + * Used for tracking custom performance indicators beyond automatic instrumentation. + * + * @see SentryMetricValue + * @see SentryAttributeContent + */ +@interface SentryMetric : NSObject + +/// Timestamp when the metric was recorded. +@property (nonatomic, readonly) NSDate *timestamp; + +/// Metric name (e.g., "response_time", "cache_hit_rate"). +@property (nonatomic, readonly) NSString *name; + +/// Trace ID for correlating this metric with a distributed trace. +@property (nonatomic, readonly) SentryId *traceId; + +/// Optional span ID for correlating this metric with a specific span. +@property (nonatomic, readonly, nullable) SentrySpanId *spanId; + +/// The metric value (counter, gauge, distribution, or set). +@property (nonatomic, readonly) SentryMetricValue *value; + +/// Unit of measurement (e.g., "milliseconds", "bytes", "percent"). +@property (nonatomic, readonly, nullable) NSString *unit; + +/// Additional structured attributes for filtering and grouping. +@property (nonatomic, readonly) NSDictionary *attributes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryMetricValue.h b/Sources/SentryObjC/Public/SentryMetricValue.h new file mode 100644 index 00000000000..85813732a96 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryMetricValue.h @@ -0,0 +1,66 @@ +#import + +#import "SentryDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Type of metric value. + */ +typedef NS_ENUM(NSInteger, SentryMetricValueType) { + /// Monotonically increasing counter (e.g., total requests). + SentryMetricValueTypeCounter, + /// Single value snapshot (e.g., current memory usage). + SentryMetricValueTypeGauge, + /// Statistical distribution of values (e.g., response time percentiles). + SentryMetricValueTypeDistribution +}; + +/** + * Typed metric value: counter, gauge, or distribution. + * + * Use the factory methods to create instances of the appropriate type. + * + * @see SentryMetric + */ +@interface SentryMetricValue : NSObject + +/// The type of metric value stored. +@property (nonatomic, readonly) SentryMetricValueType type; + +/// Counter value, if @c type is @c SentryMetricValueTypeCounter. +@property (nonatomic, readonly) unsigned long long counterValue; + +/// Gauge value, if @c type is @c SentryMetricValueTypeGauge. +@property (nonatomic, readonly) double gaugeValue; + +/// Distribution value, if @c type is @c SentryMetricValueTypeDistribution. +@property (nonatomic, readonly) double distributionValue; + +/** + * Creates a counter metric value. + * + * @param value The counter value (must increase monotonically). + * @return A new metric value instance. + */ ++ (instancetype)counterWithValue:(unsigned long long)value; + +/** + * Creates a gauge metric value. + * + * @param value The gauge value (snapshot). + * @return A new metric value instance. + */ ++ (instancetype)gaugeWithValue:(double)value; + +/** + * Creates a distribution metric value. + * + * @param value A sample value for the distribution. + * @return A new metric value instance. + */ ++ (instancetype)distributionWithValue:(double)value; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryMetricsApi.h b/Sources/SentryObjC/Public/SentryMetricsApi.h new file mode 100644 index 00000000000..3a5fb727783 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryMetricsApi.h @@ -0,0 +1,112 @@ +#import + +#import "SentryDefines.h" + +@class SentryAttributeContent; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Protocol for recording metrics (counters, distributions, and gauges) in Sentry. + * + * This protocol provides an API for recording telemetry metrics that can be used + * for monitoring application performance, tracking business metrics, and analyzing system behavior. + * + * Access via @c [SentrySDK metrics]. + * + * @see SentryAttributeContent + * @see SentryUnit.h for predefined unit constants + */ +@protocol SentryMetricsApi + +/** + * Records a count metric for the specified key. + * + * Use this to increment or set a discrete occurrence count associated with a metric key, + * such as the number of events, requests, or errors. + * + * @param key A namespaced identifier for the metric (e.g., @c "network.request.count"). + * Prefer stable, lowercase, dot-delimited names to aid aggregation and filtering. + * @param value The count value to record. A non-negative integer (e.g., 1 to increment by one). + * @param attributes Optional dictionary of attributes to attach to the metric. + * Keys are strings, values are @c SentryAttributeContent instances. + * Pass @c nil or empty dictionary if no attributes are needed. + * + * @code + * [[SentrySDK metrics] countWithKey:@"button.click" + * value:1 + * attributes:@{ + * @"screen": [SentryAttributeContent stringWithValue:@"home"] + * }]; + * @endcode + */ +- (void)countWithKey:(NSString *)key + value:(NSUInteger)value + attributes:(nullable NSDictionary *)attributes; + +/** + * Records a distribution metric for the specified key. + * + * Use this to track the distribution of a value over time, such as response times, + * request durations, or any measurable quantity where you want to analyze statistical + * properties (mean, median, percentiles, etc.). + * + * @param key A namespaced identifier for the metric (e.g., @c "http.request.duration"). + * Prefer stable, lowercase, dot-delimited names to aid aggregation and filtering. + * @param value The value to record in the distribution. This can be any numeric value + * representing the measurement (e.g., milliseconds for response time). + * @param unit Optional unit of measurement (e.g., @c SentryUnitNameMillisecond). + * Use constants from @c SentryUnit.h or create custom units via @c + * SentryUnitWithName(). Pass @c nil if no unit is needed. + * @param attributes Optional dictionary of attributes to attach to the metric. + * Pass @c nil or empty dictionary if no attributes are needed. + * + * @code + * [[SentrySDK metrics] distributionWithKey:@"response.time" + * value:125.5 + * unit:SentryUnitNameMillisecond + * attributes:@{ + * @"endpoint": [SentryAttributeContent stringWithValue:@"/api/data"] + * }]; + * @endcode + */ +- (void)distributionWithKey:(NSString *)key + value:(double)value + unit:(nullable NSString *)unit + attributes: + (nullable NSDictionary *)attributes; + +/** + * Records a gauge metric for the specified key. + * + * Use this to track a value that can go up and down over time, such as current memory usage, + * queue depth, active connections, or any metric that represents a current state rather + * than an incrementing counter. + * + * @param key A namespaced identifier for the metric (e.g., @c "memory.usage", @c "queue.depth"). + * Prefer stable, lowercase, dot-delimited names to aid aggregation and filtering. + * @param value The current gauge value to record. This represents the state at the time of + * recording (e.g., current memory in bytes, current number of items in queue). + * @param unit Optional unit of measurement (e.g., @c SentryUnitNameByte). + * Use constants from @c SentryUnit.h or create custom units via @c + * SentryUnitWithName(). Pass @c nil if no unit is needed. + * @param attributes Optional dictionary of attributes to attach to the metric. + * Pass @c nil or empty dictionary if no attributes are needed. + * + * @code + * [[SentrySDK metrics] gaugeWithKey:@"queue.depth" + * value:42 + * unit:SentryUnitWithName(@"items") + * attributes:@{ + * @"queue": [SentryAttributeContent stringWithValue:@"upload"] + * }]; + * @endcode + */ +- (void)gaugeWithKey:(NSString *)key + value:(double)value + unit:(nullable NSString *)unit + attributes:(nullable NSDictionary *)attributes; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryNSError.h b/Sources/SentryObjC/Public/SentryNSError.h new file mode 100644 index 00000000000..f32d382868a --- /dev/null +++ b/Sources/SentryObjC/Public/SentryNSError.h @@ -0,0 +1,37 @@ +#import + +#import "SentryDefines.h" +#import "SentrySerializable.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Serializable representation of an @c NSError. + * + * Captures the essential error information (domain and code) for event payloads. + * Used in mechanism metadata to provide structured error details. + * + * @see SentryMechanismContext + */ +@interface SentryNSError : NSObject + +SENTRY_NO_INIT + +/// The error domain (e.g., @c NSCocoaErrorDomain, @c SentryErrorDomain). +@property (nonatomic, copy) NSString *domain; + +/// The error code within the domain. +@property (nonatomic, assign) NSInteger code; + +/** + * Creates an error representation with domain and code. + * + * @param domain The error domain. + * @param code The error code. + * @return A new instance. + */ +- (instancetype)initWithDomain:(NSString *)domain code:(NSInteger)code; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryObjC.h b/Sources/SentryObjC/Public/SentryObjC.h new file mode 100644 index 00000000000..90a4819ac11 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryObjC.h @@ -0,0 +1,65 @@ +#import + +#import "SentryDefines.h" + +// Re-declared ObjC types (standalone headers, no transitive imports from Sentry) +#import "SentryAppStartMeasurement.h" +#import "SentryAttachment.h" +#import "SentryBaggage.h" +#import "SentryBreadcrumb.h" +#import "SentryDebugMeta.h" +#import "SentryError.h" +#import "SentryEvent.h" +#import "SentryException.h" +#import "SentryFrame.h" +#import "SentryGeo.h" +#import "SentryHttpStatusCodeRange.h" +#import "SentryId.h" +#import "SentryLevel.h" +#import "SentryMeasurementUnit.h" +#import "SentryMechanism.h" +#import "SentryMechanismContext.h" +#import "SentryMessage.h" +#import "SentryNSError.h" +#import "SentryReplayApi.h" +#import "SentryRequest.h" +#import "SentrySampleDecision.h" +#import "SentrySamplingContext.h" +#import "SentryScope.h" +#import "SentrySerializable.h" +#import "SentrySpan.h" +#import "SentrySpanContext.h" +#import "SentrySpanId.h" +#import "SentrySpanStatus.h" +#import "SentryStacktrace.h" +#import "SentryThread.h" +#import "SentryTraceContext.h" +#import "SentryTraceHeader.h" +#import "SentryTransactionContext.h" +#import "SentryTransactionNameSource.h" +#import "SentryUser.h" + +// Swift @objc types +#import "SentryAttribute.h" +#import "SentryFeedback.h" +#import "SentryFeedbackSource.h" +#import "SentryLog.h" +#import "SentryLogLevel.h" +#import "SentryLogger.h" +#import "SentryOptions.h" +#import "SentryReplayOptions.h" +#import "SentrySDK.h" + +// Envelope types (SPI for hybrid SDKs) +#import "PrivateSentrySDKOnly.h" +#import "SentryEnvelope.h" +#import "SentryEnvelopeHeader.h" +#import "SentryEnvelopeItem.h" + +// Wrappers for Swift-only types +#import "SentryAttributeContent.h" +#import "SentryMetric.h" +#import "SentryMetricValue.h" +#import "SentryMetricsApi.h" +#import "SentryRedactRegionType.h" +#import "SentryUnit.h" diff --git a/Sources/SentryObjC/Public/SentryOptions.h b/Sources/SentryObjC/Public/SentryOptions.h new file mode 100644 index 00000000000..b79f960b330 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryOptions.h @@ -0,0 +1,524 @@ +#import + +#import "SentryDefines.h" +#import "SentryLevel.h" + +@class SentryReplayOptions; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Configuration options for the Sentry SDK. + * + * Configure all SDK features and behavior through this object before + * passing it to @c +[SentrySDK startWithOptions:]. + * + * @see SentrySDK + */ +@interface SentryOptions : NSObject + +/** + * The DSN (Data Source Name) for your Sentry project. + * + * This uniquely identifies your project and directs events to the correct endpoint. + */ +@property (nonatomic, copy, nullable) NSString *dsn; + +/** + * Parsed representation of the DSN. + * + * @warning This is maintained automatically and should not be set directly. + */ +@property (nonatomic, strong, nullable) id parsedDsn; + +/** + * Whether to enable debug mode. + * + * When @c YES, the SDK will output detailed logs. Defaults to @c NO. + */ +@property (nonatomic, assign) BOOL debug; + +/** + * The minimum level for diagnostic messages to be logged. + * + * Only messages at or above this level will be logged. + */ +@property (nonatomic, assign) SentryLevel diagnosticLevel; + +/** + * The release version of your application. + * + * Format: @c \@\+\ (e.g., "my.app@1.0.0+123"). + * If not set, the SDK will attempt to detect it automatically. + */ +@property (nonatomic, copy, nullable) NSString *releaseName; + +/** + * The distribution identifier for this release. + * + * Used to distinguish different distributions of the same release (e.g., "enterprise", "appstore"). + */ +@property (nonatomic, copy, nullable) NSString *dist; + +/** + * The environment name (e.g., "production", "staging", "development"). + * + * Defaults to "production". + */ +@property (nonatomic, copy) NSString *environment; + +/** + * Whether the SDK is enabled. + * + * When @c NO, the SDK will not send any events. Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enabled; + +/** + * Maximum time to wait for pending events to be sent during shutdown. + * + * Specified in seconds. Defaults to 2 seconds. + */ +@property (nonatomic, assign) NSTimeInterval shutdownTimeInterval; + +/** + * Whether to install the crash handler. + * + * When @c YES, the SDK will capture crashes. Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableCrashHandler; + +/** + * Maximum number of breadcrumbs to keep. + * + * When the limit is exceeded, older breadcrumbs are removed. Defaults to 100. + */ +@property (nonatomic, assign) NSUInteger maxBreadcrumbs; + +/** + * Whether to automatically capture network request breadcrumbs. + * + * Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableNetworkBreadcrumbs; + +/** + * Maximum number of events to cache on disk. + * + * When the limit is exceeded, the oldest events are removed. Defaults to 30. + */ +@property (nonatomic, assign) NSUInteger maxCacheItems; + +/** + * Callback invoked before an event is sent. + * + * Use this to modify or filter events. Return @c nil to prevent sending. + */ +@property (nonatomic, copy, nullable) SentryBeforeSendEventCallback beforeSend; + +/** + * Callback invoked before a span is sent. + * + * Use this to modify or filter spans. Return @c nil to prevent sending. + */ +@property (nonatomic, copy, nullable) SentryBeforeSendSpanCallback beforeSendSpan; + +/** + * Whether to enable automatic log capture. + * + * When @c YES, logs will be captured and sent to Sentry. Defaults to @c NO. + */ +@property (nonatomic, assign) BOOL enableLogs; + +/** + * Callback invoked before a log is sent. + * + * Use this to modify or filter logs. Return @c nil to prevent sending. + */ +@property (nonatomic, copy, nullable) SentryBeforeSendLogCallback beforeSendLog; + +/** + * Callback invoked before a breadcrumb is added. + * + * Use this to modify or filter breadcrumbs. Return @c nil to prevent adding. + */ +@property (nonatomic, copy, nullable) SentryBeforeBreadcrumbCallback beforeBreadcrumb; + +/** + * Callback invoked before a screenshot is captured. + * + * Return @c nil to prevent capturing the screenshot. + */ +@property (nonatomic, copy, nullable) SentryBeforeCaptureScreenshotCallback beforeCaptureScreenshot; + +/** + * Callback invoked before the view hierarchy is captured. + * + * Return @c nil to prevent capturing the view hierarchy. + */ +@property (nonatomic, copy, nullable) + SentryBeforeCaptureScreenshotCallback beforeCaptureViewHierarchy; + +/** + * Callback invoked when the SDK determines the app crashed on the previous run. + * + * Use this to perform custom logic when a crash is detected. + */ +@property (nonatomic, copy, nullable) SentryOnCrashedLastRunCallback onCrashedLastRun; + +/** + * The sample rate for error events. + * + * A value between 0.0 (0%) and 1.0 (100%). Defaults to 1.0 (all events sent). + */ +@property (nonatomic, strong, nullable) NSNumber *sampleRate; + +/** + * Whether to enable automatic session tracking. + * + * When @c YES, sessions are automatically started and stopped. Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableAutoSessionTracking; + +/** + * Whether to enable automatic GraphQL operation tracking. + * + * Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableGraphQLOperationTracking; + +/** + * Whether to track watchdog terminations. + * + * Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableWatchdogTerminationTracking; + +/** + * Interval for session tracking in milliseconds. + * + * Sessions are sent to Sentry at this interval. Defaults to 30000 (30 seconds). + */ +@property (nonatomic, assign) NSUInteger sessionTrackingIntervalMillis; + +/** + * Whether to attach stack traces to captured messages. + * + * Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL attachStacktrace; + +/** + * Maximum size for attachments in bytes. + * + * Attachments larger than this will not be sent. Defaults to 20 MB. + */ +@property (nonatomic, assign) NSUInteger maxAttachmentSize; + +/** + * Whether to send default personally identifiable information (PII). + * + * When @c YES, user IP addresses and usernames are sent. Defaults to @c NO. + */ +@property (nonatomic, assign) BOOL sendDefaultPii; + +/** + * Whether to enable automatic performance tracing. + * + * Defaults to @c YES when @c tracesSampleRate or @c tracesSampler is set. + */ +@property (nonatomic, assign) BOOL enableAutoPerformanceTracing; + +/** + * Whether to persist traces when the application crashes. + * + * This allows traces to be sent with crash reports. Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enablePersistingTracesWhenCrashing; + +/** + * Initial scope data to apply when the SDK starts. + * + * Set this to pre-populate the scope with tags, extras, or other data. + */ +@property (nonatomic, copy, nullable) id initialScope; + +#if SENTRY_OBJC_UIKIT_AVAILABLE +/** + * Whether to enable automatic view controller tracing. + * + * When @c YES, navigation between view controllers is automatically traced. Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableUIViewControllerTracing; + +/** + * Whether to attach screenshots to error events. + * + * Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL attachScreenshot; + +/** + * Configuration for screenshot attachment. + * + * @warning This is maintained automatically. + */ +@property (nonatomic, strong) id screenshot; + +/** + * Whether to attach the view hierarchy to error events. + * + * Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL attachViewHierarchy; + +/** + * Whether to include accessibility identifiers in the view hierarchy. + * + * Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL reportAccessibilityIdentifier; + +/** + * Whether to enable automatic user interaction tracing. + * + * When @c YES, user taps and swipes are automatically traced. Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableUserInteractionTracing; + +/** + * The idle timeout for automatically finishing transactions. + * + * If no child spans are running for this duration, the transaction is automatically finished. + * Specified in seconds. Defaults to 3 seconds. + */ +@property (nonatomic, assign) NSTimeInterval idleTimeout; + +/** + * Whether to trace app start for pre-warmed launches. + * + * Defaults to @c NO. + */ +@property (nonatomic, assign) BOOL enablePreWarmedAppStartTracing; + +/** + * Whether to report app hangs that don't fully block the main thread. + * + * Defaults to @c NO. + */ +@property (nonatomic, assign) BOOL enableReportNonFullyBlockingAppHangs; + +/** + * Configuration options for Session Replay. + */ +@property (nonatomic, strong) SentryReplayOptions *sessionReplay; +#endif + +/** + * Whether to enable automatic network request tracing. + * + * When @c YES, network requests are automatically traced. Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableNetworkTracking; + +/** + * Whether to enable file I/O tracing. + * + * Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableFileIOTracing; + +/** + * Whether to enable method swizzling for automatic instrumentation. + * + * Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableDataSwizzling; + +/** + * Whether to swizzle @c NSFileManager methods for file I/O tracing. + * + * Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableFileManagerSwizzling; + +/** + * The sample rate for performance traces. + * + * A value between 0.0 (0%) and 1.0 (100%). Defaults to @c nil (no tracing). + */ +@property (nonatomic, strong, nullable) NSNumber *tracesSampleRate; + +/** + * Callback for dynamic trace sampling decisions. + * + * If set, this callback is invoked for each transaction to determine + * whether it should be sampled. + */ +@property (nonatomic, copy, nullable) SentryTracesSamplerCallback tracesSampler; + +/** + * Whether performance tracing is enabled. + * + * @c YES if @c tracesSampleRate or @c tracesSampler is set. + */ +@property (nonatomic, readonly) BOOL isTracingEnabled; + +/** + * List of module/package prefixes to consider as in-app code. + * + * Stack frames from these modules are marked as in-app. + */ +@property (nonatomic, copy) NSArray *inAppIncludes; + +/** + * Custom delegate for the SDK's @c NSURLSession. + */ +@property (nonatomic, weak, nullable) id urlSessionDelegate; + +/** + * Custom @c NSURLSession for network communication. + * + * If not set, the SDK creates its own session. + */ +@property (nonatomic, strong, nullable) NSURLSession *urlSession; + +/** + * Whether to enable method swizzling globally. + * + * When @c NO, automatic instrumentation is disabled. Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableSwizzling; + +/** + * Set of class name prefixes to exclude from swizzling. + * + * Classes whose names start with these prefixes will not be swizzled. + */ +@property (nonatomic, copy) NSSet *swizzleClassNameExcludes; + +/** + * Whether to enable Core Data tracing. + * + * Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableCoreDataTracing; + +/** + * Whether to send client reports about dropped events. + * + * Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL sendClientReports; + +/** + * Whether to enable app hang tracking. + * + * When @c YES, the SDK detects when the main thread is blocked. Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableAppHangTracking; + +/** + * Threshold for detecting app hangs. + * + * If the main thread is blocked for longer than this duration, it's reported + * as an app hang. Specified in seconds. Defaults to 2 seconds. + */ +@property (nonatomic, assign) NSTimeInterval appHangTimeoutInterval; + +/** + * Whether to enable automatic breadcrumb tracking. + * + * When @c YES, various system events are automatically captured as breadcrumbs. Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableAutoBreadcrumbTracking; + +/** + * Whether to propagate trace context in HTTP headers. + * + * When @c YES, @c sentry-trace and @c baggage headers are added to outgoing requests. Defaults to + * @c YES. + */ +@property (nonatomic, assign) BOOL enablePropagateTraceparent; + +/** + * List of URL patterns for trace propagation. + * + * Only requests to URLs matching these patterns will have trace headers added. + * If empty, all requests receive headers. + */ +@property (nonatomic, copy) NSArray *tracePropagationTargets; + +/** + * Whether to capture HTTP requests that result in error status codes. + * + * Defaults to @c YES when tracing is enabled. + */ +@property (nonatomic, assign) BOOL enableCaptureFailedRequests; + +/** + * List of HTTP status code ranges to consider as failed requests. + * + * Requests with these status codes are captured as error events. + */ +@property (nonatomic, copy) NSArray *failedRequestStatusCodes; + +/** + * List of URL patterns to capture when they result in failed requests. + * + * Only requests to URLs matching these patterns are captured. + */ +@property (nonatomic, copy) NSArray *failedRequestTargets; + +/** + * Whether to enable Time To Full Display tracking. + * + * Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL enableTimeToFullDisplayTracing; + +/** + * Whether to capture stack traces from Swift async functions. + * + * Defaults to @c YES on iOS 15+. + */ +@property (nonatomic, assign) BOOL swiftAsyncStacktraces; + +/** + * Custom directory path for caching events. + * + * If not set, the SDK uses the default cache directory. + */ +@property (nonatomic, copy) NSString *cacheDirectoryPath; + +/** + * Whether to enable Spotlight integration for local debugging. + * + * Defaults to @c NO. + */ +@property (nonatomic, assign) BOOL enableSpotlight; + +/** + * URL for the Spotlight server. + * + * Defaults to @c "http://localhost:8969/stream". + */ +@property (nonatomic, copy) NSString *spotlightUrl; + +/** + * Experimental features configuration. + * + * Access experimental SDK features through this property. + */ +@property (nonatomic, strong) id experimental; + +/** + * Adds a module/package prefix to the in-app includes list. + * + * @param inAppInclude The module prefix to add. + */ +- (void)addInAppInclude:(NSString *)inAppInclude; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryRedactRegionType.h b/Sources/SentryObjC/Public/SentryRedactRegionType.h new file mode 100644 index 00000000000..799dbbd2fef --- /dev/null +++ b/Sources/SentryObjC/Public/SentryRedactRegionType.h @@ -0,0 +1,18 @@ +#import + +#import "SentryDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Defines how a region should be handled during session replay redaction. + */ +typedef NSString *SentryRedactRegionType NS_STRING_ENUM; + +FOUNDATION_EXPORT SentryRedactRegionType const SentryRedactRegionTypeRedact; +FOUNDATION_EXPORT SentryRedactRegionType const SentryRedactRegionTypeClipOut; +FOUNDATION_EXPORT SentryRedactRegionType const SentryRedactRegionTypeClipBegin; +FOUNDATION_EXPORT SentryRedactRegionType const SentryRedactRegionTypeClipEnd; +FOUNDATION_EXPORT SentryRedactRegionType const SentryRedactRegionTypeRedactSwiftUI; + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryReplayApi.h b/Sources/SentryObjC/Public/SentryReplayApi.h new file mode 100644 index 00000000000..f2dcdbdac51 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryReplayApi.h @@ -0,0 +1,90 @@ +#import + +#import "SentryDefines.h" + +#if SENTRY_OBJC_REPLAY_SUPPORTED +# import +#endif + +NS_ASSUME_NONNULL_BEGIN + +#if SENTRY_OBJC_REPLAY_SUPPORTED + +@class UIView; + +/** + * Session replay API for masking and controlling replay recording. + * + * Use this API to dynamically control which views are masked, and to + * start/stop/pause replay recording at runtime. + */ +@interface SentryReplayApi : NSObject + +/** + * Masks a specific view in the replay. + * + * The view's content will be hidden in replay recordings. + * + * @param view The view to mask. + */ +- (void)maskView:(UIView *)view; + +/** + * Unmasks a specific view in the replay. + * + * The view's content will be visible in replay recordings. + * + * @param view The view to unmask. + */ +- (void)unmaskView:(UIView *)view; + +/** + * Pauses replay recording. + * + * Recording can be resumed with @c -resume. + */ +- (void)pause; + +/** + * Resumes replay recording after it was paused. + */ +- (void)resume; + +/** + * Starts replay recording. + * + * @note Replay is usually started automatically when sampled. + */ +- (void)start; + +/** + * Stops replay recording. + * + * The recorded replay will be uploaded if errors occurred. + */ +- (void)stop; + +/** + * Shows a visual preview of which views are masked. + * + * Useful for debugging privacy settings. Uses default opacity. + */ +- (void)showMaskPreview; + +/** + * Shows a visual preview of which views are masked with custom opacity. + * + * @param opacity Opacity for the mask overlay (0.0 to 1.0). + */ +- (void)showMaskPreview:(CGFloat)opacity; + +/** + * Hides the mask preview overlay. + */ +- (void)hideMaskPreview; + +@end + +#endif // SENTRY_OBJC_REPLAY_SUPPORTED + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryReplayOptions.h b/Sources/SentryObjC/Public/SentryReplayOptions.h new file mode 100644 index 00000000000..7b7ef05cf99 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryReplayOptions.h @@ -0,0 +1,133 @@ +#import + +#import "SentryDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +#if SENTRY_OBJC_REPLAY_SUPPORTED + +/** + * Video quality for session replay recordings. + */ +typedef NS_ENUM(NSInteger, SentryReplayQuality) { + /** Low quality (lower file size, faster upload) */ + SentryReplayQualityLow = 0, + /** Medium quality (balanced size and clarity) */ + SentryReplayQualityMedium = 1, + /** High quality (larger file size, better clarity) */ + SentryReplayQualityHigh = 2 +}; + +/** + * Configuration options for Session Replay. + * + * Configure replay behavior, sampling rates, privacy settings, and quality. + * Session Replay captures a video-like recording of user interactions for + * debugging. + * + * @see SentryOptions + */ +@interface SentryReplayOptions : NSObject + +/** + * Sample rate for replaying sessions. + * + * Value between 0.0 and 1.0. Defaults to 0.0 (disabled). + * Only sampled sessions will record replays. + */ +@property (nonatomic, assign) float sessionSampleRate; + +/** + * Sample rate for replaying sessions with errors. + * + * Value between 0.0 and 1.0. Defaults to 0.0 (disabled). + * Sessions with errors are more likely to need replay for debugging. + */ +@property (nonatomic, assign) float onErrorSampleRate; + +/** + * Whether to mask all text in the replay. + * + * When @c YES, all text is replaced with placeholder blocks. Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL maskAllText; + +/** + * Whether to mask all images in the replay. + * + * When @c YES, all images are replaced with placeholder blocks. Defaults to @c YES. + */ +@property (nonatomic, assign) BOOL maskAllImages; + +/** + * Video quality for replay recordings. + * + * Higher quality produces clearer recordings but larger files. Defaults to medium. + */ +@property (nonatomic, assign) SentryReplayQuality quality; + +/** + * View classes to mask in the replay. + * + * Views of these classes will have their content hidden. + */ +@property (nonatomic, copy) NSArray *maskedViewClasses; + +/** + * View classes to explicitly not mask in the replay. + * + * Overrides @c maskAllText and @c maskAllImages for these view classes. + */ +@property (nonatomic, copy) NSArray *unmaskedViewClasses; + +/** + * View class names to exclude from subtree traversal. + * + * Views with these class names and their children will not be rendered. + */ +@property (nonatomic, copy) NSSet *excludedViewClasses; + +/** + * View class names to include in subtree traversal. + * + * Overrides exclusions for these view classes. + */ +@property (nonatomic, copy) NSSet *includedViewClasses; + +/** + * Whether to enable the V2 view renderer. + * + * @warning Experimental. May change in future versions. + */ +@property (nonatomic, assign) BOOL enableViewRendererV2; + +/** + * Whether to enable fast view rendering optimizations. + * + * @warning Experimental. May change in future versions. + */ +@property (nonatomic, assign) BOOL enableFastViewRendering; + +/** + * Excludes a view type from being rendered in replays. + * + * The view and its entire subtree will not appear in the replay. + * + * @param viewType Fully qualified class name (e.g., "UITextField"). + */ +- (void)excludeViewTypeFromSubtreeTraversal:(NSString *)viewType; + +/** + * Includes a view type in replay rendering. + * + * Overrides previous exclusions for this view type. + * + * @param viewType Fully qualified class name (e.g., "UITextField"). + */ +- (void)includeViewTypeInSubtreeTraversal:(NSString *)viewType; + +@end + +#endif // SENTRY_OBJC_REPLAY_SUPPORTED + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryRequest.h b/Sources/SentryObjC/Public/SentryRequest.h new file mode 100644 index 00000000000..478709836b2 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryRequest.h @@ -0,0 +1,65 @@ +#import + +#import "SentrySerializable.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * HTTP request information for an event. + * + * Captures details about an HTTP request that was being processed when an + * error occurred. Useful for web applications and API servers. + * + * @see SentryEvent + */ +@interface SentryRequest : NSObject + +/** + * Size of the request body in bytes. + */ +@property (nonatomic, copy, nullable) NSNumber *bodySize; + +/** + * Cookies sent with the request. + * + * @note Only included when @c sendDefaultPii is @c YES. + */ +@property (nonatomic, copy, nullable) NSString *cookies; + +/** + * HTTP headers from the request. + * + * @note Sensitive headers are automatically filtered. + */ +@property (nonatomic, strong, nullable) NSDictionary *headers; + +/** + * URL fragment (the part after #). + */ +@property (nonatomic, copy, nullable) NSString *fragment; + +/** + * HTTP method (GET, POST, etc.). + */ +@property (nonatomic, copy, nullable) NSString *method; + +/** + * Query string (the part after ?). + */ +@property (nonatomic, copy, nullable) NSString *queryString; + +/** + * Full request URL. + */ +@property (nonatomic, copy, nullable) NSString *url; + +/** + * Creates a new request instance. + * + * @return A new request instance. + */ +- (instancetype)init; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentrySDK.h b/Sources/SentryObjC/Public/SentrySDK.h new file mode 100644 index 00000000000..947266058ba --- /dev/null +++ b/Sources/SentryObjC/Public/SentrySDK.h @@ -0,0 +1,400 @@ +#import + +#import "SentryDefines.h" + +@class SentryBreadcrumb; +@class SentryEvent; +@class SentryId; +@class SentryOptions; +@class SentryScope; +@class SentryTransactionContext; +@class SentryFeedback; +@class SentryUser; +@protocol SentrySpan; + +#if SENTRY_OBJC_REPLAY_SUPPORTED +@class SentryReplayApi; +#endif + +@class SentryLogger; +@protocol SentryMetricsApi; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Main entry point for the Sentry SDK (Objective-C wrapper). + * + * This is a pure Objective-C wrapper around the Sentry SDK that works in + * projects with CLANG_ENABLE_MODULES=NO. Use this class to initialize the + * SDK, capture events, and manage SDK state. + * + * @see SentryOptions + * @see SentryScope + */ +@interface SentrySDK : NSObject + +SENTRY_NO_INIT + +/** + * Returns the currently active span or transaction. + * + * @return The active span, or @c nil if no span is active. + */ ++ (nullable id)span; + +/** + * Indicates whether the SDK has been properly initialized and is enabled. + * + * @return @c YES if the SDK is enabled, @c NO otherwise. + */ ++ (BOOL)isEnabled; + +#if SENTRY_OBJC_REPLAY_SUPPORTED +/** + * Returns the Session Replay API for controlling replay recording. + * + * @return The replay API instance. + */ ++ (SentryReplayApi *)replay; +#endif + +/** + * Returns the SDK logger instance. + * + * @return The logger instance. + */ ++ (SentryLogger *)logger; + +/** + * Returns the Metrics API for recording custom metrics. + * + * Sentry Metrics allows you to send counters, gauges, and distributions from your applications + * to Sentry. Once in Sentry, these metrics can be viewed alongside related errors, traces, and + * logs. + * + * @return The metrics API instance. + * + * @code + * // Simple counter + * [[SentrySDK metrics] countWithKey:@"button.click"]; + * + * // Distribution with unit and attributes + * [[SentrySDK metrics] distributionWithKey:@"response.time" + * value:125.5 + * unit:SentryUnitNameMillisecond + * attributes:@{ + * @"endpoint": [SentryAttributeContent stringWithValue:@"/api/data"] + * }]; + * @endcode + * + * @see SentryMetricsApi + */ ++ (id)metrics; + +/** + * Initializes the SDK with the provided options. + * + * Call this method once during application startup. + * + * @param options The configuration options for the SDK. + */ ++ (void)startWithOptions:(SentryOptions *)options; + +/** + * Initializes the SDK with a configuration block. + * + * This is a convenience method that creates default options and passes them + * to the configuration block for customization. + * + * @param configureOptions A block that receives the options object for configuration. + */ ++ (void)startWithConfigureOptions:(void (^)(SentryOptions *options))configureOptions; + +/** + * Captures an event and sends it to Sentry. + * + * @param event The event to capture. + * @return The event ID of the captured event. + */ ++ (SentryId *)captureEvent:(SentryEvent *)event; + +/** + * Captures an event with a specific scope and sends it to Sentry. + * + * @param event The event to capture. + * @param scope The scope to use for this event. + * @return The event ID of the captured event. + */ ++ (SentryId *)captureEvent:(SentryEvent *)event withScope:(SentryScope *)scope; + +/** + * Captures an event with a scope modification block. + * + * The block allows you to modify the scope for this specific event capture. + * + * @param event The event to capture. + * @param block A block that receives the scope for modification. + * @return The event ID of the captured event. + */ ++ (SentryId *)captureEvent:(SentryEvent *)event withScopeBlock:(void (^)(SentryScope *scope))block; + +/** + * Starts a new transaction for performance monitoring. + * + * @param name The name of the transaction. + * @param operation The operation type (e.g., "http.server", "db.query"). + * @return The started transaction span. + */ ++ (id)startTransactionWithName:(NSString *)name operation:(NSString *)operation; + +/** + * Starts a new transaction with scope binding control. + * + * @param name The name of the transaction. + * @param operation The operation type. + * @param bindToScope If @c YES, binds the transaction to the current scope. + * @return The started transaction span. + */ ++ (id)startTransactionWithName:(NSString *)name + operation:(NSString *)operation + bindToScope:(BOOL)bindToScope; + +/** + * Starts a new transaction from a transaction context. + * + * @param transactionContext The transaction context containing name, operation, and trace + * information. + * @return The started transaction span. + */ ++ (id)startTransactionWithContext:(SentryTransactionContext *)transactionContext; + +/** + * Starts a new transaction from a transaction context with scope binding control. + * + * @param transactionContext The transaction context. + * @param bindToScope If @c YES, binds the transaction to the current scope. + * @return The started transaction span. + */ ++ (id)startTransactionWithContext:(SentryTransactionContext *)transactionContext + bindToScope:(BOOL)bindToScope; + +/** + * Starts a new transaction with custom sampling context. + * + * @param transactionContext The transaction context. + * @param customSamplingContext Additional data to pass to the traces sampler callback. + * @return The started transaction span. + */ ++ (id)startTransactionWithContext:(SentryTransactionContext *)transactionContext + customSamplingContext:(NSDictionary *)customSamplingContext; + +/** + * Starts a new transaction with full control over binding and sampling. + * + * @param transactionContext The transaction context. + * @param bindToScope If @c YES, binds the transaction to the current scope. + * @param customSamplingContext Additional data to pass to the traces sampler callback. + * @return The started transaction span. + */ ++ (id)startTransactionWithContext:(SentryTransactionContext *)transactionContext + bindToScope:(BOOL)bindToScope + customSamplingContext:(NSDictionary *)customSamplingContext; + +/** + * Captures an @c NSError and sends it to Sentry. + * + * @param error The error to capture. + * @return The event ID of the captured error. + */ ++ (SentryId *)captureError:(NSError *)error; + +/** + * Captures an @c NSError with a specific scope. + * + * @param error The error to capture. + * @param scope The scope to use for this error. + * @return The event ID of the captured error. + */ ++ (SentryId *)captureError:(NSError *)error withScope:(SentryScope *)scope; + +/** + * Captures an @c NSError with a scope modification block. + * + * @param error The error to capture. + * @param block A block that receives the scope for modification. + * @return The event ID of the captured error. + */ ++ (SentryId *)captureError:(NSError *)error withScopeBlock:(void (^)(SentryScope *scope))block; + +/** + * Captures an @c NSException and sends it to Sentry. + * + * @param exception The exception to capture. + * @return The event ID of the captured exception. + */ ++ (SentryId *)captureException:(NSException *)exception; + +/** + * Captures an @c NSException with a specific scope. + * + * @param exception The exception to capture. + * @param scope The scope to use for this exception. + * @return The event ID of the captured exception. + */ ++ (SentryId *)captureException:(NSException *)exception withScope:(SentryScope *)scope; + +/** + * Captures an @c NSException with a scope modification block. + * + * @param exception The exception to capture. + * @param block A block that receives the scope for modification. + * @return The event ID of the captured exception. + */ ++ (SentryId *)captureException:(NSException *)exception + withScopeBlock:(void (^)(SentryScope *scope))block; + +/** + * Captures a message string and sends it to Sentry. + * + * @param message The message to capture. + * @return The event ID of the captured message. + */ ++ (SentryId *)captureMessage:(NSString *)message; + +/** + * Captures a message with a specific scope. + * + * @param message The message to capture. + * @param scope The scope to use for this message. + * @return The event ID of the captured message. + */ ++ (SentryId *)captureMessage:(NSString *)message withScope:(SentryScope *)scope; + +/** + * Captures a message with a scope modification block. + * + * @param message The message to capture. + * @param block A block that receives the scope for modification. + * @return The event ID of the captured message. + */ ++ (SentryId *)captureMessage:(NSString *)message withScopeBlock:(void (^)(SentryScope *scope))block; + +/** + * Captures user feedback and sends it to Sentry. + * + * @param feedback The user feedback to capture. + */ ++ (void)captureFeedback:(SentryFeedback *)feedback; + +/** + * Adds a breadcrumb to the current scope. + * + * Breadcrumbs are sent with subsequent error events to provide context. + * + * @param crumb The breadcrumb to add. + */ ++ (void)addBreadcrumb:(SentryBreadcrumb *)crumb; + +/** + * Modifies the current scope using a callback block. + * + * Use this to add tags, extra data, or other contextual information. + * + * @param callback A block that receives the current scope for modification. + */ ++ (void)configureScope:(void (^)(SentryScope *scope))callback; + +/** + * Indicates whether the application crashed during the last run. + * + * @return @c YES if the app crashed on the previous run, @c NO otherwise. + */ ++ (BOOL)crashedLastRun; + +/** + * Indicates whether a startup crash was detected. + * + * A startup crash is one that occurred shortly after app launch. + * + * @return @c YES if a startup crash was detected, @c NO otherwise. + */ ++ (BOOL)detectedStartUpCrash; + +/** + * Sets the user information for the current scope. + * + * @param user The user information, or @c nil to clear the current user. + */ ++ (void)setUser:(nullable SentryUser *)user; + +/** + * Manually starts a new session. + * + * Sessions are typically started automatically, but this method allows manual control. + */ ++ (void)startSession; + +/** + * Manually ends the current session. + */ ++ (void)endSession; + +/** + * Triggers a crash for testing purposes. + * + * @warning This method will terminate the application. Use only for testing. + */ ++ (void)crash; + +/** + * Reports that the application is now fully displayed to the user. + * + * Used for Time To Full Display tracking. + */ ++ (void)reportFullyDisplayed; + +/** + * Pauses app hang tracking. + * + * Use this when performing known long-running operations on the main thread + * that should not be reported as app hangs. + */ ++ (void)pauseAppHangTracking; + +/** + * Resumes app hang tracking after it was paused. + */ ++ (void)resumeAppHangTracking; + +/** + * Waits for all pending events to be sent to Sentry. + * + * @param timeout Maximum time to wait in seconds. + */ ++ (void)flush:(NSTimeInterval)timeout; + +/** + * Shuts down the SDK and releases resources. + * + * After calling this method, the SDK will no longer capture events. + */ ++ (void)close; + +#if !(TARGET_OS_WATCH || TARGET_OS_TV || TARGET_OS_VISION) +/** + * Manually starts the profiler. + * + * Profiling is typically controlled automatically by sampling, but this + * method allows manual control for testing or specific use cases. + */ ++ (void)startProfiler; + +/** + * Manually stops the profiler. + */ ++ (void)stopProfiler; +#endif + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentrySampleDecision.h b/Sources/SentryObjC/Public/SentrySampleDecision.h new file mode 100644 index 00000000000..50ec2272236 --- /dev/null +++ b/Sources/SentryObjC/Public/SentrySampleDecision.h @@ -0,0 +1,21 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Trace sample decision flag. + * + * @see SentryTracesSamplerCallback + */ +typedef NS_ENUM(NSUInteger, SentrySampleDecision) { + /** Used when the decision to sample a trace should be postponed. */ + kSentrySampleDecisionUndecided, + + /** The trace should be sampled. */ + kSentrySampleDecisionYes, + + /** The trace should not be sampled. */ + kSentrySampleDecisionNo +}; + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentrySamplingContext.h b/Sources/SentryObjC/Public/SentrySamplingContext.h new file mode 100644 index 00000000000..1afbf0412da --- /dev/null +++ b/Sources/SentryObjC/Public/SentrySamplingContext.h @@ -0,0 +1,52 @@ +#import + +@class SentryTransactionContext; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Context passed to the traces sampler callback. + * + * Provides information needed to make dynamic sampling decisions for traces. + * The sampler callback can inspect this context and return a sampling decision. + * + * @see SentryTracesSamplerCallback + */ +@interface SentrySamplingContext : NSObject + +/** + * Transaction context being sampled. + * + * Contains the transaction name, operation, and trace information. + */ +@property (nonatomic, readonly) SentryTransactionContext *transactionContext; + +/** + * Custom data provided for this sampling decision. + * + * Application-specific data that can influence the sampling decision. + * For example, you might include user tier, request path, or feature flags. + */ +@property (nullable, nonatomic, readonly) NSDictionary *customSamplingContext; + +/** + * Creates a sampling context with a transaction context. + * + * @param transactionContext The transaction being sampled. + * @return A new sampling context instance. + */ +- (instancetype)initWithTransactionContext:(SentryTransactionContext *)transactionContext; + +/** + * Creates a sampling context with custom data. + * + * @param transactionContext The transaction being sampled. + * @param customSamplingContext Application-specific sampling data. + * @return A new sampling context instance. + */ +- (instancetype)initWithTransactionContext:(SentryTransactionContext *)transactionContext + customSamplingContext:(NSDictionary *)customSamplingContext; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryScope.h b/Sources/SentryObjC/Public/SentryScope.h new file mode 100644 index 00000000000..41746990947 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryScope.h @@ -0,0 +1,226 @@ +#import + +#import "SentryLevel.h" +#import "SentrySerializable.h" +#import "SentrySpan.h" + +@class SentryAttachment; +@class SentryBreadcrumb; +@class SentryUser; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Scope holds contextual data sent with every event (tags, breadcrumbs, user, etc.). + * + * The scope persists across captures and can be modified to add contextual + * information to all subsequent events. Use @c +[SentrySDK configureScope:] + * to access and modify the current scope. + * + * @see https://docs.sentry.io/platforms/apple/enriching-events/scopes/#whats-a-scope-whats-a-hub + */ +@interface SentryScope : NSObject + +/** + * The currently active span or transaction. + */ +@property (nullable, nonatomic, strong) id span; + +/** + * ID of the current session replay. + * + * Set when a session replay is active. + */ +@property (nullable, nonatomic, strong) NSString *replayId; + +/** + * Currently set tags. + * + * Tags are key-value pairs that are indexed for search in Sentry. + */ +@property (nonatomic, readonly, copy) NSDictionary *tags; + +/** + * Currently set attributes. + * + * Attributes provide additional metadata for spans and transactions. + */ +@property (nonatomic, readonly, copy) NSDictionary *attributes; + +/** + * Creates a new scope with a maximum breadcrumb limit. + * + * @param maxBreadcrumbs Maximum number of breadcrumbs to retain. + * @return A new scope instance. + */ +- (instancetype)initWithMaxBreadcrumbs:(NSInteger)maxBreadcrumbs; + +/** + * Creates a new scope with default settings. + * + * @return A new scope instance. + */ +- (instancetype)init; + +/** + * Creates a new scope by copying another scope. + * + * @param scope The scope to copy from. + * @return A new scope instance with copied data. + */ +- (instancetype)initWithScope:(SentryScope *)scope; + +/** + * Sets user information for this scope. + * + * @param user The user information to set. + */ +- (void)setUser:(SentryUser *)user; + +/** + * Sets a tag value for a specific key. + * + * @param value The tag value. + * @param key The tag key. + */ +- (void)setTagValue:(NSString *)value forKey:(NSString *)key; + +/** + * Removes a tag for the specified key. + * + * @param key The tag key to remove. + */ +- (void)removeTagForKey:(NSString *)key; + +/** + * Replaces all tags with the provided dictionary. + * + * @param tags Dictionary of tags to set. + */ +- (void)setTags:(NSDictionary *)tags; + +/** + * Replaces all extras with the provided dictionary. + * + * @param extras Dictionary of extra data to set. + */ +- (void)setExtras:(NSDictionary *)extras; + +/** + * Sets an extra value for a specific key. + * + * @param value The extra value. + * @param key The extra key. + */ +- (void)setExtraValue:(id)value forKey:(NSString *)key; + +/** + * Removes an extra value for the specified key. + * + * @param key The extra key to remove. + */ +- (void)removeExtraForKey:(NSString *)key; + +/** + * Sets the distribution identifier for this scope. + * + * @param dist The distribution identifier. + */ +- (void)setDist:(NSString *)dist; + +/** + * Sets the environment name for this scope. + * + * @param environment The environment name. + */ +- (void)setEnvironment:(NSString *)environment; + +/** + * Sets the fingerprint for grouping events. + * + * @param fingerprint Array of fingerprint strings. + */ +- (void)setFingerprint:(NSArray *)fingerprint; + +/** + * Sets the severity level for events from this scope. + * + * @param level The severity level. + */ +- (void)setLevel:(SentryLevel)level; + +/** + * Adds a breadcrumb to this scope. + * + * @param crumb The breadcrumb to add. + */ +- (void)addBreadcrumb:(SentryBreadcrumb *)crumb; + +/** + * Removes all breadcrumbs from this scope. + */ +- (void)clearBreadcrumbs; + +/** + * Serializes the scope to a dictionary. + * + * @return Dictionary representation of the scope. + */ +- (NSDictionary *)serialize; + +/** + * Sets a context value for a specific category. + * + * Common categories include "device", "os", "app", etc. + * + * @param value Dictionary of context data. + * @param key The context category key. + */ +- (void)setContextValue:(NSDictionary *)value forKey:(NSString *)key; + +/** + * Removes context for the specified category. + * + * @param key The context category key to remove. + */ +- (void)removeContextForKey:(NSString *)key; + +/** + * Adds an attachment to this scope. + * + * Attachments are sent with all subsequent events from this scope. + * + * @param attachment The attachment to add. + */ +- (void)addAttachment:(SentryAttachment *)attachment; + +/** + * Sets an attribute value for a specific key. + * + * @param value The attribute value. + * @param key The attribute key. + */ +- (void)setAttributeValue:(id)value forKey:(NSString *)key; + +/** + * Removes an attribute for the specified key. + * + * @param key The attribute key to remove. + */ +- (void)removeAttributeForKey:(NSString *)key; + +/** + * Removes all attachments from this scope. + */ +- (void)clearAttachments; + +/** + * Clears all data from this scope. + * + * Resets user, tags, extras, context, breadcrumbs, and attachments. + */ +- (void)clear; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentrySerializable.h b/Sources/SentryObjC/Public/SentrySerializable.h new file mode 100644 index 00000000000..23f39b3f949 --- /dev/null +++ b/Sources/SentryObjC/Public/SentrySerializable.h @@ -0,0 +1,28 @@ +#import + +#import "SentryDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Protocol for types that can be serialized to a dictionary. + * + * @see SentryScope + * @see SentryBreadcrumb + * @see SentryEvent + */ +@protocol SentrySerializable + +SENTRY_NO_INIT + +/** + * Serialize the contents of the object into an NSDictionary. + * + * @return A dictionary representation. Modifications to the original object do not affect the + * returned dictionary. + */ +- (NSDictionary *)serialize; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentrySpan.h b/Sources/SentryObjC/Public/SentrySpan.h new file mode 100644 index 00000000000..29d2f7cfbe3 --- /dev/null +++ b/Sources/SentryObjC/Public/SentrySpan.h @@ -0,0 +1,224 @@ +#import + +#import "SentrySampleDecision.h" +#import "SentrySerializable.h" +#import "SentrySpanContext.h" +#import "SentrySpanStatus.h" + +@class SentryId; +@class SentryMeasurementUnit; +@class SentrySpanId; +@class SentryTraceContext; +@class SentryTraceHeader; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Protocol for a span in a trace. + * + * Spans represent units of work within a transaction, such as database queries, + * network requests, or function calls. Use spans to instrument your code for + * performance monitoring. + * + * @see SentrySDK + * @see SentryTransactionContext + */ +@protocol SentrySpan + +/** + * Unique identifier for the trace this span belongs to. + * + * All spans in the same trace share this ID. + */ +@property (nonatomic, strong) SentryId *traceId; + +/** + * Unique identifier for this span. + */ +@property (nonatomic, strong) SentrySpanId *spanId; + +/** + * Identifier of the parent span. + * + * @c nil for root spans (transactions). + */ +@property (nullable, nonatomic, strong) SentrySpanId *parentSpanId; + +/** + * Whether this span is sampled. + * + * Only sampled spans are sent to Sentry. + */ +@property (nonatomic) SentrySampleDecision sampled; + +/** + * Operation type for this span. + * + * Examples: "db.query", "http.client", "ui.load". + */ +@property (nonatomic, copy) NSString *operation; + +/** + * Origin of this span, indicating which instrumentation created it. + * + * Examples: "manual", "auto.http", "auto.db". + */ +@property (nonatomic, copy) NSString *origin; + +/** + * Human-readable description of this span. + * + * Example: "SELECT * FROM users WHERE id = ?". + */ +@property (nullable, nonatomic, copy) NSString *spanDescription; + +/** + * Status of this span. + * + * Indicates whether the operation succeeded, failed, or was cancelled. + */ +@property (nonatomic) SentrySpanStatus status; + +/** + * Timestamp when this span finished. + * + * Set automatically when @c -finish is called. + */ +@property (nullable, nonatomic, strong) NSDate *timestamp; + +/** + * Timestamp when this span started. + * + * Set automatically when the span is created. + */ +@property (nullable, nonatomic, strong) NSDate *startTimestamp; + +/** + * Additional structured data attached to this span. + * + * Read-only. Use @c -setDataValue:forKey: to modify. + */ +@property (readonly) NSDictionary *data; + +/** + * Tags attached to this span. + * + * Read-only. Use @c -setTagValue:forKey: to modify. + */ +@property (readonly) NSDictionary *tags; + +/** + * Whether this span has been finished. + */ +@property (readonly) BOOL isFinished; + +/** + * Trace context for distributed tracing. + * + * Contains information needed to continue the trace across service boundaries. + */ +@property (nullable, nonatomic, readonly) SentryTraceContext *traceContext; + +/** + * Starts a new child span with the specified operation. + * + * @param operation The operation type for the child span. + * @return A new child span. + */ +- (id)startChildWithOperation:(NSString *)operation; + +/** + * Starts a new child span with operation and description. + * + * @param operation The operation type for the child span. + * @param description Human-readable description of the operation. + * @return A new child span. + */ +- (id)startChildWithOperation:(NSString *)operation + description:(nullable NSString *)description; + +/** + * Sets a data value for the specified key. + * + * @param value The value to set, or @c nil to remove the key. + * @param key The key to set. + */ +- (void)setDataValue:(nullable id)value forKey:(NSString *)key; + +/** + * Removes data for the specified key. + * + * @param key The key to remove. + */ +- (void)removeDataForKey:(NSString *)key; + +/** + * Sets a tag value for the specified key. + * + * @param value The tag value. + * @param key The tag key. + */ +- (void)setTagValue:(NSString *)value forKey:(NSString *)key; + +/** + * Removes a tag for the specified key. + * + * @param key The tag key to remove. + */ +- (void)removeTagForKey:(NSString *)key; + +/** + * Adds a measurement to this span. + * + * @param name The measurement name. + * @param value The measurement value. + */ +- (void)setMeasurement:(NSString *)name value:(NSNumber *)value; + +/** + * Adds a measurement with a unit to this span. + * + * @param name The measurement name. + * @param value The measurement value. + * @param unit The measurement unit. + */ +- (void)setMeasurement:(NSString *)name value:(NSNumber *)value unit:(SentryMeasurementUnit *)unit; + +/** + * Finishes this span with a successful status. + * + * Records the finish timestamp and marks the span as complete. + */ +- (void)finish; + +/** + * Finishes this span with the specified status. + * + * @param status The status to set for this span. + */ +- (void)finishWithStatus:(SentrySpanStatus)status; + +/** + * Creates a trace header for distributed tracing. + * + * @return A trace header containing this span's trace information. + */ +- (SentryTraceHeader *)toTraceHeader; + +/** + * Creates a baggage HTTP header value for distributed tracing. + * + * @return The baggage header value, or @c nil if no baggage is set. + */ +- (nullable NSString *)baggageHttpHeader; + +/** + * Serializes the span to a dictionary. + * + * @return Dictionary representation of the span. + */ +- (NSDictionary *)serialize; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentrySpanContext.h b/Sources/SentryObjC/Public/SentrySpanContext.h new file mode 100644 index 00000000000..1982e3dd031 --- /dev/null +++ b/Sources/SentryObjC/Public/SentrySpanContext.h @@ -0,0 +1,105 @@ +#import + +#import "SentryDefines.h" +#import "SentrySampleDecision.h" +#import "SentrySerializable.h" + +@class SentryId; +@class SentrySpanId; + +NS_ASSUME_NONNULL_BEGIN + +static NSString *const SENTRY_TRACE_TYPE = @"trace"; + +/** + * Context identifying a span within a trace. + * + * @see SentrySpan + * @see SentryTransactionContext + */ +@interface SentrySpanContext : NSObject + +SENTRY_NO_INIT + +/** Determines which trace the Span belongs to. */ +@property (nonatomic, readonly) SentryId *traceId; + +/** Span id. */ +@property (nonatomic, readonly) SentrySpanId *spanId; + +/** Id of a parent span. */ +@property (nullable, nonatomic, readonly) SentrySpanId *parentSpanId; + +/** Whether the trace is sampled. */ +@property (nonatomic, readonly) SentrySampleDecision sampled; + +/** Short code identifying the type of operation the span is measuring. */ +@property (nonatomic, copy, readonly) NSString *operation; + +/** Longer description of the span's operation. */ +@property (nullable, nonatomic, copy, readonly) NSString *spanDescription; + +/** + * The origin of the span indicates what created the span. + * + * @note Set by the SDK. Not expected to be set manually. + * @see https://develop.sentry.dev/sdk/performance/trace-origin + */ +@property (nonatomic, copy) NSString *origin; + +/** + * Creates a span context with an operation. + * + * Trace ID and span ID are randomly generated. + * + * @param operation The operation type. + * @return A new span context instance. + */ +- (instancetype)initWithOperation:(NSString *)operation; + +/** + * Creates a span context with operation and sampling decision. + * + * @param operation The operation type. + * @param sampled Whether this span is sampled. + * @return A new span context instance. + */ +- (instancetype)initWithOperation:(NSString *)operation sampled:(SentrySampleDecision)sampled; + +/** + * Creates a span context with full trace information. + * + * @param traceId The trace ID. + * @param spanId The span ID. + * @param parentId The parent span ID, or @c nil for root spans. + * @param operation The operation type. + * @param sampled Whether this span is sampled. + * @return A new span context instance. + */ +- (instancetype)initWithTraceId:(SentryId *)traceId + spanId:(SentrySpanId *)spanId + parentId:(nullable SentrySpanId *)parentId + operation:(NSString *)operation + sampled:(SentrySampleDecision)sampled; + +/** + * Creates a span context with full trace information and description. + * + * @param traceId The trace ID. + * @param spanId The span ID. + * @param parentId The parent span ID, or @c nil for root spans. + * @param operation The operation type. + * @param description Human-readable description of the span. + * @param sampled Whether this span is sampled. + * @return A new span context instance. + */ +- (instancetype)initWithTraceId:(SentryId *)traceId + spanId:(SentrySpanId *)spanId + parentId:(nullable SentrySpanId *)parentId + operation:(NSString *)operation + spanDescription:(nullable NSString *)description + sampled:(SentrySampleDecision)sampled; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentrySpanId.h b/Sources/SentryObjC/Public/SentrySpanId.h new file mode 100644 index 00000000000..d819dca3ef7 --- /dev/null +++ b/Sources/SentryObjC/Public/SentrySpanId.h @@ -0,0 +1,35 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * A 16-character identifier for a span. + * + * @see SentrySpanContext + * @see SentrySpan + */ +@interface SentrySpanId : NSObject + +/** Creates a SentrySpanId with a random 16 character Id. */ +- (instancetype)init; + +/** Creates a SentrySpanId with the first 16 characters of the given UUID. */ +- (instancetype)initWithUUID:(NSUUID *)uuid; + +/** + * Creates a SentrySpanId from a 16 character string. + * + * @param value A 16-character string. + * @return Empty SentrySpanId if the input is invalid. + */ +- (instancetype)initWithValue:(NSString *)value; + +/** Returns the span Id value. */ +@property (readonly, copy) NSString *sentrySpanIdString; + +/** A SentrySpanId with an empty Id "0000000000000000". */ +@property (class, nonatomic, readonly, strong) SentrySpanId *empty; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentrySpanStatus.h b/Sources/SentryObjC/Public/SentrySpanStatus.h new file mode 100644 index 00000000000..c2a8f78c0d3 --- /dev/null +++ b/Sources/SentryObjC/Public/SentrySpanStatus.h @@ -0,0 +1,52 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Describes the status of the Span/Transaction. + * + * @see SentrySpan + */ +typedef NS_ENUM(NSUInteger, SentrySpanStatus) { + kSentrySpanStatusUndefined, + kSentrySpanStatusOk, + kSentrySpanStatusDeadlineExceeded, + kSentrySpanStatusUnauthenticated, + kSentrySpanStatusPermissionDenied, + kSentrySpanStatusNotFound, + kSentrySpanStatusResourceExhausted, + kSentrySpanStatusInvalidArgument, + kSentrySpanStatusUnimplemented, + kSentrySpanStatusUnavailable, + kSentrySpanStatusInternalError, + kSentrySpanStatusUnknownError, + kSentrySpanStatusCancelled, + kSentrySpanStatusAlreadyExists, + kSentrySpanStatusFailedPrecondition, + kSentrySpanStatusAborted, + kSentrySpanStatusOutOfRange, + kSentrySpanStatusDataLoss, +}; + +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameUndefined; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameOk; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameDeadlineExceeded; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameUnauthenticated; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNamePermissionDenied; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameNotFound; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameResourceExhausted; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameInvalidArgument; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameUnimplemented; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameUnavailable; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameInternalError; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameUnknownError; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameCancelled; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameAlreadyExists; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameFailedPrecondition; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameAborted; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameOutOfRange; +FOUNDATION_EXPORT NSString *const kSentrySpanStatusNameDataLoss; + +NSString *nameForSentrySpanStatus(SentrySpanStatus status); + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryStacktrace.h b/Sources/SentryObjC/Public/SentryStacktrace.h new file mode 100644 index 00000000000..4331d7d464f --- /dev/null +++ b/Sources/SentryObjC/Public/SentryStacktrace.h @@ -0,0 +1,62 @@ +#import + +#import "SentryDefines.h" +#import "SentrySerializable.h" + +@class SentryFrame; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Stack trace containing frames. + * + * Represents a call stack at a specific point in execution, typically when + * an error or exception occurred. Contains ordered frames from the call site + * up through the call chain. + * + * @see SentryEvent + * @see SentryException + */ +@interface SentryStacktrace : NSObject + +SENTRY_NO_INIT + +/** + * Array of stack frames, ordered from outermost (top of stack) to innermost (call site). + */ +@property (nonatomic, strong) NSArray *frames; + +/** + * CPU register values at the time the stack trace was captured. + * + * Keys are register names (e.g., "pc", "sp", "lr"), values are hex addresses. + */ +@property (nonatomic, strong) NSDictionary *registers; + +/** + * Whether this is a snapshot of the stack at a specific point in time. + * + * Used to distinguish between crash stacks and periodic snapshots. + */ +@property (nonatomic, copy, nullable) NSNumber *snapshot; + +/** + * Creates a stack trace with frames and register values. + * + * @param frames Array of stack frames. + * @param registers CPU register values. + * @return A new stack trace instance. + */ +- (instancetype)initWithFrames:(NSArray *)frames + registers:(NSDictionary *)registers; + +/** + * Removes duplicate frames that may occur from inlining or recursion. + * + * @warning Internal method. Called automatically by the SDK. + */ +- (void)fixDuplicateFrames; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryThread.h b/Sources/SentryObjC/Public/SentryThread.h new file mode 100644 index 00000000000..33797cd8bbc --- /dev/null +++ b/Sources/SentryObjC/Public/SentryThread.h @@ -0,0 +1,72 @@ +#import + +#import "SentryDefines.h" +#import "SentrySerializable.h" + +@class SentryStacktrace; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Thread information for an event. + * + * Represents a thread's state at the time of an event, including its stack trace + * and metadata about whether it crashed or was the current/main thread. + * + * @see SentryEvent + */ +@interface SentryThread : NSObject + +SENTRY_NO_INIT + +/** + * Unique identifier for this thread. + */ +@property (nullable, nonatomic, copy) NSNumber *threadId; + +/** + * Name of the thread, if available. + * + * Named threads (e.g., from @c pthread_setname_np) display better in Sentry. + */ +@property (nullable, nonatomic, copy) NSString *name; + +/** + * Stack trace for this thread. + * + * Contains the call stack at the time the event occurred. + */ +@property (nullable, nonatomic, strong) SentryStacktrace *stacktrace; + +/** + * Whether this thread crashed. + * + * @c YES for the crashing thread, @c NO for other threads. + */ +@property (nullable, nonatomic, copy) NSNumber *crashed; + +/** + * Whether this was the currently executing thread. + * + * @c YES for the thread that was running when the event occurred. + */ +@property (nullable, nonatomic, copy) NSNumber *current; + +/** + * Whether this is the main thread. + * + * @c YES for the main/UI thread. + */ +@property (nullable, nonatomic, copy) NSNumber *isMain; + +/** + * Creates thread information with a thread ID. + * + * @param threadId The thread identifier, or @c nil if unknown. + * @return A new thread instance. + */ +- (instancetype)initWithThreadId:(nullable NSNumber *)threadId; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryTraceContext.h b/Sources/SentryObjC/Public/SentryTraceContext.h new file mode 100644 index 00000000000..1661ae2edf4 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryTraceContext.h @@ -0,0 +1,49 @@ +#import + +#import "SentrySerializable.h" + +@class SentryBaggage; +@class SentryId; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Trace context for distributed tracing. + * + * @see SentrySpan + */ +@interface SentryTraceContext : NSObject + +/** UUID V4 encoded as 32 hexadecimal digits. */ +@property (nonatomic, readonly) SentryId *traceId; + +/** Public key from the DSN. */ +@property (nonatomic, readonly) NSString *publicKey; + +/** Release name, e.g. package@x.y.z+build. */ +@property (nullable, nonatomic, readonly) NSString *releaseName; + +/** Environment name, e.g. staging. */ +@property (nullable, nonatomic, readonly) NSString *environment; + +/** Transaction name from the scope. */ +@property (nullable, nonatomic, readonly) NSString *transaction; + +/** Serialized sample rate. */ +@property (nullable, nonatomic, readonly) NSString *sampleRate; + +/** Serialized random value for sampling. */ +@property (nullable, nonatomic, readonly) NSString *sampleRand; + +/** Whether the trace was sampled. */ +@property (nullable, nonatomic, readonly) NSString *sampled; + +/** Id of the current session replay. */ +@property (nullable, nonatomic, readonly) NSString *replayId; + +/** Creates a SentryBaggage from this trace context. */ +- (SentryBaggage *)toBaggage; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryTraceHeader.h b/Sources/SentryObjC/Public/SentryTraceHeader.h new file mode 100644 index 00000000000..16fd2e486c3 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryTraceHeader.h @@ -0,0 +1,41 @@ +#import + +#import "SentryDefines.h" +#import "SentrySampleDecision.h" + +@class SentryId; +@class SentrySpanId; + +NS_ASSUME_NONNULL_BEGIN + +static NSString *const SENTRY_TRACE_HEADER = @"sentry-trace"; + +/** + * Trace information for the sentry-trace HTTP header. + * + * @see SentrySpan + */ +@interface SentryTraceHeader : NSObject + +SENTRY_NO_INIT + +/** Trace ID. */ +@property (nonatomic, readonly) SentryId *traceId; + +/** Span ID. */ +@property (nonatomic, readonly) SentrySpanId *spanId; + +/** The trace sample decision. */ +@property (nonatomic, readonly) SentrySampleDecision sampled; + +/** Creates a trace header with the given values. */ +- (instancetype)initWithTraceId:(SentryId *)traceId + spanId:(SentrySpanId *)spanId + sampled:(SentrySampleDecision)sampled; + +/** Returns the value to use in a request header. */ +- (NSString *)value; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryTransactionContext.h b/Sources/SentryObjC/Public/SentryTransactionContext.h new file mode 100644 index 00000000000..f6360c39f24 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryTransactionContext.h @@ -0,0 +1,133 @@ +#import + +#import "SentryDefines.h" +#import "SentrySampleDecision.h" +#import "SentrySpanContext.h" +#import "SentryTransactionNameSource.h" + +@class SentryId; +@class SentrySpanId; + +NS_ASSUME_NONNULL_BEGIN + +/** + * Context for a transaction (root span). + * + * Transactions represent high-level operations that span multiple lower-level spans. + * Examples include page loads, navigation events, or API requests. + * + * @see SentrySDK + * @see SentrySpanContext + */ +@interface SentryTransactionContext : SentrySpanContext + +SENTRY_NO_INIT + +/** + * Human-readable name of the transaction. + * + * Examples: "/api/users", "MainActivity.onCreate", "button.click". + */ +@property (nonatomic, readonly) NSString *name; + +/** + * Source indicating how the transaction name was determined. + * + * Used for grouping and quality scoring in Sentry. + */ +@property (nonatomic, readonly) SentryTransactionNameSource nameSource; + +/** + * Sample rate applied to this transaction. + * + * A value between 0.0 and 1.0 indicating the probability this transaction is sampled. + */ +@property (nonatomic, strong, nullable) NSNumber *sampleRate; + +/** + * Random value used to determine if this transaction is sampled. + * + * Compared against @c sampleRate to make the sampling decision. + */ +@property (nonatomic, strong, nullable) NSNumber *sampleRand; + +/** + * Whether the parent transaction/span is sampled. + * + * Used in distributed tracing to propagate sampling decisions. + */ +@property (nonatomic) SentrySampleDecision parentSampled; + +/** + * Sample rate of the parent transaction. + * + * Propagated from the parent in distributed tracing. + */ +@property (nonatomic, strong, nullable) NSNumber *parentSampleRate; + +/** + * Random sampling value from the parent transaction. + * + * Propagated from the parent in distributed tracing. + */ +@property (nonatomic, strong, nullable) NSNumber *parentSampleRand; + +/** + * Whether this transaction context is for app launch profiling. + * + * @warning Internal use. Set by the SDK for sampling app launch profiles. + */ +@property (nonatomic, assign) BOOL forNextAppLaunch; + +/** + * Creates a transaction context with name and operation. + * + * @param name The transaction name. + * @param operation The operation type. + * @return A new transaction context instance. + */ +- (instancetype)initWithName:(NSString *)name operation:(NSString *)operation; + +/** + * Creates a transaction context with sampling parameters. + * + * @param name The transaction name. + * @param operation The operation type. + * @param sampled Whether this transaction is sampled. + * @param sampleRate The sample rate applied. + * @param sampleRand Random value used for sampling. + * @return A new transaction context instance. + */ +- (instancetype)initWithName:(NSString *)name + operation:(NSString *)operation + sampled:(SentrySampleDecision)sampled + sampleRate:(nullable NSNumber *)sampleRate + sampleRand:(nullable NSNumber *)sampleRand; + +/** + * Creates a transaction context with full trace and sampling information. + * + * Used for distributed tracing to continue a trace from another service. + * + * @param name The transaction name. + * @param operation The operation type. + * @param traceId The trace ID. + * @param spanId The span ID for this transaction. + * @param parentSpanId The parent span ID, or @c nil if this is the root. + * @param parentSampled Whether the parent is sampled. + * @param parentSampleRate Sample rate of the parent. + * @param parentSampleRand Random sampling value from the parent. + * @return A new transaction context instance. + */ +- (instancetype)initWithName:(NSString *)name + operation:(NSString *)operation + traceId:(SentryId *)traceId + spanId:(SentrySpanId *)spanId + parentSpanId:(nullable SentrySpanId *)parentSpanId + parentSampled:(SentrySampleDecision)parentSampled + parentSampleRate:(nullable NSNumber *)parentSampleRate + parentSampleRand:(nullable NSNumber *)parentSampleRand; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryTransactionNameSource.h b/Sources/SentryObjC/Public/SentryTransactionNameSource.h new file mode 100644 index 00000000000..bdb7557de9a --- /dev/null +++ b/Sources/SentryObjC/Public/SentryTransactionNameSource.h @@ -0,0 +1,30 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Describes the source of the transaction name. + * + * @see SentryTransactionContext + */ +typedef NS_ENUM(NSInteger, SentryTransactionNameSource) { + /** The name was set manually by the user. */ + kSentryTransactionNameSourceCustom = 0, + + /** The name was derived from the request URL. */ + kSentryTransactionNameSourceUrl, + + /** The name was derived from a routing framework. */ + kSentryTransactionNameSourceRoute, + + /** The name was derived from a UI view or screen. */ + kSentryTransactionNameSourceView, + + /** The name was derived from a UI component. */ + kSentryTransactionNameSourceComponent, + + /** The name was derived from a background task. */ + kSentryTransactionNameSourceTask, +}; + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryUnit.h b/Sources/SentryObjC/Public/SentryUnit.h new file mode 100644 index 00000000000..290bb046e13 --- /dev/null +++ b/Sources/SentryObjC/Public/SentryUnit.h @@ -0,0 +1,47 @@ +#import + +#import "SentryDefines.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Type-safe units for telemetry data (Metrics, Spans, and Logs). + * + * @see https://develop.sentry.dev/sdk/telemetry/attributes/#units + */ +typedef NSString *SentryUnitName NS_STRING_ENUM; + +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameNanosecond; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameMicrosecond; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameMillisecond; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameSecond; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameMinute; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameHour; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameDay; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameWeek; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameBit; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameByte; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameKilobyte; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameKibibyte; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameMegabyte; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameMebibyte; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameGigabyte; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameGibibyte; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameTerabyte; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameTebibyte; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNamePetabyte; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNamePebibyte; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameExabyte; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameExbibyte; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNameRatio; +FOUNDATION_EXPORT SentryUnitName const SentryUnitNamePercent; + +/** + * Creates a custom unit from a string name. + * + * @param name The unit name (e.g. "custom", "request"). + * @return A unit string for use with metrics. + */ +FOUNDATION_EXPORT SentryUnitName SentryUnitWithName(NSString *name); + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/SentryUser.h b/Sources/SentryObjC/Public/SentryUser.h new file mode 100644 index 00000000000..4913ed5c39a --- /dev/null +++ b/Sources/SentryObjC/Public/SentryUser.h @@ -0,0 +1,101 @@ +#import + +#import "SentrySerializable.h" + +@class SentryGeo; + +NS_ASSUME_NONNULL_BEGIN + +/** + * User information attached to events. + * + * Use this to identify and provide context about the user who experienced an issue. + * Setting user information helps correlate events with specific users in Sentry. + * + * @see SentryScope + */ +@interface SentryUser : NSObject + +/** + * Unique identifier for the user. + */ +@property (atomic, copy) NSString *userId; + +/** + * Email address of the user. + * + * @note Only sent when @c sendDefaultPii is @c YES. + */ +@property (atomic, copy) NSString *email; + +/** + * Username of the user. + * + * @note Only sent when @c sendDefaultPii is @c YES. + */ +@property (atomic, copy) NSString *username; + +/** + * IP address of the user. + * + * @note Only sent when @c sendDefaultPii is @c YES. If not set, Sentry + * will use the IP address from the HTTP request. + */ +@property (atomic, copy) NSString *ipAddress; + +/** + * Display name of the user. + */ +@property (atomic, copy) NSString *name; + +/** + * Geographic location information for the user. + */ +@property (nullable, nonatomic, strong) SentryGeo *geo; + +/** + * Additional arbitrary data associated with the user. + */ +@property (atomic, strong) NSDictionary *data; + +/** + * Creates a user with the specified user ID. + * + * @param userId The unique identifier for the user. + * @return A new user instance. + */ +- (instancetype)initWithUserId:(NSString *)userId; + +/** + * Creates a user with default values. + * + * @return A new user instance. + */ +- (instancetype)init; + +/** + * Compares this user with another object for equality. + * + * @param other The object to compare with. + * @return @c YES if the objects are equal, @c NO otherwise. + */ +- (BOOL)isEqual:(nullable id)other; + +/** + * Compares this user with another user for equality. + * + * @param user The user to compare with. + * @return @c YES if the users are equal, @c NO otherwise. + */ +- (BOOL)isEqualToUser:(SentryUser *)user; + +/** + * Returns a hash value for this user. + * + * @return The hash value. + */ +- (NSUInteger)hash; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/Public/module.modulemap b/Sources/SentryObjC/Public/module.modulemap new file mode 100644 index 00000000000..8202b5efa9f --- /dev/null +++ b/Sources/SentryObjC/Public/module.modulemap @@ -0,0 +1,4 @@ +module SentryObjC { + umbrella header "SentryObjC.h" + export * +} diff --git a/Sources/SentryObjC/SentryAttributeContent.m b/Sources/SentryObjC/SentryAttributeContent.m new file mode 100644 index 00000000000..9015784f588 --- /dev/null +++ b/Sources/SentryObjC/SentryAttributeContent.m @@ -0,0 +1,85 @@ +#import "SentryAttributeContent.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface SentryAttributeContent () +@property (nonatomic, readwrite) SentryAttributeContentType type; +@property (nonatomic, readwrite, copy, nullable) NSString *stringValue; +@property (nonatomic, readwrite) BOOL booleanValue; +@property (nonatomic, readwrite) NSInteger integerValue; +@property (nonatomic, readwrite) double doubleValue; +@property (nonatomic, readwrite, copy, nullable) NSArray *stringArrayValue; +@property (nonatomic, readwrite, copy, nullable) NSArray *booleanArrayValue; +@property (nonatomic, readwrite, copy, nullable) NSArray *integerArrayValue; +@property (nonatomic, readwrite, copy, nullable) NSArray *doubleArrayValue; +@end + +@implementation SentryAttributeContent + ++ (instancetype)stringWithValue:(NSString *)value +{ + SentryAttributeContent *obj = [[SentryAttributeContent alloc] init]; + obj->_type = SentryAttributeContentTypeString; + obj->_stringValue = [value copy]; + return obj; +} + ++ (instancetype)booleanWithValue:(BOOL)value +{ + SentryAttributeContent *obj = [[SentryAttributeContent alloc] init]; + obj->_type = SentryAttributeContentTypeBoolean; + obj->_booleanValue = value; + return obj; +} + ++ (instancetype)integerWithValue:(NSInteger)value +{ + SentryAttributeContent *obj = [[SentryAttributeContent alloc] init]; + obj->_type = SentryAttributeContentTypeInteger; + obj->_integerValue = value; + return obj; +} + ++ (instancetype)doubleWithValue:(double)value +{ + SentryAttributeContent *obj = [[SentryAttributeContent alloc] init]; + obj->_type = SentryAttributeContentTypeDouble; + obj->_doubleValue = value; + return obj; +} + ++ (instancetype)stringArrayWithValue:(NSArray *)value +{ + SentryAttributeContent *obj = [[SentryAttributeContent alloc] init]; + obj->_type = SentryAttributeContentTypeStringArray; + obj->_stringArrayValue = [value copy]; + return obj; +} + ++ (instancetype)booleanArrayWithValue:(NSArray *)value +{ + SentryAttributeContent *obj = [[SentryAttributeContent alloc] init]; + obj->_type = SentryAttributeContentTypeBooleanArray; + obj->_booleanArrayValue = [value copy]; + return obj; +} + ++ (instancetype)integerArrayWithValue:(NSArray *)value +{ + SentryAttributeContent *obj = [[SentryAttributeContent alloc] init]; + obj->_type = SentryAttributeContentTypeIntegerArray; + obj->_integerArrayValue = [value copy]; + return obj; +} + ++ (instancetype)doubleArrayWithValue:(NSArray *)value +{ + SentryAttributeContent *obj = [[SentryAttributeContent alloc] init]; + obj->_type = SentryAttributeContentTypeDoubleArray; + obj->_doubleArrayValue = [value copy]; + return obj; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/SentryMetric.m b/Sources/SentryObjC/SentryMetric.m new file mode 100644 index 00000000000..7f09da126c0 --- /dev/null +++ b/Sources/SentryObjC/SentryMetric.m @@ -0,0 +1,14 @@ +#import "SentryMetric.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation SentryMetric + +- (instancetype)init +{ + return [super init]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/SentryMetricValue.m b/Sources/SentryObjC/SentryMetricValue.m new file mode 100644 index 00000000000..9cb802ba60a --- /dev/null +++ b/Sources/SentryObjC/SentryMetricValue.m @@ -0,0 +1,40 @@ +#import "SentryMetricValue.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface SentryMetricValue () +@property (nonatomic, readwrite) SentryMetricValueType type; +@property (nonatomic, readwrite) unsigned long long counterValue; +@property (nonatomic, readwrite) double gaugeValue; +@property (nonatomic, readwrite) double distributionValue; +@end + +@implementation SentryMetricValue + ++ (instancetype)counterWithValue:(unsigned long long)value +{ + SentryMetricValue *obj = [[SentryMetricValue alloc] init]; + obj->_type = SentryMetricValueTypeCounter; + obj->_counterValue = value; + return obj; +} + ++ (instancetype)gaugeWithValue:(double)value +{ + SentryMetricValue *obj = [[SentryMetricValue alloc] init]; + obj->_type = SentryMetricValueTypeGauge; + obj->_gaugeValue = value; + return obj; +} + ++ (instancetype)distributionWithValue:(double)value +{ + SentryMetricValue *obj = [[SentryMetricValue alloc] init]; + obj->_type = SentryMetricValueTypeDistribution; + obj->_distributionValue = value; + return obj; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/SentryMetricsApiImpl.h b/Sources/SentryObjC/SentryMetricsApiImpl.h new file mode 100644 index 00000000000..adf8188b2a2 --- /dev/null +++ b/Sources/SentryObjC/SentryMetricsApiImpl.h @@ -0,0 +1,17 @@ +#import + +#import "SentryMetricsApi.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Internal implementation of the metrics API protocol. + * + * This class delegates all metrics recording to the Swift layer via SentrySDKInternal. + * Not exposed in public headers. + */ +@interface SentryMetricsApiImpl : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/SentryMetricsApiImpl.m b/Sources/SentryObjC/SentryMetricsApiImpl.m new file mode 100644 index 00000000000..5426d95cc3a --- /dev/null +++ b/Sources/SentryObjC/SentryMetricsApiImpl.m @@ -0,0 +1,54 @@ +#import "SentryMetricsApiImpl.h" + +NS_ASSUME_NONNULL_BEGIN + +// Forward declare SentryObjCBridge to avoid importing headers that require modules. +// At link time, the actual implementation from SentryObjCBridge will be used. +@interface SentryObjCBridge : NSObject ++ (void)metricsCountWithKey:(NSString *)key + value:(NSUInteger)value + attributes:(NSDictionary *)attributes; + ++ (void)metricsDistributionWithKey:(NSString *)key + value:(double)value + unit:(nullable NSString *)unit + attributes:(NSDictionary *)attributes; + ++ (void)metricsGaugeWithKey:(NSString *)key + value:(double)value + unit:(nullable NSString *)unit + attributes:(NSDictionary *)attributes; +@end + +@implementation SentryMetricsApiImpl + +- (void)countWithKey:(NSString *)key + value:(NSUInteger)value + attributes:(nullable NSDictionary *)attributes +{ + [SentryObjCBridge metricsCountWithKey:key value:value attributes:attributes ?: @{ }]; +} + +- (void)distributionWithKey:(NSString *)key + value:(double)value + unit:(nullable NSString *)unit + attributes: + (nullable NSDictionary *)attributes +{ + [SentryObjCBridge metricsDistributionWithKey:key + value:value + unit:unit + attributes:attributes ?: @{ }]; +} + +- (void)gaugeWithKey:(NSString *)key + value:(double)value + unit:(nullable NSString *)unit + attributes:(nullable NSDictionary *)attributes +{ + [SentryObjCBridge metricsGaugeWithKey:key value:value unit:unit attributes:attributes ?: @{ }]; +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/SentryRedactRegionType.m b/Sources/SentryObjC/SentryRedactRegionType.m new file mode 100644 index 00000000000..0421ff60c2e --- /dev/null +++ b/Sources/SentryObjC/SentryRedactRegionType.m @@ -0,0 +1,11 @@ +#import "SentryRedactRegionType.h" + +NS_ASSUME_NONNULL_BEGIN + +SentryRedactRegionType const SentryRedactRegionTypeRedact = @"redact"; +SentryRedactRegionType const SentryRedactRegionTypeClipOut = @"clip_out"; +SentryRedactRegionType const SentryRedactRegionTypeClipBegin = @"clip_begin"; +SentryRedactRegionType const SentryRedactRegionTypeClipEnd = @"clip_end"; +SentryRedactRegionType const SentryRedactRegionTypeRedactSwiftUI = @"redact_swiftui"; + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/SentrySDK.m b/Sources/SentryObjC/SentrySDK.m new file mode 100644 index 00000000000..f80bc2126f7 --- /dev/null +++ b/Sources/SentryObjC/SentrySDK.m @@ -0,0 +1,294 @@ +#import + +// Forward declare SentrySDKInternal to avoid importing headers that require modules. +// At link time, the actual implementation from SentryObjCInternal will be used. +@interface SentrySDKInternal : NSObject ++ (nullable id)span; ++ (BOOL)isEnabled; ++ (void)startWithOptions:(id)options; ++ (void)startWithConfigureOptions:(void (^)(id options))configureOptions; ++ (id)captureEvent:(id)event; ++ (id)captureEvent:(id)event withScope:(id)scope; ++ (id)captureEvent:(id)event withScopeBlock:(void (^)(id scope))block; ++ (id)startTransactionWithName:(NSString *)name operation:(NSString *)operation; ++ (id)startTransactionWithName:(NSString *)name + operation:(NSString *)operation + bindToScope:(BOOL)bindToScope; ++ (id)startTransactionWithContext:(id)transactionContext; ++ (id)startTransactionWithContext:(id)transactionContext bindToScope:(BOOL)bindToScope; ++ (id)startTransactionWithContext:(id)transactionContext + customSamplingContext:(NSDictionary *)customSamplingContext; ++ (id)startTransactionWithContext:(id)transactionContext + bindToScope:(BOOL)bindToScope + customSamplingContext:(NSDictionary *)customSamplingContext; ++ (id)captureError:(NSError *)error; ++ (id)captureError:(NSError *)error withScope:(id)scope; ++ (id)captureError:(NSError *)error withScopeBlock:(void (^)(id scope))block; ++ (id)captureException:(NSException *)exception; ++ (id)captureException:(NSException *)exception withScope:(id)scope; ++ (id)captureException:(NSException *)exception withScopeBlock:(void (^)(id scope))block; ++ (id)captureMessage:(NSString *)message; ++ (id)captureMessage:(NSString *)message withScope:(id)scope; ++ (id)captureMessage:(NSString *)message withScopeBlock:(void (^)(id scope))block; ++ (void)captureFeedback:(id)feedback; ++ (void)addBreadcrumb:(id)crumb; ++ (void)configureScope:(void (^)(id scope))callback; ++ (BOOL)crashedLastRun; ++ (BOOL)detectedStartUpCrash; ++ (void)setUser:(nullable id)user; ++ (void)startSession; ++ (void)endSession; ++ (void)crash; ++ (void)reportFullyDisplayed; ++ (void)pauseAppHangTracking; ++ (void)resumeAppHangTracking; ++ (void)flush:(NSTimeInterval)timeout; ++ (void)close; +#if !(TARGET_OS_WATCH || TARGET_OS_TV || TARGET_OS_VISION) ++ (void)startProfiler; ++ (void)stopProfiler; +#endif +@end + +// Forward declare SentryObjCBridge for metrics, logger, and replay access. +@interface SentryObjCBridge : NSObject ++ (id)logger; ++ (id)replay; +@end + +// Import the public header which declares SentrySDK +#import "SentryMetricsApiImpl.h" +#import "SentrySDK.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation SentrySDK + ++ (nullable id)span +{ + return [SentrySDKInternal span]; +} + ++ (BOOL)isEnabled +{ + return [SentrySDKInternal isEnabled]; +} + +#if SENTRY_OBJC_REPLAY_SUPPORTED ++ (SentryReplayApi *)replay +{ + return [SentryObjCBridge replay]; +} +#endif + ++ (SentryLogger *)logger +{ + return [SentryObjCBridge logger]; +} + ++ (id)metrics +{ + static SentryMetricsApiImpl *_metricsApi = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ _metricsApi = [[SentryMetricsApiImpl alloc] init]; }); + return _metricsApi; +} + ++ (void)startWithOptions:(SentryOptions *)options +{ + [SentrySDKInternal startWithOptions:options]; +} + ++ (void)startWithConfigureOptions:(void (^)(SentryOptions *options))configureOptions +{ + [SentrySDKInternal startWithConfigureOptions:configureOptions]; +} + ++ (SentryId *)captureEvent:(SentryEvent *)event +{ + return [SentrySDKInternal captureEvent:event]; +} + ++ (SentryId *)captureEvent:(SentryEvent *)event withScope:(SentryScope *)scope +{ + return [SentrySDKInternal captureEvent:event withScope:scope]; +} + ++ (SentryId *)captureEvent:(SentryEvent *)event withScopeBlock:(void (^)(SentryScope *scope))block +{ + return [SentrySDKInternal captureEvent:event withScopeBlock:block]; +} + ++ (id)startTransactionWithName:(NSString *)name operation:(NSString *)operation +{ + return [SentrySDKInternal startTransactionWithName:name operation:operation]; +} + ++ (id)startTransactionWithName:(NSString *)name + operation:(NSString *)operation + bindToScope:(BOOL)bindToScope +{ + return [SentrySDKInternal startTransactionWithName:name + operation:operation + bindToScope:bindToScope]; +} + ++ (id)startTransactionWithContext:(SentryTransactionContext *)transactionContext +{ + return [SentrySDKInternal startTransactionWithContext:transactionContext]; +} + ++ (id)startTransactionWithContext:(SentryTransactionContext *)transactionContext + bindToScope:(BOOL)bindToScope +{ + return [SentrySDKInternal startTransactionWithContext:transactionContext + bindToScope:bindToScope]; +} + ++ (id)startTransactionWithContext:(SentryTransactionContext *)transactionContext + customSamplingContext:(NSDictionary *)customSamplingContext +{ + return [SentrySDKInternal startTransactionWithContext:transactionContext + customSamplingContext:customSamplingContext]; +} + ++ (id)startTransactionWithContext:(SentryTransactionContext *)transactionContext + bindToScope:(BOOL)bindToScope + customSamplingContext:(NSDictionary *)customSamplingContext +{ + return [SentrySDKInternal startTransactionWithContext:transactionContext + bindToScope:bindToScope + customSamplingContext:customSamplingContext]; +} + ++ (SentryId *)captureError:(NSError *)error +{ + return [SentrySDKInternal captureError:error]; +} + ++ (SentryId *)captureError:(NSError *)error withScope:(SentryScope *)scope +{ + return [SentrySDKInternal captureError:error withScope:scope]; +} + ++ (SentryId *)captureError:(NSError *)error withScopeBlock:(void (^)(SentryScope *scope))block +{ + return [SentrySDKInternal captureError:error withScopeBlock:block]; +} + ++ (SentryId *)captureException:(NSException *)exception +{ + return [SentrySDKInternal captureException:exception]; +} + ++ (SentryId *)captureException:(NSException *)exception withScope:(SentryScope *)scope +{ + return [SentrySDKInternal captureException:exception withScope:scope]; +} + ++ (SentryId *)captureException:(NSException *)exception + withScopeBlock:(void (^)(SentryScope *scope))block +{ + return [SentrySDKInternal captureException:exception withScopeBlock:block]; +} + ++ (SentryId *)captureMessage:(NSString *)message +{ + return [SentrySDKInternal captureMessage:message]; +} + ++ (SentryId *)captureMessage:(NSString *)message withScope:(SentryScope *)scope +{ + return [SentrySDKInternal captureMessage:message withScope:scope]; +} + ++ (SentryId *)captureMessage:(NSString *)message withScopeBlock:(void (^)(SentryScope *scope))block +{ + return [SentrySDKInternal captureMessage:message withScopeBlock:block]; +} + ++ (void)captureFeedback:(SentryFeedback *)feedback +{ + [SentrySDKInternal captureFeedback:feedback]; +} + ++ (void)addBreadcrumb:(SentryBreadcrumb *)crumb +{ + [SentrySDKInternal addBreadcrumb:crumb]; +} + ++ (void)configureScope:(void (^)(SentryScope *scope))callback +{ + [SentrySDKInternal configureScope:callback]; +} + ++ (BOOL)crashedLastRun +{ + return [SentrySDKInternal crashedLastRun]; +} + ++ (BOOL)detectedStartUpCrash +{ + return [SentrySDKInternal detectedStartUpCrash]; +} + ++ (void)setUser:(nullable SentryUser *)user +{ + [SentrySDKInternal setUser:user]; +} + ++ (void)startSession +{ + [SentrySDKInternal startSession]; +} + ++ (void)endSession +{ + [SentrySDKInternal endSession]; +} + ++ (void)crash +{ + [SentrySDKInternal crash]; +} + ++ (void)reportFullyDisplayed +{ + [SentrySDKInternal reportFullyDisplayed]; +} + ++ (void)pauseAppHangTracking +{ + [SentrySDKInternal pauseAppHangTracking]; +} + ++ (void)resumeAppHangTracking +{ + [SentrySDKInternal resumeAppHangTracking]; +} + ++ (void)flush:(NSTimeInterval)timeout +{ + [SentrySDKInternal flush:timeout]; +} + ++ (void)close +{ + [SentrySDKInternal close]; +} + +#if !(TARGET_OS_WATCH || TARGET_OS_TV || TARGET_OS_VISION) ++ (void)startProfiler +{ + [SentrySDKInternal startProfiler]; +} + ++ (void)stopProfiler +{ + [SentrySDKInternal stopProfiler]; +} +#endif + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjC/SentryUnit.m b/Sources/SentryObjC/SentryUnit.m new file mode 100644 index 00000000000..60d7307937c --- /dev/null +++ b/Sources/SentryObjC/SentryUnit.m @@ -0,0 +1,36 @@ +#import "SentryUnit.h" + +NS_ASSUME_NONNULL_BEGIN + +SentryUnitName const SentryUnitNameNanosecond = @"nanosecond"; +SentryUnitName const SentryUnitNameMicrosecond = @"microsecond"; +SentryUnitName const SentryUnitNameMillisecond = @"millisecond"; +SentryUnitName const SentryUnitNameSecond = @"second"; +SentryUnitName const SentryUnitNameMinute = @"minute"; +SentryUnitName const SentryUnitNameHour = @"hour"; +SentryUnitName const SentryUnitNameDay = @"day"; +SentryUnitName const SentryUnitNameWeek = @"week"; +SentryUnitName const SentryUnitNameBit = @"bit"; +SentryUnitName const SentryUnitNameByte = @"byte"; +SentryUnitName const SentryUnitNameKilobyte = @"kilobyte"; +SentryUnitName const SentryUnitNameKibibyte = @"kibibyte"; +SentryUnitName const SentryUnitNameMegabyte = @"megabyte"; +SentryUnitName const SentryUnitNameMebibyte = @"mebibyte"; +SentryUnitName const SentryUnitNameGigabyte = @"gigabyte"; +SentryUnitName const SentryUnitNameGibibyte = @"gibibyte"; +SentryUnitName const SentryUnitNameTerabyte = @"terabyte"; +SentryUnitName const SentryUnitNameTebibyte = @"tebibyte"; +SentryUnitName const SentryUnitNamePetabyte = @"petabyte"; +SentryUnitName const SentryUnitNamePebibyte = @"pebibyte"; +SentryUnitName const SentryUnitNameExabyte = @"exabyte"; +SentryUnitName const SentryUnitNameExbibyte = @"exbibyte"; +SentryUnitName const SentryUnitNameRatio = @"ratio"; +SentryUnitName const SentryUnitNamePercent = @"percent"; + +SentryUnitName +SentryUnitWithName(NSString *name) +{ + return [name copy]; +} + +NS_ASSUME_NONNULL_END diff --git a/Sources/SentryObjCBridge/SentryObjCBridge.swift b/Sources/SentryObjCBridge/SentryObjCBridge.swift new file mode 100644 index 00000000000..8407dcfe198 --- /dev/null +++ b/Sources/SentryObjCBridge/SentryObjCBridge.swift @@ -0,0 +1,111 @@ +@_implementationOnly import _SentryPrivate +import Foundation + +// Import the Sentry SDK module. +// SPM uses SentrySwift, Xcode uses Sentry. +#if SWIFT_PACKAGE +import SentrySwift +private typealias SDKAttributeContent = SentrySwift.SentryAttributeContent +#else +import Sentry +private typealias SDKAttributeContent = Sentry.SentryAttributeContent +#endif + +/// Bridge class that exposes Swift SDK functionality to pure Objective-C code. +/// +/// This class provides @objc methods that can be called from SentryObjC (pure ObjC, no modules) +/// and forwards them to the Swift SentrySDK implementation. +@objc(SentryObjCBridge) +public final class SentrySwiftBridge: NSObject { + + // MARK: - Metrics API + + /// Bridge for count metrics from ObjC to Swift + @objc public static func metricsCount( + key: String, + value: UInt, + attributes: [String: Any] + ) { + let bridgedAttributes = convertObjCAttributesToSwift(attributes) + SentrySDK.metrics.count(key: key, value: value, attributes: bridgedAttributes) + } + + /// Bridge for distribution metrics from ObjC to Swift + @objc public static func metricsDistribution( + key: String, + value: Double, + unit: String?, + attributes: [String: Any] + ) { + let bridgedAttributes = convertObjCAttributesToSwift(attributes) + let swiftUnit = unit.flatMap { SentryUnit(rawValue: $0) } + SentrySDK.metrics.distribution(key: key, value: value, unit: swiftUnit, attributes: bridgedAttributes) + } + + /// Bridge for gauge metrics from ObjC to Swift + @objc public static func metricsGauge( + key: String, + value: Double, + unit: String?, + attributes: [String: Any] + ) { + let bridgedAttributes = convertObjCAttributesToSwift(attributes) + let swiftUnit = unit.flatMap { SentryUnit(rawValue: $0) } + SentrySDK.metrics.gauge(key: key, value: value, unit: swiftUnit, attributes: bridgedAttributes) + } + + // MARK: - Logger API + + /// Bridge for logger access from ObjC to Swift + @objc public static var logger: AnyObject { + return SentrySDK.logger + } + + // MARK: - Replay API + + #if SENTRY_TARGET_REPLAY_SUPPORTED + /// Bridge for replay API access from ObjC to Swift + @objc public static var replay: AnyObject { + return SentrySDK.replay + } + #endif + + // MARK: - Private Helpers + + /// Convert ObjC attributes dictionary to Swift [String: SentryAttributeValue] + /// + /// This method extracts attribute values from SentryObjCAttributeContent instances + /// and converts them to their Swift SentryAttributeContent equivalents. + /// + /// Uses KVC to extract values from ObjC objects since we can't directly import + /// SentryObjC types here (would create circular dependency). + /// + /// Invalid attributes are silently skipped to maintain robustness. + private static func convertObjCAttributesToSwift(_ objcAttributes: [String: Any]) -> [String: SentryAttributeValue] { + objcAttributes.compactMapValues { value in + guard let attributeContent = value as? NSObject, + let typeValue = attributeContent.value(forKey: "type") as? Int, + let swiftValue = convertAttributeContent(attributeContent, typeValue: typeValue) + else { + return nil + } + return swiftValue + } + } + + /// Convert a single attribute content object to Swift SentryAttributeContent + /// Note: Uses SDKAttributeContent typealias to avoid ambiguity with SentryObjC's wrapper type + private static func convertAttributeContent(_ content: NSObject, typeValue: Int) -> SDKAttributeContent? { + switch typeValue { + case 0: return (content.value(forKey: "stringValue") as? String).map { .string($0) } + case 1: return (content.value(forKey: "booleanValue") as? Bool).map { .boolean($0) } + case 2: return (content.value(forKey: "integerValue") as? Int).map { .integer($0) } + case 3: return (content.value(forKey: "doubleValue") as? Double).map { .double($0) } + case 4: return (content.value(forKey: "stringArrayValue") as? [String]).map { .stringArray($0) } + case 5: return (content.value(forKey: "booleanArrayValue") as? [NSNumber]).map { .booleanArray($0.map { $0.boolValue }) } + case 6: return (content.value(forKey: "integerArrayValue") as? [NSNumber]).map { .integerArray($0.map { $0.intValue }) } + case 7: return (content.value(forKey: "doubleArrayValue") as? [NSNumber]).map { .doubleArray($0.map { $0.doubleValue }) } + default: return nil + } + } +} diff --git a/Sources/Swift/Core/Helper/Log/SentryLevel.swift b/Sources/Swift/Core/Helper/Log/SentryLevel.swift index c3b983ca795..1919509a787 100644 --- a/Sources/Swift/Core/Helper/Log/SentryLevel.swift +++ b/Sources/Swift/Core/Helper/Log/SentryLevel.swift @@ -3,7 +3,7 @@ import Foundation private let levelNames = ["none", "debug", "info", "warning", "error", "fatal"] -extension SentryLevel: CustomStringConvertible { +extension SentryLevel: CustomStringConvertible { public var description: String { return levelNames[Int(self.rawValue)] } diff --git a/Sources/Swift/Protocol/SentryAttributeContent.swift b/Sources/Swift/Protocol/SentryAttributeContent.swift index f9cf1f9a600..6cbd87862cc 100644 --- a/Sources/Swift/Protocol/SentryAttributeContent.swift +++ b/Sources/Swift/Protocol/SentryAttributeContent.swift @@ -223,4 +223,11 @@ extension SentryAttributeContent: ExpressibleByIntegerLiteral { self = .integer(value) } } + +extension SentryAttributeContent: SentryAttributeValue { + /// Returns self since `SentryAttributeContent` is already the canonical representation. + public var asSentryAttributeContent: SentryAttributeContent { + return self + } +} // swiftlint:enable missing_docs diff --git a/Tests/SentryTests/SentryObjCMetricsApiTests.m.wip b/Tests/SentryTests/SentryObjCMetricsApiTests.m.wip new file mode 100644 index 00000000000..ca7d0b0e13c --- /dev/null +++ b/Tests/SentryTests/SentryObjCMetricsApiTests.m.wip @@ -0,0 +1,174 @@ +#import "../../Sources/SentryObjC/Public/SentryObjC.h" +#import + +@interface SentryObjCMetricsApiTests : XCTestCase +@end + +@implementation SentryObjCMetricsApiTests + +- (void)setUp +{ + [super setUp]; + // SDK needs to be started for metrics to work + if (![SentrySDK isEnabled]) { + [SentrySDK startWithConfigureOptions:^(SentryOptions *options) { + options.dsn = @"https://username@sentry.io/1"; + options.enableMetrics = YES; + }]; + } +} + +- (void)tearDown +{ + [super tearDown]; + [SentrySDK close]; +} + +- (void)testMetricsApiReturnsNonNil +{ + id metrics = [SentrySDK metrics]; + XCTAssertNotNil(metrics); +} + +- (void)testCountWithKeyOnly +{ + // This should not crash - just verify the API works + [[SentrySDK metrics] countWithKey:@"test.counter"]; +} + +- (void)testCountWithValueOnly +{ + [[SentrySDK metrics] countWithKey:@"test.counter" value:5]; +} + +- (void)testCountWithAllParameters +{ + NSDictionary *attributes = @{ + @"screen" : [SentryObjCAttributeContent stringWithValue:@"home"], + @"success" : [SentryObjCAttributeContent booleanWithValue:YES] + }; + + [[SentrySDK metrics] countWithKey:@"button.click" value:1 attributes:attributes]; +} + +- (void)testDistributionWithValueOnly +{ + [[SentrySDK metrics] distributionWithKey:@"response.time" value:125.5]; +} + +- (void)testDistributionWithUnit +{ + [[SentrySDK metrics] distributionWithKey:@"response.time" + value:125.5 + unit:SentryUnitNameMillisecond]; +} + +- (void)testDistributionWithAllParameters +{ + NSDictionary *attributes = @{ + @"endpoint" : [SentryObjCAttributeContent stringWithValue:@"/api/data"], + @"cached" : [SentryObjCAttributeContent booleanWithValue:NO], + @"status" : [SentryObjCAttributeContent integerWithValue:200] + }; + + [[SentrySDK metrics] distributionWithKey:@"http.request.duration" + value:187.5 + unit:SentryUnitNameMillisecond + attributes:attributes]; +} + +- (void)testGaugeWithValueOnly +{ + [[SentrySDK metrics] gaugeWithKey:@"queue.depth" value:42]; +} + +- (void)testGaugeWithUnit +{ + [[SentrySDK metrics] gaugeWithKey:@"memory.usage" value:1024.0 unit:SentryUnitNameByte]; +} + +- (void)testGaugeWithAllParameters +{ + NSDictionary *attributes = @{ + @"queue" : [SentryObjCAttributeContent stringWithValue:@"upload"], + @"priority" : [SentryObjCAttributeContent integerWithValue:1] + }; + + [[SentrySDK metrics] gaugeWithKey:@"queue.depth" + value:42 + unit:SentryUnitWithName(@"items") + attributes:attributes]; +} + +- (void)testGaugeWithCustomUnit +{ + [[SentrySDK metrics] gaugeWithKey:@"custom.metric" + value:99.9 + unit:SentryUnitWithName(@"custom")]; +} + +- (void)testAttributeTypesConversion +{ + NSDictionary *attributes = @{ + @"string" : [SentryObjCAttributeContent stringWithValue:@"value"], + @"boolean" : [SentryObjCAttributeContent booleanWithValue:YES], + @"integer" : [SentryObjCAttributeContent integerWithValue:123], + @"double" : [SentryObjCAttributeContent doubleWithValue:45.67], + @"stringArray" : [SentryObjCAttributeContent stringArrayWithValue:@[ @"a", @"b" ]], + @"booleanArray" : [SentryObjCAttributeContent booleanArrayWithValue:@[ @YES, @NO ]], + @"integerArray" : [SentryObjCAttributeContent integerArrayWithValue:@[ @1, @2, @3 ]], + @"doubleArray" : [SentryObjCAttributeContent doubleArrayWithValue:@[ @1.1, @2.2 ]] + }; + + [[SentrySDK metrics] countWithKey:@"test.all.types" value:1 attributes:attributes]; +} + +- (void)testNilAttributesHandled +{ + [[SentrySDK metrics] countWithKey:@"test" value:1 attributes:nil]; + [[SentrySDK metrics] distributionWithKey:@"test" value:1.0 unit:nil attributes:nil]; + [[SentrySDK metrics] gaugeWithKey:@"test" value:1.0 unit:nil attributes:nil]; +} + +- (void)testEmptyAttributesHandled +{ + [[SentrySDK metrics] countWithKey:@"test" value:1 attributes:@{ }]; + [[SentrySDK metrics] distributionWithKey:@"test" value:1.0 unit:nil attributes:@{ }]; + [[SentrySDK metrics] gaugeWithKey:@"test" value:1.0 unit:nil attributes:@{ }]; +} + +- (void)testLoggerAccess +{ + SentryLogger *logger = [SentrySDK logger]; + XCTAssertNotNil(logger); +} + +- (void)testInvalidAttributeType_shouldSkipAttribute +{ + // Test that invalid attribute types are skipped gracefully + NSDictionary *attributes = @{ + @"valid" : [SentryObjCAttributeContent stringWithValue:@"test"], + @"invalid" : @"not an attribute content object" + }; + + // Should not crash - invalid attributes are logged and skipped + [[SentrySDK metrics] countWithKey:@"test.invalid" value:1 attributes:attributes]; +} + +- (void)testMetricsApiLazySingleton +{ + // Verify that metrics returns the same instance each time (singleton) + id metrics1 = [SentrySDK metrics]; + id metrics2 = [SentrySDK metrics]; + XCTAssertEqual(metrics1, metrics2); +} + +#if SENTRY_OBJC_REPLAY_SUPPORTED +- (void)testReplayApiReturnsNonNil +{ + SentryReplayApi *replay = [SentrySDK replay]; + XCTAssertNotNil(replay, @"Replay API should not return nil on supported platforms"); +} +#endif + +@end diff --git a/agents.toml b/agents.toml index e2e08b00986..90e4798756d 100644 --- a/agents.toml +++ b/agents.toml @@ -13,3 +13,47 @@ args = ["-y", "xcodebuildmcp@2.0.7", "mcp"] [[mcp]] name = "sentry" url = "https://mcp.sentry.dev/mcp/sentry-sdks/sentry-cocoa" + +[[skills]] +name = "brainstorming" +source = "obra/superpowers" + +[[skills]] +name = "dispatching-parallel-agents" +source = "obra/superpowers" + +[[skills]] +name = "executing-plans" +source = "obra/superpowers" + +[[skills]] +name = "finishing-a-development-branch" +source = "obra/superpowers" + +[[skills]] +name = "subagent-driven-development" +source = "obra/superpowers" + +[[skills]] +name = "systematic-debugging" +source = "obra/superpowers" + +[[skills]] +name = "test-driven-development" +source = "obra/superpowers" + +[[skills]] +name = "using-git-worktrees" +source = "obra/superpowers" + +[[skills]] +name = "using-superpowers" +source = "obra/superpowers" + +[[skills]] +name = "verification-before-completion" +source = "obra/superpowers" + +[[skills]] +name = "writing-plans" +source = "obra/superpowers" diff --git a/develop-docs/README.md b/develop-docs/README.md index 1cce7f66e9a..9afa9b57df1 100644 --- a/develop-docs/README.md +++ b/develop-docs/README.md @@ -3,6 +3,7 @@ This is a collection of documents that can help you develop for the SentrySDK. - ARCHITECTURE.md: the high-level concepts, features and organization of the codebase +- SENTRY-OBJC.md: the pure Objective-C wrapper for ObjC++ consumers without modules - SWIFT.md: how we handle the intricacies when mixing Swift and ObjC/++ - TEST.md: unit testing, UI testing and static/runtime analysis - BUILD.md: how we configure and build our SDK deliverables diff --git a/develop-docs/SENTRY-OBJC.md b/develop-docs/SENTRY-OBJC.md new file mode 100644 index 00000000000..9f47e07c306 --- /dev/null +++ b/develop-docs/SENTRY-OBJC.md @@ -0,0 +1,253 @@ +# SentryObjC Architecture + +SentryObjC is a pure Objective-C wrapper around the Sentry SDK, designed for consumers who cannot use Clang modules (e.g., ObjC++ projects with `-fmodules=NO`). + +## Problem + +Many projects cannot enable Clang modules: + +- **React Native** (≤0.76): AppDelegate is `.mm` (Objective-C++), modules disabled by default +- **Haxe**: Build toolchain conflicts with `-fmodules` / `-fcxx-modules` +- **Custom build systems**: May not support module imports + +With modules disabled: + +- `@import Sentry` does not work (requires modules) +- `#import ` exposes only ObjC headers, not Swift APIs +- `#import ` fails with forward declaration errors in `.mm` files + +**Result:** `SentrySDK`, `SentryOptions`, `options.sessionReplay` and other Swift-bridged APIs are unavailable from ObjC++ without modules. + +## Solution + +SentryObjC provides a three-tier architecture with two dependency paths: + +```mermaid +graph TD + subgraph SentryObjC["SentryObjC (Pure Objective-C)"] + Headers["Public headers: SentrySDK.h, SentryOptions.h, etc."] + Impl[".m implementation files"] + end + + subgraph Bridge["SentryObjCBridge (Swift)"] + BridgeMethods["@objc methods for:
metrics, logger, replay,
SentryAttributeContent"] + end + + subgraph SDK["Sentry SDK"] + ObjCTypes["SentrySDKInternal, SentryUser,
SentryOptions, SentryEvent,
SentryCrash, etc."] + end + + SentryObjC -->|"Swift-only APIs"| Bridge + SentryObjC -->|"ObjC-compatible APIs"| SDK + Bridge --> SDK +``` + +### Two Dependency Paths + +**Direct path (SentryObjC → Sentry):** For ObjC-compatible types already exposed in the SDK: + +- `SentrySDKInternal` (ObjC class wrapping the real `SentrySDK`) +- `SentryOptions`, `SentryUser`, `SentryEvent`, `SentryBreadcrumb`, etc. +- Any Swift class with `@objc` exposure + +**Bridge path (SentryObjC → SentryObjCBridge → Sentry):** For Swift-only APIs that need bridging: + +- `SentrySDK.metrics` (Swift protocol type) +- `SentrySDK.logger` (Swift Logger API) +- `SentrySDK.replay` (Swift Replay API) +- `SentryAttributeContent` (Swift enum with associated values) + +The bridge converts Swift-only constructs (protocols, enums with payloads, generics) into `@objc`-callable methods that pure ObjC can invoke. + +## Type Architecture + +SentryObjC defines its own types that mirror the main SDK: + +| SentryObjC Type | Wraps | +| ------------------ | ----------------------- | +| `SentrySDK` | Real `SentrySDK` | +| `SentryOptions` | Real `SentryOptions` | +| `SentryUser` | Real `SentryUser` | +| `SentryBreadcrumb` | Real `SentryBreadcrumb` | +| `SentryScope` | Real `SentryScope` | +| ... | ... | + +Each wrapper type: + +1. Is a complete `@interface` definition (pure ObjC, no Swift imports) +2. Holds an internal reference to the real SDK type +3. Exposes the same properties/methods +4. Calls the real SDK directly for ObjC-compatible APIs +5. Uses `SentryObjCBridge` only for Swift-only APIs (metrics, logger, replay) + +## Source Layout + +``` +Sources/ +├── SentryObjC/ +│ ├── Public/ +│ │ ├── SentryObjC.h # Umbrella header +│ │ ├── SentrySDK.h # @interface SentrySDK +│ │ ├── SentryOptions.h # @interface SentryOptions +│ │ ├── SentryUser.h # @interface SentryUser +│ │ └── ... # All public types +│ ├── SentrySDK.m # Implementation +│ ├── SentryOptions.m +│ └── ... +├── SentryObjCBridge/ +│ └── SentryObjCBridge.swift # @objc bridge methods +``` + +## Xcode Project Structure + +Three framework targets in `Sentry.xcodeproj`: + +| Target | Type | Sources | Dependencies | +| ------------------ | --------- | -------------------------------- | -------------------------------------------- | +| `Sentry` | Framework | `Sources/Sentry/`, `Swift/`, etc | System frameworks | +| `SentryObjCBridge` | Framework | `Sources/SentryObjCBridge/` | Sentry.framework | +| `SentryObjC` | Framework | `Sources/SentryObjC/` | SentryObjCBridge.framework, Sentry.framework | + +This mirrors the SPM target structure exactly. + +## Distribution + +### SPM + +The `SentryObjC` product in `Package.swift` includes all three tiers: + +```swift +.library(name: "SentryObjC", targets: ["SentryObjCInternal", "SentryObjCBridge", "SentryObjC"]) +``` + +### XCFramework + +`SentryObjC.xcframework` bundles everything into a single standalone dynamic framework: + +1. Build `Sentry`, `SentryObjCBridge`, and `SentryObjC` as static libraries using `xcodebuild` +2. Merge all three `.a` archives into one with `libtool -static` +3. Link with `swiftc -emit-library -force_load` into a dynamic library (swiftc embeds the Swift runtime automatically) +4. Copy SentryObjC public headers and module map into the framework bundle +5. Assemble per-platform slices into a single `.xcframework` + +Properties: + +- All platforms: iOS, macOS, Catalyst, tvOS, watchOS, visionOS +- Pure ObjC public headers (no `Sentry-Swift.h`) +- Single binary containing wrapper + bridge + full SDK + Swift runtime + +#### XCFramework Structure + +``` +SentryObjC.xcframework/ +├── Info.plist +├── ios-arm64/ +│ └── SentryObjC.framework/ +│ ├── SentryObjC (binary) +│ ├── Info.plist +│ ├── Headers/ +│ │ ├── SentryObjC.h (umbrella) +│ │ ├── SentrySDK.h +│ │ ├── SentryOptions.h +│ │ └── ... (pure ObjC headers) +│ └── Modules/ +│ └── module.modulemap +├── ios-arm64_x86_64-simulator/ +├── ios-arm64_x86_64-maccatalyst/ +├── macos-arm64_x86_64/ +├── tvos-arm64/ +├── tvos-arm64_x86_64-simulator/ +├── watchos-arm64_arm64_32_armv7k/ +├── watchos-arm64_x86_64-simulator/ +├── xros-arm64/ +└── xros-arm64_x86_64-simulator/ +``` + +#### Module Map + +``` +framework module SentryObjC { + umbrella header "SentryObjC.h" + export * + module * { export * } +} +``` + +No Swift module exposed - pure ObjC only. + +## Usage + +```objc +// In .mm file with CLANG_ENABLE_MODULES=NO +#import + +[SentrySDK startWithConfigureOptions:^(SentryOptions *options) { + options.dsn = @"https://..."; + options.debug = YES; + options.tracesSampleRate = @1.0; + + // Swift APIs work! + options.sessionReplay.sessionSampleRate = 0; + options.sessionReplay.onErrorSampleRate = 1; +}]; +``` + +## Building + +```bash +# Build for iOS simulator (development) +make build-sentryobjc + +# Build full xcframework (all platforms) +make build-sentryobjc-xcframework + +# Test SPM build +make build-sample-iOS-ObjectiveCpp-NoModules +``` + +### Build Scripts + +``` +scripts/build-xcframework-local.sh (SentryObjCOnly variant) + ├── build-xcframework-variant.sh → Sentry (staticlib, reused from StaticOnly) + ├── build-xcframework-variant.sh → SentryObjCBridge (staticlib) + ├── build-xcframework-variant.sh → SentryObjC (staticlib) + └── build-xcframework-sentryobjc-standalone.sh + ├── libtool -static (merge all three) + ├── swiftc -emit-library -force_load (link per arch) + ├── lipo -create (merge archs) + └── assemble-xcframework.sh +``` + +## Design Decisions + +### Why same type names? + +Using `SentryOptions` instead of `SentryObjCOptions` provides a familiar API for developers. Since `SentryObjC.xcframework` is standalone (doesn't link against `Sentry.xcframework`), there's no symbol collision. + +### Why not just fix the Swift headers? + +The `Sentry-Swift.h` generated header has inherent issues when included from ObjC++ without modules. Forward declarations for UIKit types (`UIView`, `UIWindowLevel`) fail. This is a limitation of the Swift-to-ObjC bridging, not something we can easily fix. + +### Why embed the full SDK? + +Embedding the full SDK in `SentryObjC.xcframework` (vs. depending on `Sentry.xcframework`) provides: + +- Single framework to link +- No transitive dependency management +- No risk of version mismatches + +### Why three Xcode targets? + +Having `SentryObjCBridge` as a separate framework target (not compiled into `SentryObjC`) avoids module conflicts. When Swift code is in `SentryObjC` target, it can see both the `SentryObjC` module and `Sentry` module definitions of the same types, causing compilation errors. + +## Out of Scope + +- SentrySwiftUI support (requires Swift/SwiftUI) +- Hybrid SDK bridges (React Native, Flutter use their own wrappers) + +## Related + +- [Issue #6342](https://github.com/getsentry/sentry-cocoa/issues/6342) - Original feature request +- [Issue #4543](https://github.com/getsentry/sentry-cocoa/issues/4543) - Problem documentation +- `Samples/iOS-ObjectiveCpp-NoModules/` - Sample app demonstrating usage diff --git a/scripts/build-xcframework-local.sh b/scripts/build-xcframework-local.sh index 78be88acb00..16b79d32d19 100755 --- a/scripts/build-xcframework-local.sh +++ b/scripts/build-xcframework-local.sh @@ -50,3 +50,38 @@ if [ "$variants" = "WithoutUIKitWithARM64eOnly" ] || [ "$variants" = "AllVariant ./scripts/compress-xcframework.sh "$signed" Sentry-WithoutUIKitOrAppKit-WithARM64e mv Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework.zip XCFrameworkBuildPath/Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework.zip fi + +if [ "$variants" = "SentryObjCOnly" ] || [ "$variants" = "AllVariants" ]; then + # Build a standalone SentryObjC.xcframework that embeds the full SDK. + # + # Strategy: build Sentry, SentryObjCBridge, and SentryObjC as static + # frameworks, merge them with libtool, then link into a dynamic library + # with swiftc. This produces a single binary containing wrapper + bridge + # + full SDK + Swift runtime. + # + # The Sentry static framework is already built by StaticOnly above + # (or will be built here if running SentryObjCOnly alone). We reuse + # those archives from XCFrameworkBuildPath/archive/Sentry/. + + # 1. Build Sentry as a static framework if not already built + if [ ! -d "XCFrameworkBuildPath/archive/Sentry" ]; then + ./scripts/build-xcframework-variant.sh "Sentry" "" "staticlib" "" "$sdks" "" + fi + + # 2. Build SentryObjCBridge as a static framework + ./scripts/build-xcframework-variant.sh "SentryObjCBridge" "" "staticlib" "" "$sdks" "" + + # 3. Build SentryObjC as a static framework + ./scripts/build-xcframework-variant.sh "SentryObjC" "" "staticlib" "" "$sdks" "" + + # 4. Link all three static archives into a standalone dynamic SentryObjC framework + ./scripts/build-xcframework-sentryobjc-standalone.sh "$sdks" + + ./scripts/validate-xcframework-format.sh "SentryObjC.xcframework" + ./scripts/compress-xcframework.sh "$signed" SentryObjC + mv SentryObjC.xcframework.zip XCFrameworkBuildPath/SentryObjC.xcframework.zip + + # Clean up intermediate static builds (keep Sentry/ — shared with StaticOnly) + rm -rf "XCFrameworkBuildPath/archive/SentryObjCBridge" + rm -rf "XCFrameworkBuildPath/archive/SentryObjC" +fi diff --git a/scripts/build-xcframework-sentryobjc-standalone.sh b/scripts/build-xcframework-sentryobjc-standalone.sh new file mode 100755 index 00000000000..7fff86af384 --- /dev/null +++ b/scripts/build-xcframework-sentryobjc-standalone.sh @@ -0,0 +1,204 @@ +#!/bin/bash +# +# Links three pre-built static archives (Sentry, SentryObjCBridge, SentryObjC) +# into a standalone dynamic SentryObjC.framework for each SDK slice, then +# assembles them into an XCFramework. +# +# Strategy: +# 1. Merge all three .a files with libtool +# 2. Link into a dynamic library with swiftc (handles Swift runtime automatically) +# 3. Copy SentryObjC public headers + module map +# 4. Assemble into XCFramework +# +# Parameters: +# $1 - sdks_to_build (comma-separated list or preset: AllSDKs, iOSOnly, etc.) + +set -eoux pipefail + +sdks_to_build="${1:-AllSDKs}" + +if [ "$sdks_to_build" = "iOSOnly" ]; then + sdks=( iphoneos iphonesimulator ) +elif [ "$sdks_to_build" = "macOSOnly" ]; then + sdks=( macosx ) +elif [ "$sdks_to_build" = "macCatalystOnly" ]; then + sdks=( maccatalyst ) +elif [ "$sdks_to_build" = "AllSDKs" ]; then + sdks=( iphoneos iphonesimulator macosx maccatalyst appletvos appletvsimulator watchos watchsimulator xros xrsimulator ) +else + # Treat as comma-separated list (e.g. from CI) + IFS=',' read -r -a sdks <<< "$sdks_to_build" +fi + +ARCHIVE_BASE="$(pwd)/XCFrameworkBuildPath/archive" +OUTPUT_BASE="$(pwd)/XCFrameworkBuildPath/archive/SentryObjC-Standalone" + +# System libraries required for all platforms. +SYSTEM_LIBS=( z c++ ) + +# All candidate frameworks the Sentry SDK may link against. +# The script checks which ones actually exist on each platform's SDK +# and skips the rest, so this list is safe for all platforms. +REQUIRED_FRAMEWORKS=( Foundation CoreData SystemConfiguration CoreGraphics QuartzCore ) +CANDIDATE_WEAK_FRAMEWORKS=( AVFoundation CoreMedia CoreVideo MetricKit PDFKit SwiftUI UIKit WebKit AppKit ) + +for sdk in "${sdks[@]}"; do + echo "=== Linking standalone SentryObjC for ${sdk} ===" + + # Locate the three static archives (reuses the normal Sentry static build) + sentry_archive="${ARCHIVE_BASE}/Sentry/${sdk}.xcarchive/Products/Library/Frameworks/Sentry.framework" + bridge_archive="${ARCHIVE_BASE}/SentryObjCBridge/${sdk}.xcarchive/Products/Library/Frameworks/SentryObjCBridge.framework" + objc_archive="${ARCHIVE_BASE}/SentryObjC/${sdk}.xcarchive/Products/Library/Frameworks/SentryObjC.framework" + + # Get the actual binary paths (macOS uses Versions/A structure) + if [ "$sdk" = "macosx" ] || [ "$sdk" = "maccatalyst" ]; then + sentry_a="${sentry_archive}/Versions/A/Sentry" + bridge_a="${bridge_archive}/Versions/A/SentryObjCBridge" + objc_a="${objc_archive}/Versions/A/SentryObjC" + else + sentry_a="${sentry_archive}/Sentry" + bridge_a="${bridge_archive}/SentryObjCBridge" + objc_a="${objc_archive}/SentryObjC" + fi + + for lib in "$sentry_a" "$bridge_a" "$objc_a"; do + if [ ! -f "$lib" ]; then + echo "ERROR: Static library not found at: $lib" + exit 1 + fi + echo " Found: $lib ($(du -h "$lib" | cut -f1))" + done + + # Merge into one static archive + combined_a="/tmp/SentryObjC_combined_${sdk}.a" + libtool -static "$sentry_a" "$bridge_a" "$objc_a" -o "$combined_a" + echo " Combined: $(du -h "$combined_a" | cut -f1)" + + # Determine target triple(s) per architecture + sysroot="$(xcrun --sdk "${sdk}" --show-sdk-path 2>/dev/null || xcrun --sdk iphoneos --show-sdk-path)" + case "$sdk" in + iphoneos) arch_targets=( "arm64-apple-ios15.0" ) ;; + iphonesimulator) arch_targets=( "arm64-apple-ios15.0-simulator" "x86_64-apple-ios15.0-simulator" ) ;; + macosx) arch_targets=( "arm64-apple-macos10.14" "x86_64-apple-macos10.14" ) ;; + maccatalyst) arch_targets=( "arm64-apple-ios15.0-macabi" "x86_64-apple-ios15.0-macabi" ) + sysroot="$(xcrun --sdk macosx --show-sdk-path)" ;; + appletvos) arch_targets=( "arm64-apple-tvos15.0" ) ;; + appletvsimulator) arch_targets=( "arm64-apple-tvos15.0-simulator" "x86_64-apple-tvos15.0-simulator" ) ;; + watchos) arch_targets=( "arm64-apple-watchos8.0" "arm64_32-apple-watchos8.0" ) ;; + watchsimulator) arch_targets=( "arm64-apple-watchos8.0-simulator" "x86_64-apple-watchos8.0-simulator" ) ;; + xros) arch_targets=( "arm64-apple-xros1.0" ) ;; + xrsimulator) arch_targets=( "arm64-apple-xros1.0-simulator" ) ;; + esac + + # Discover which weak frameworks are available on this SDK. + # This avoids hardcoding per-platform lists — frameworks that don't exist + # on a given platform (e.g., WebKit on watchOS) are simply skipped. + fw_search_path="${sysroot}/System/Library/Frameworks" + if [ "$sdk" = "maccatalyst" ]; then + catalyst_fw_path="${sysroot}/System/iOSSupport/System/Library/Frameworks" + fi + + WEAK_FRAMEWORKS=() + for fw in "${CANDIDATE_WEAK_FRAMEWORKS[@]}"; do + if [ -d "${fw_search_path}/${fw}.framework" ]; then + WEAK_FRAMEWORKS+=( "$fw" ) + elif [ "$sdk" = "maccatalyst" ] && [ -d "${catalyst_fw_path}/${fw}.framework" ]; then + WEAK_FRAMEWORKS+=( "$fw" ) + fi + done + echo " Weak frameworks for ${sdk}: ${WEAK_FRAMEWORKS[*]}" + + # Prepare output framework directory + output_xcarchive="${OUTPUT_BASE}/${sdk}.xcarchive" + output_fw_dir="${output_xcarchive}/Products/Library/Frameworks/SentryObjC.framework" + + if [ "$sdk" = "macosx" ] || [ "$sdk" = "maccatalyst" ]; then + output_fw_binary_dir="${output_fw_dir}/Versions/A" + mkdir -p "${output_fw_binary_dir}" + else + output_fw_binary_dir="${output_fw_dir}" + mkdir -p "${output_fw_dir}" + fi + + # Build linker flags (same for all archs) + linker_flags=() + linker_flags+=( -Xlinker -install_name -Xlinker "@rpath/SentryObjC.framework/SentryObjC" ) + linker_flags+=( -Xlinker -rpath -Xlinker "@executable_path/Frameworks" ) + linker_flags+=( -Xlinker -force_load -Xlinker "$combined_a" ) + linker_flags+=( -Xlinker -compatibility_version -Xlinker 1.0.0 ) + linker_flags+=( -Xlinker -current_version -Xlinker 1.0.0 ) + # Mac Catalyst needs the iOSSupport framework path for UIKit + if [ "$sdk" = "maccatalyst" ]; then + linker_flags+=( -Xlinker -F -Xlinker "${catalyst_fw_path}" ) + fi + for fw in "${REQUIRED_FRAMEWORKS[@]}"; do + linker_flags+=( -framework "$fw" ) + done + for fw in "${WEAK_FRAMEWORKS[@]}"; do + linker_flags+=( -Xlinker -weak_framework -Xlinker "$fw" ) + done + for lib in "${SYSTEM_LIBS[@]}"; do + linker_flags+=( -l"$lib" ) + done + + # Link each architecture separately, then merge with lipo + # swiftc needs a dummy .swift input but handles Swift runtime automatically + dummy_swift="/tmp/SentryObjC_dummy.swift" + echo "" > "$dummy_swift" + + arch_binaries=() + for target in "${arch_targets[@]}"; do + arch="${target%%-*}" + echo " Linking arch: $arch ($target)" + + arch_output="/tmp/SentryObjC_${sdk}_${arch}" + xcrun swiftc \ + "$dummy_swift" \ + -emit-library \ + -target "$target" \ + -sdk "$sysroot" \ + "${linker_flags[@]}" \ + -o "$arch_output" 2>&1 || { + echo "ERROR: Failed to link arch $arch for $sdk" + exit 1 + } + arch_binaries+=("$arch_output") + done + + # Merge architectures with lipo if multiple + if [ "${#arch_binaries[@]}" -gt 1 ]; then + xcrun lipo -create "${arch_binaries[@]}" -output "${output_fw_binary_dir}/SentryObjC" + else + cp "${arch_binaries[0]}" "${output_fw_binary_dir}/SentryObjC" + fi + + echo " Final binary: $(du -h "${output_fw_binary_dir}/SentryObjC" | cut -f1)" + + # Copy headers and module map from the SentryObjC static build + if [ "$sdk" = "macosx" ] || [ "$sdk" = "maccatalyst" ]; then + cp -R "${objc_archive}/Versions/A/Headers" "${output_fw_binary_dir}/Headers" + cp -R "${objc_archive}/Versions/A/Modules" "${output_fw_binary_dir}/Modules" + mkdir -p "${output_fw_binary_dir}/Resources" + cp "${objc_archive}/Versions/A/Resources/Info.plist" "${output_fw_binary_dir}/Resources/Info.plist" 2>/dev/null || \ + cp "${objc_archive}/Resources/Info.plist" "${output_fw_binary_dir}/Resources/Info.plist" 2>/dev/null || true + # Create standard macOS framework symlinks + ln -sfh A "${output_fw_dir}/Versions/Current" + ln -sfh Versions/Current/Headers "${output_fw_dir}/Headers" + ln -sfh Versions/Current/Modules "${output_fw_dir}/Modules" + ln -sfh Versions/Current/SentryObjC "${output_fw_dir}/SentryObjC" + else + cp -R "${objc_archive}/Headers" "${output_fw_dir}/Headers" + cp -R "${objc_archive}/Modules" "${output_fw_dir}/Modules" + cp "${objc_archive}/Info.plist" "${output_fw_dir}/Info.plist" 2>/dev/null || true + fi + + # Clean up temp files + rm -f "$combined_a" "$dummy_swift" + rm -f /tmp/SentryObjC_"${sdk}"_* + + echo "=== Done: ${sdk} ===" +done + +# Assemble the XCFramework from all slices +xcframework_sdks="$(IFS=,; echo "${sdks[*]}")" +./scripts/assemble-xcframework.sh "SentryObjC" "" "" "$xcframework_sdks" "$(pwd)/XCFrameworkBuildPath/archive/SentryObjC-Standalone/SDK_NAME.xcarchive" diff --git a/scripts/build-xcframework-slice.sh b/scripts/build-xcframework-slice.sh index a11f2b1ddde..6c3a5a18f69 100755 --- a/scripts/build-xcframework-slice.sh +++ b/scripts/build-xcframework-slice.sh @@ -1,7 +1,14 @@ #!/bin/bash # # Builds a single slice of the SDK to be packaged into an XCFramework - +# +# Parameters: +# $1 - sdk (e.g., iphoneos, iphonesimulator, macosx) +# $2 - scheme (e.g., Sentry, SentryObjC) +# $3 - suffix (optional, e.g., -Dynamic) +# $4 - MACH_O_TYPE (mh_dylib or staticlib) +# $5 - configuration_suffix (optional) +# $6 - use_workspace (optional, set to "workspace" to use Sentry.xcworkspace instead of Sentry.xcodeproj) set -eoux pipefail sdk="${1:-}" @@ -9,11 +16,22 @@ scheme="$2" suffix="${3:-}" MACH_O_TYPE="${4-mh_dylib}" configuration_suffix="${5-}" +use_workspace="${6:-}" resolved_configuration="Release$configuration_suffix" resolved_product_name="$scheme$configuration_suffix.framework" OTHER_LDFLAGS="" +# Determine project/workspace source +if [ "$use_workspace" = "workspace" ]; then + BUILD_SOURCE="-workspace Sentry.xcworkspace" + # SPM targets need library evolution for distribution + EXTRA_BUILD_SETTINGS="BUILD_LIBRARY_FOR_DISTRIBUTION=YES" +else + BUILD_SOURCE="-project Sentry.xcodeproj/" + EXTRA_BUILD_SETTINGS="" +fi + GCC_GENERATE_DEBUGGING_SYMBOLS="YES" if [ "$MACH_O_TYPE" = "staticlib" ]; then #For static framework we disabled symbols because they are not distributed in the framework causing warnings. @@ -23,10 +41,9 @@ fi rm -rf XCFrameworkBuildPath/DerivedData ## watchos and watchsimulator don't support make_mergeable: ld: unknown option: -make_mergeable -if [[ "$sdk" == "watchos" || "$sdk" == "watchsimulator" ]]; then - OTHER_LDFLAGS="" -elif [ "$MACH_O_TYPE" != "staticlib" ]; then - OTHER_LDFLAGS="-Wl,-make_mergeable" +## For other dynamic frameworks, add -make_mergeable (append to existing flags) +if [[ "$sdk" != "watchos" && "$sdk" != "watchsimulator" ]] && [ "$MACH_O_TYPE" != "staticlib" ]; then + OTHER_LDFLAGS="$OTHER_LDFLAGS -Wl,-make_mergeable" fi slice_id="${scheme}${suffix}-${sdk}" @@ -36,8 +53,9 @@ sentry_xcarchive_path="$output_xcarchive_path/${sdk}.xcarchive" if [ "$sdk" = "maccatalyst" ]; then # we can't use the "archive" action here because it doesn't support the -destination option, which we need to build the maccatalyst slice. so we'll have to build it manually and then copy the build product to an xcarchive directory we create. + # shellcheck disable=SC2086 set -o pipefail && NSUnbufferedIO=YES xcodebuild \ - -project Sentry.xcodeproj/ \ + $BUILD_SOURCE \ -scheme "$scheme" \ -configuration "$resolved_configuration" \ -sdk iphoneos \ @@ -49,7 +67,8 @@ if [ "$sdk" = "maccatalyst" ]; then SUPPORTS_MACCATALYST=YES \ ENABLE_CODE_COVERAGE=NO \ GCC_GENERATE_DEBUGGING_SYMBOLS="$GCC_GENERATE_DEBUGGING_SYMBOLS" \ - OTHER_LDFLAGS="$OTHER_LDFLAGS" 2>&1 | tee "${slice_id}.maccatalyst.log" | xcbeautify + OTHER_LDFLAGS="$OTHER_LDFLAGS" \ + $EXTRA_BUILD_SETTINGS 2>&1 | tee "${slice_id}.maccatalyst.log" | xcbeautify maccatalyst_build_product_directory="XCFrameworkBuildPath/DerivedData/Build/Products/$resolved_configuration-maccatalyst" @@ -63,8 +82,9 @@ if [ "$sdk" = "maccatalyst" ]; then cp -R "${maccatalyst_build_product_directory}/${resolved_product_name}.dSYM" "${maccatalyst_archive_dsym_destination}" fi else + # shellcheck disable=SC2086 set -o pipefail && NSUnbufferedIO=YES xcodebuild archive \ - -project Sentry.xcodeproj/ \ + $BUILD_SOURCE \ -scheme "$scheme" \ -configuration "$resolved_configuration" \ -sdk "$sdk" \ @@ -75,7 +95,8 @@ else MACH_O_TYPE="$MACH_O_TYPE" \ ENABLE_CODE_COVERAGE=NO \ GCC_GENERATE_DEBUGGING_SYMBOLS="$GCC_GENERATE_DEBUGGING_SYMBOLS" \ - OTHER_LDFLAGS="$OTHER_LDFLAGS" 2>&1 | tee "${slice_id}.log" | xcbeautify + OTHER_LDFLAGS="$OTHER_LDFLAGS" \ + $EXTRA_BUILD_SETTINGS 2>&1 | tee "${slice_id}.log" | xcbeautify fi if [ "$MACH_O_TYPE" = "staticlib" ]; then diff --git a/scripts/build-xcframework-variant.sh b/scripts/build-xcframework-variant.sh index 4526f99af33..4ac36bdffc3 100755 --- a/scripts/build-xcframework-variant.sh +++ b/scripts/build-xcframework-variant.sh @@ -1,5 +1,15 @@ #!/bin/bash - +# +# Builds all slices for an XCFramework variant +# +# Parameters: +# $1 - scheme (e.g., Sentry, SentryObjC) +# $2 - suffix (optional, e.g., -Dynamic) +# $3 - MACH_O_TYPE (mh_dylib or staticlib) +# $4 - configuration_suffix (optional) +# $5 - sdks_to_build (AllSDKs, iOSOnly, macOSOnly, macCatalystOnly) +# $6 - excluded_archs (optional) +# $7 - use_workspace (optional, set to "workspace" to use Sentry.xcworkspace) set -eoux pipefail scheme="$1" @@ -8,6 +18,7 @@ MACH_O_TYPE="${3-mh_dylib}" configuration_suffix="${4-}" sdks_to_build="${5:-}" excluded_archs="${6:-}" +use_workspace="${7:-}" if [ "$sdks_to_build" = "iOSOnly" ]; then sdks=( iphoneos iphonesimulator ) @@ -20,7 +31,7 @@ else fi for sdk in "${sdks[@]}"; do - ./scripts/build-xcframework-slice.sh "$sdk" "$scheme" "$suffix" "$MACH_O_TYPE" "$configuration_suffix" + ./scripts/build-xcframework-slice.sh "$sdk" "$scheme" "$suffix" "$MACH_O_TYPE" "$configuration_suffix" "$use_workspace" done if [ -n "$excluded_archs" ]; then diff --git a/scripts/extract-objc-api.sh b/scripts/extract-objc-api.sh new file mode 100755 index 00000000000..7ff341962a7 --- /dev/null +++ b/scripts/extract-objc-api.sh @@ -0,0 +1,118 @@ +#!/bin/bash +set -euo pipefail + +# Extract public API declarations from SentryObjC headers for stability tracking. +# +# Uses clang AST parsing to reliably extract Objective-C declarations. +# Outputs a sorted JSON array of declaration objects. Used by update-api.sh +# to generate sdk_api_objc.json. Changes to the output indicate API changes. + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +HEADERS_DIR="$PROJECT_ROOT/Sources/SentryObjC/Public" +UMBRELLA_HEADER="$HEADERS_DIR/SentryObjC.h" + +# Temporary files +TMP_DIR=$(mktemp -d) +trap 'rm -rf "$TMP_DIR"' EXIT + +AST_JSON="$TMP_DIR/ast.json" +INTERFACES_JSON="$TMP_DIR/interfaces.json" +PROTOCOLS_JSON="$TMP_DIR/protocols.json" +METHODS_JSON="$TMP_DIR/methods.json" +PROPERTIES_JSON="$TMP_DIR/properties.json" +TYPEDEFS_JSON="$TMP_DIR/typedefs.json" + +# Get iOS SDK path +SDK_PATH=$(xcrun --sdk iphoneos --show-sdk-path) + +# Step 1: Generate AST dump from umbrella header +xcrun clang -x objective-c \ + -Xclang -ast-dump=json \ + -fsyntax-only \ + -isysroot "$SDK_PATH" \ + -I "$HEADERS_DIR" \ + "$UMBRELLA_HEADER" \ + 2>/dev/null > "$AST_JSON" + +# Step 2: Extract interfaces +jq ' + [.. | objects | + select(.kind == "ObjCInterfaceDecl") | + select(.loc.file? // "" | contains("SentryObjC")) | + { + kind, + name, + file: (.loc.file | split("/") | last), + super: .super.name?, + has_inner: (if .inner then true else false end) + }] +' "$AST_JSON" > "$INTERFACES_JSON" + +# Step 3: Extract protocols +jq ' + [.. | objects | + select(.kind == "ObjCProtocolDecl") | + select(.loc.file? // "" | contains("SentryObjC")) | + { + kind, + name, + file: (.loc.file | split("/") | last) + }] +' "$AST_JSON" > "$PROTOCOLS_JSON" + +# Step 4: Extract methods (from interfaces) +jq ' + [.. | objects | + select(.kind == "ObjCInterfaceDecl") | + select(.loc.file? // "" | contains("SentryObjC")) | + select(.inner) | + . as $interface | + .inner[] | + select(.kind == "ObjCMethodDecl") | + { + kind, + name, + file: ($interface.loc.file | split("/") | last), + returnType: .returnType.qualType?, + instance: .instance? + }] +' "$AST_JSON" > "$METHODS_JSON" + +# Step 5: Extract properties (from interfaces) +jq ' + [.. | objects | + select(.kind == "ObjCInterfaceDecl") | + select(.loc.file? // "" | contains("SentryObjC")) | + select(.inner) | + . as $interface | + .inner[] | + select(.kind == "ObjCPropertyDecl") | + { + kind, + name, + file: ($interface.loc.file | split("/") | last), + type: .type.qualType? + }] +' "$AST_JSON" > "$PROPERTIES_JSON" + +# Step 6: Extract typedefs +jq ' + [.. | objects | + select(.kind == "TypedefDecl") | + select(.loc.file? // "" | contains("SentryObjC")) | + { + kind, + name, + file: (.loc.file | split("/") | last), + type: .type.qualType? + }] +' "$AST_JSON" > "$TYPEDEFS_JSON" + +# Step 7: Combine all declarations and output +jq -s 'add | sort_by(.file, .kind, .name)' \ + "$INTERFACES_JSON" \ + "$PROTOCOLS_JSON" \ + "$METHODS_JSON" \ + "$PROPERTIES_JSON" \ + "$TYPEDEFS_JSON" diff --git a/scripts/generate_release_matrix.sh b/scripts/generate_release_matrix.sh index 46dddf95bdc..996d1e9b310 100755 --- a/scripts/generate_release_matrix.sh +++ b/scripts/generate_release_matrix.sh @@ -10,7 +10,9 @@ BASE_SLICES_JSON='[ {"name": "Sentry", "macho-type": "mh_dylib", "suffix": "-Dynamic", "id": "sentry-dynamic"}, {"name": "Sentry", "macho-type": "staticlib", "id": "sentry-static"}, {"name": "SentrySwiftUI", "macho-type": "mh_dylib", "id": "sentry-swiftui"}, - {"name": "Sentry", "macho-type": "mh_dylib", "suffix": "-WithoutUIKitOrAppKit", "configuration-suffix": "WithoutUIKit", "id": "sentry-withoutuikit-dynamic"} + {"name": "Sentry", "macho-type": "mh_dylib", "suffix": "-WithoutUIKitOrAppKit", "configuration-suffix": "WithoutUIKit", "id": "sentry-withoutuikit-dynamic"}, + {"name": "SentryObjCBridge", "macho-type": "staticlib", "id": "sentryobjc-bridge"}, + {"name": "SentryObjC", "macho-type": "staticlib", "id": "sentryobjc-objc"} ]' BASE_VARIANTS_JSON='[ {"scheme": "Sentry", "macho-type": "mh_dylib", "suffix": "-Dynamic", "id": "sentry-dynamic", "excluded-archs": "arm64e"}, diff --git a/scripts/update-api.sh b/scripts/update-api.sh index 0796fef1968..6ce9dfc9111 100755 --- a/scripts/update-api.sh +++ b/scripts/update-api.sh @@ -105,3 +105,9 @@ xcrun --sdk iphoneos swift-api-digester \ log_notice "Sorting JSON keys and arrays for stable output" jq -S 'walk(if type == "array" then sort_by(tostring) else . end)' sdk_api_sentryswiftui.json > sdk_api_sentryswiftui.json.tmp && mv sdk_api_sentryswiftui.json.tmp sdk_api_sentryswiftui.json end_group + +begin_group "Extract SentryObjC Public API" +log_notice "Extracting SentryObjC public API from headers" +"$(dirname "$0")/extract-objc-api.sh" > sdk_api_objc.json +log_notice "SentryObjC API written to sdk_api_objc.json" +end_group diff --git a/sdk_api.json b/sdk_api.json index 7d7b65d11f3..93bc733f5d3 100644 --- a/sdk_api.json +++ b/sdk_api.json @@ -33521,6 +33521,45 @@ "printedName": "UnicodeScalarLiteralType", "usr": "s:6Sentry0A16AttributeContentO24UnicodeScalarLiteralTypea" }, + { + "accessors": [ + { + "accessorKind": "get", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryAttributeContent", + "printedName": "Sentry.SentryAttributeContent", + "usr": "s:6Sentry0A16AttributeContentO" + } + ], + "declKind": "Accessor", + "isFromExtension": true, + "kind": "Accessor", + "mangledName": "$s6Sentry0A16AttributeContentO02asabC0ACvg", + "moduleName": "Sentry", + "name": "Get", + "printedName": "Get()", + "usr": "s:6Sentry0A16AttributeContentO02asabC0ACvg" + } + ], + "children": [ + { + "kind": "TypeNominal", + "name": "SentryAttributeContent", + "printedName": "Sentry.SentryAttributeContent", + "usr": "s:6Sentry0A16AttributeContentO" + } + ], + "declKind": "Var", + "isFromExtension": true, + "kind": "Var", + "mangledName": "$s6Sentry0A16AttributeContentO02asabC0ACvp", + "moduleName": "Sentry", + "name": "asSentryAttributeContent", + "printedName": "asSentryAttributeContent", + "usr": "s:6Sentry0A16AttributeContentO02asabC0ACvp" + }, { "children": [ { @@ -34242,6 +34281,13 @@ "name": "Hashable", "printedName": "Hashable", "usr": "s:SH" + }, + { + "kind": "Conformance", + "mangledName": "$s6Sentry0A14AttributeValueP", + "name": "SentryAttributeValue", + "printedName": "SentryAttributeValue", + "usr": "s:6Sentry0A14AttributeValueP" } ], "declKind": "Enum", diff --git a/sdk_api_objc.json b/sdk_api_objc.json index 0967ef424bc..54eeead2c12 100644 --- a/sdk_api_objc.json +++ b/sdk_api_objc.json @@ -1 +1,1535 @@ -{} +[ + { + "kind": "ObjCInterfaceDecl", + "name": "SentryId", + "file": "SentryObjCBaggage.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryBreadcrumb", + "file": "SentryObjCBreadcrumb.h", + "super": "NSObject", + "has_inner": true + }, + { + "kind": "ObjCMethodDecl", + "name": "category", + "file": "SentryObjCBreadcrumb.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "data", + "file": "SentryObjCBreadcrumb.h", + "returnType": "NSDictionary * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "hash", + "file": "SentryObjCBreadcrumb.h", + "returnType": "NSUInteger", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "init", + "file": "SentryObjCBreadcrumb.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "initWithLevel:category:", + "file": "SentryObjCBreadcrumb.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "isEqual:", + "file": "SentryObjCBreadcrumb.h", + "returnType": "BOOL", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "isEqualToBreadcrumb:", + "file": "SentryObjCBreadcrumb.h", + "returnType": "BOOL", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "level", + "file": "SentryObjCBreadcrumb.h", + "returnType": "SentryLevel", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "message", + "file": "SentryObjCBreadcrumb.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "origin", + "file": "SentryObjCBreadcrumb.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "serialize", + "file": "SentryObjCBreadcrumb.h", + "returnType": "NSDictionary * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setCategory:", + "file": "SentryObjCBreadcrumb.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setData:", + "file": "SentryObjCBreadcrumb.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setLevel:", + "file": "SentryObjCBreadcrumb.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setMessage:", + "file": "SentryObjCBreadcrumb.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setOrigin:", + "file": "SentryObjCBreadcrumb.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setTimestamp:", + "file": "SentryObjCBreadcrumb.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setType:", + "file": "SentryObjCBreadcrumb.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "timestamp", + "file": "SentryObjCBreadcrumb.h", + "returnType": "NSDate * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "type", + "file": "SentryObjCBreadcrumb.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCPropertyDecl", + "name": "category", + "file": "SentryObjCBreadcrumb.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "data", + "file": "SentryObjCBreadcrumb.h", + "type": "NSDictionary * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "level", + "file": "SentryObjCBreadcrumb.h", + "type": "SentryLevel" + }, + { + "kind": "ObjCPropertyDecl", + "name": "message", + "file": "SentryObjCBreadcrumb.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "origin", + "file": "SentryObjCBreadcrumb.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "timestamp", + "file": "SentryObjCBreadcrumb.h", + "type": "NSDate * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "type", + "file": "SentryObjCBreadcrumb.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryDebugMeta", + "file": "SentryObjCDebugMeta.h", + "super": "NSObject", + "has_inner": true + }, + { + "kind": "ObjCMethodDecl", + "name": "codeFile", + "file": "SentryObjCDebugMeta.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "debugID", + "file": "SentryObjCDebugMeta.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "imageAddress", + "file": "SentryObjCDebugMeta.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "imageSize", + "file": "SentryObjCDebugMeta.h", + "returnType": "NSNumber * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "imageVmAddress", + "file": "SentryObjCDebugMeta.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "init", + "file": "SentryObjCDebugMeta.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setCodeFile:", + "file": "SentryObjCDebugMeta.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setDebugID:", + "file": "SentryObjCDebugMeta.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setImageAddress:", + "file": "SentryObjCDebugMeta.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setImageSize:", + "file": "SentryObjCDebugMeta.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setImageVmAddress:", + "file": "SentryObjCDebugMeta.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setType:", + "file": "SentryObjCDebugMeta.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "type", + "file": "SentryObjCDebugMeta.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCPropertyDecl", + "name": "codeFile", + "file": "SentryObjCDebugMeta.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "debugID", + "file": "SentryObjCDebugMeta.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "imageAddress", + "file": "SentryObjCDebugMeta.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "imageSize", + "file": "SentryObjCDebugMeta.h", + "type": "NSNumber * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "imageVmAddress", + "file": "SentryObjCDebugMeta.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "type", + "file": "SentryObjCDebugMeta.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryBreadcrumb", + "file": "SentryObjCDefines.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryBreadcrumb", + "file": "SentryObjCEvent.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryMechanism", + "file": "SentryObjCException.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryFrame", + "file": "SentryObjCFrame.h", + "super": "NSObject", + "has_inner": true + }, + { + "kind": "ObjCMethodDecl", + "name": "columnNumber", + "file": "SentryObjCFrame.h", + "returnType": "NSNumber * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "contextLine", + "file": "SentryObjCFrame.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "fileName", + "file": "SentryObjCFrame.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "function", + "file": "SentryObjCFrame.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "imageAddress", + "file": "SentryObjCFrame.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "inApp", + "file": "SentryObjCFrame.h", + "returnType": "NSNumber * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "init", + "file": "SentryObjCFrame.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "instructionAddress", + "file": "SentryObjCFrame.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "lineNumber", + "file": "SentryObjCFrame.h", + "returnType": "NSNumber * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "module", + "file": "SentryObjCFrame.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "package", + "file": "SentryObjCFrame.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "platform", + "file": "SentryObjCFrame.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "postContext", + "file": "SentryObjCFrame.h", + "returnType": "NSArray * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "preContext", + "file": "SentryObjCFrame.h", + "returnType": "NSArray * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setColumnNumber:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setContextLine:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setFileName:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setFunction:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setImageAddress:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setInApp:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setInstructionAddress:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setLineNumber:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setModule:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setPackage:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setPlatform:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setPostContext:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setPreContext:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setStackStart:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setSymbolAddress:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setVars:", + "file": "SentryObjCFrame.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "stackStart", + "file": "SentryObjCFrame.h", + "returnType": "NSNumber * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "symbolAddress", + "file": "SentryObjCFrame.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "vars", + "file": "SentryObjCFrame.h", + "returnType": "NSDictionary * _Nonnull", + "instance": true + }, + { + "kind": "ObjCPropertyDecl", + "name": "columnNumber", + "file": "SentryObjCFrame.h", + "type": "NSNumber * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "contextLine", + "file": "SentryObjCFrame.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "fileName", + "file": "SentryObjCFrame.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "function", + "file": "SentryObjCFrame.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "imageAddress", + "file": "SentryObjCFrame.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "inApp", + "file": "SentryObjCFrame.h", + "type": "NSNumber * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "instructionAddress", + "file": "SentryObjCFrame.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "lineNumber", + "file": "SentryObjCFrame.h", + "type": "NSNumber * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "module", + "file": "SentryObjCFrame.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "package", + "file": "SentryObjCFrame.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "platform", + "file": "SentryObjCFrame.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "postContext", + "file": "SentryObjCFrame.h", + "type": "NSArray * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "preContext", + "file": "SentryObjCFrame.h", + "type": "NSArray * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "stackStart", + "file": "SentryObjCFrame.h", + "type": "NSNumber * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "symbolAddress", + "file": "SentryObjCFrame.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "vars", + "file": "SentryObjCFrame.h", + "type": "NSDictionary * _Nonnull" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryGeo", + "file": "SentryObjCGeo.h", + "super": "NSObject", + "has_inner": true + }, + { + "kind": "ObjCMethodDecl", + "name": "city", + "file": "SentryObjCGeo.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "countryCode", + "file": "SentryObjCGeo.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "hash", + "file": "SentryObjCGeo.h", + "returnType": "NSUInteger", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "isEqual:", + "file": "SentryObjCGeo.h", + "returnType": "BOOL", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "isEqualToGeo:", + "file": "SentryObjCGeo.h", + "returnType": "BOOL", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "region", + "file": "SentryObjCGeo.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setCity:", + "file": "SentryObjCGeo.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setCountryCode:", + "file": "SentryObjCGeo.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setRegion:", + "file": "SentryObjCGeo.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCPropertyDecl", + "name": "city", + "file": "SentryObjCGeo.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "countryCode", + "file": "SentryObjCGeo.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "region", + "file": "SentryObjCGeo.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryHttpStatusCodeRange", + "file": "SentryObjCHttpStatusCodeRange.h", + "super": "NSObject", + "has_inner": true + }, + { + "kind": "ObjCMethodDecl", + "name": "init", + "file": "SentryObjCHttpStatusCodeRange.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "initWithMin:max:", + "file": "SentryObjCHttpStatusCodeRange.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "initWithStatusCode:", + "file": "SentryObjCHttpStatusCodeRange.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "max", + "file": "SentryObjCHttpStatusCodeRange.h", + "returnType": "NSInteger", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "min", + "file": "SentryObjCHttpStatusCodeRange.h", + "returnType": "NSInteger", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "new", + "file": "SentryObjCHttpStatusCodeRange.h", + "returnType": "instancetype _Nonnull", + "instance": false + }, + { + "kind": "ObjCPropertyDecl", + "name": "max", + "file": "SentryObjCHttpStatusCodeRange.h", + "type": "NSInteger" + }, + { + "kind": "ObjCPropertyDecl", + "name": "min", + "file": "SentryObjCHttpStatusCodeRange.h", + "type": "NSInteger" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryId", + "file": "SentryObjCId.h", + "super": "NSObject", + "has_inner": true + }, + { + "kind": "ObjCMethodDecl", + "name": "empty", + "file": "SentryObjCId.h", + "returnType": "SentryId * _Nonnull", + "instance": false + }, + { + "kind": "ObjCMethodDecl", + "name": "init", + "file": "SentryObjCId.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "initWithUUIDString:", + "file": "SentryObjCId.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "initWithUuid:", + "file": "SentryObjCId.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "isEqual:", + "file": "SentryObjCId.h", + "returnType": "BOOL", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "sentryIdString", + "file": "SentryObjCId.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCPropertyDecl", + "name": "empty", + "file": "SentryObjCId.h", + "type": "SentryId * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "sentryIdString", + "file": "SentryObjCId.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryLogger", + "file": "SentryObjCLogger.h", + "super": "NSObject", + "has_inner": true + }, + { + "kind": "ObjCMethodDecl", + "name": "debug:", + "file": "SentryObjCLogger.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "debug:attributes:", + "file": "SentryObjCLogger.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "error:", + "file": "SentryObjCLogger.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "error:attributes:", + "file": "SentryObjCLogger.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "fatal:", + "file": "SentryObjCLogger.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "fatal:attributes:", + "file": "SentryObjCLogger.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "info:", + "file": "SentryObjCLogger.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "info:attributes:", + "file": "SentryObjCLogger.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "trace:", + "file": "SentryObjCLogger.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "trace:attributes:", + "file": "SentryObjCLogger.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "warn:", + "file": "SentryObjCLogger.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "warn:attributes:", + "file": "SentryObjCLogger.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryMeasurementUnit", + "file": "SentryObjCMeasurementUnit.h", + "super": "NSObject", + "has_inner": true + }, + { + "kind": "ObjCMethodDecl", + "name": "init", + "file": "SentryObjCMeasurementUnit.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "initWithUnit:", + "file": "SentryObjCMeasurementUnit.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "new", + "file": "SentryObjCMeasurementUnit.h", + "returnType": "instancetype _Nonnull", + "instance": false + }, + { + "kind": "ObjCMethodDecl", + "name": "none", + "file": "SentryObjCMeasurementUnit.h", + "returnType": "SentryMeasurementUnit * _Nonnull", + "instance": false + }, + { + "kind": "ObjCMethodDecl", + "name": "unit", + "file": "SentryObjCMeasurementUnit.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCPropertyDecl", + "name": "none", + "file": "SentryObjCMeasurementUnit.h", + "type": "SentryMeasurementUnit * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "unit", + "file": "SentryObjCMeasurementUnit.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryMechanismContext", + "file": "SentryObjCMechanism.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryNSError", + "file": "SentryObjCMechanismContext.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryMessage", + "file": "SentryObjCMessage.h", + "super": "NSObject", + "has_inner": true + }, + { + "kind": "ObjCMethodDecl", + "name": "formatted", + "file": "SentryObjCMessage.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "init", + "file": "SentryObjCMessage.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "initWithFormatted:", + "file": "SentryObjCMessage.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "message", + "file": "SentryObjCMessage.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "new", + "file": "SentryObjCMessage.h", + "returnType": "instancetype _Nonnull", + "instance": false + }, + { + "kind": "ObjCMethodDecl", + "name": "params", + "file": "SentryObjCMessage.h", + "returnType": "NSArray * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setMessage:", + "file": "SentryObjCMessage.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setParams:", + "file": "SentryObjCMessage.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCPropertyDecl", + "name": "formatted", + "file": "SentryObjCMessage.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "message", + "file": "SentryObjCMessage.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "params", + "file": "SentryObjCMessage.h", + "type": "NSArray * _Nonnull" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryId", + "file": "SentryObjCMetric.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryObjCAttributeContent", + "file": "SentryObjCMetricsApi.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryNSError", + "file": "SentryObjCNSError.h", + "super": "NSObject", + "has_inner": true + }, + { + "kind": "ObjCMethodDecl", + "name": "code", + "file": "SentryObjCNSError.h", + "returnType": "NSInteger", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "domain", + "file": "SentryObjCNSError.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "init", + "file": "SentryObjCNSError.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "initWithDomain:code:", + "file": "SentryObjCNSError.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "new", + "file": "SentryObjCNSError.h", + "returnType": "instancetype _Nonnull", + "instance": false + }, + { + "kind": "ObjCMethodDecl", + "name": "setCode:", + "file": "SentryObjCNSError.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setDomain:", + "file": "SentryObjCNSError.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCPropertyDecl", + "name": "code", + "file": "SentryObjCNSError.h", + "type": "NSInteger" + }, + { + "kind": "ObjCPropertyDecl", + "name": "domain", + "file": "SentryObjCNSError.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryReplayOptions", + "file": "SentryObjCOptions.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "TypedefDecl", + "name": "SentryRedactRegionType", + "file": "SentryObjCRedactRegionType.h", + "type": "NSString *" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "UIView", + "file": "SentryObjCReplayApi.h", + "super": null, + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryRequest", + "file": "SentryObjCRequest.h", + "super": "NSObject", + "has_inner": true + }, + { + "kind": "ObjCMethodDecl", + "name": "bodySize", + "file": "SentryObjCRequest.h", + "returnType": "NSNumber * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "cookies", + "file": "SentryObjCRequest.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "fragment", + "file": "SentryObjCRequest.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "headers", + "file": "SentryObjCRequest.h", + "returnType": "NSDictionary * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "init", + "file": "SentryObjCRequest.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "method", + "file": "SentryObjCRequest.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "queryString", + "file": "SentryObjCRequest.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setBodySize:", + "file": "SentryObjCRequest.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setCookies:", + "file": "SentryObjCRequest.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setFragment:", + "file": "SentryObjCRequest.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setHeaders:", + "file": "SentryObjCRequest.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setMethod:", + "file": "SentryObjCRequest.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setQueryString:", + "file": "SentryObjCRequest.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "setUrl:", + "file": "SentryObjCRequest.h", + "returnType": "void", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "url", + "file": "SentryObjCRequest.h", + "returnType": "NSString * _Nullable", + "instance": true + }, + { + "kind": "ObjCPropertyDecl", + "name": "bodySize", + "file": "SentryObjCRequest.h", + "type": "NSNumber * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "cookies", + "file": "SentryObjCRequest.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "fragment", + "file": "SentryObjCRequest.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "headers", + "file": "SentryObjCRequest.h", + "type": "NSDictionary * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "method", + "file": "SentryObjCRequest.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "queryString", + "file": "SentryObjCRequest.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCPropertyDecl", + "name": "url", + "file": "SentryObjCRequest.h", + "type": "NSString * _Nullable" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryBreadcrumb", + "file": "SentrySDK.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryTransactionContext", + "file": "SentryObjCSamplingContext.h", + "super": "SentrySpanContext", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryAttachment", + "file": "SentryObjCScope.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCProtocolDecl", + "name": "SentrySerializable", + "file": "SentryObjCSerializable.h" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryId", + "file": "SentryObjCSpanContext.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentrySpanId", + "file": "SentryObjCSpanId.h", + "super": "NSObject", + "has_inner": true + }, + { + "kind": "ObjCMethodDecl", + "name": "empty", + "file": "SentryObjCSpanId.h", + "returnType": "SentrySpanId * _Nonnull", + "instance": false + }, + { + "kind": "ObjCMethodDecl", + "name": "init", + "file": "SentryObjCSpanId.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "initWithUUID:", + "file": "SentryObjCSpanId.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "initWithValue:", + "file": "SentryObjCSpanId.h", + "returnType": "instancetype _Nonnull", + "instance": true + }, + { + "kind": "ObjCMethodDecl", + "name": "sentrySpanIdString", + "file": "SentryObjCSpanId.h", + "returnType": "NSString * _Nonnull", + "instance": true + }, + { + "kind": "ObjCPropertyDecl", + "name": "empty", + "file": "SentryObjCSpanId.h", + "type": "SentrySpanId * _Nonnull" + }, + { + "kind": "ObjCPropertyDecl", + "name": "sentrySpanIdString", + "file": "SentryObjCSpanId.h", + "type": "NSString * _Nonnull" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryId", + "file": "SentryObjCSpanProtocol.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryFrame", + "file": "SentryObjCStacktrace.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryStacktrace", + "file": "SentryObjCThread.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryBaggage", + "file": "SentryObjCTraceContext.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryId", + "file": "SentryObjCTraceHeader.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryId", + "file": "SentryObjCTransactionContext.h", + "super": "NSObject", + "has_inner": false + }, + { + "kind": "TypedefDecl", + "name": "SentryUnitName", + "file": "SentryObjCUnit.h", + "type": "NSString *" + }, + { + "kind": "ObjCInterfaceDecl", + "name": "SentryGeo", + "file": "SentryObjCUser.h", + "super": "NSObject", + "has_inner": false + } +]