diff --git a/.codecov.yml b/.codecov.yml index 7e9c4e732a9..df45040e774 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -1,10 +1,17 @@ codecov: branch: main - require_ci_to_pass: yes + require_ci_to_pass: false # Check coverage even if the tests fail notify: - wait_for_ci: yes + wait_for_ci: true coverage: + status: + project: + default: + threshold: 0.05% # Allow up to 0.05% coverage decrease before failing the build + patch: + default: + threshold: 0.05% # Allow up to 0.05% coverage decrease before failing the build range: 80...100 precision: 3 round: down @@ -21,5 +28,5 @@ comment: # already exists, and a newer commit results in no coverage change for the # entire pull, the comment will be deleted. require_changes: true - require_base: yes # must have a base report to post - require_head: yes # must have a head report to post + require_base: true # must have a base report to post + require_head: true # must have a head report to post diff --git a/.cursor/rules/github-workflow.mdc b/.cursor/rules/github-workflow.mdc new file mode 100644 index 00000000000..62f0f0742d7 --- /dev/null +++ b/.cursor/rules/github-workflow.mdc @@ -0,0 +1,292 @@ +--- +globs: .github/workflows/* +alwaysApply: false +--- + +# Cursor Rules for Sentry Cocoa Repository + +## GitHub Workflow Naming Convention + +### Workflow Names (Top-level `name:` field) + +Use concise, action-oriented names that describe the workflow's primary purpose: + +**Format:** `[Action] [Subject]` + +**Examples:** +- ✅ `Release` (not "Release a new version") +- ✅ `UI Tests` (not "Sentry Cocoa UI Tests") +- ✅ `Benchmarking` (not "Run benchmarking tests") +- ✅ `Lint SwiftLint` (not "Lint Swiftlint Formatting") +- ✅ `Test CocoaPods` (not "CocoaPods Integration Test") + +### Job Names (Job-level `name:` field) + +Use clear, concise descriptions that avoid redundancy with the workflow name: + +**Principles:** +1. **Remove redundant prefixes** - Don't repeat the workflow name +2. **Use action verbs** - Start with what the job does +3. **Avoid version-specific naming** - Don't include Xcode versions, tool versions, etc. +4. **Keep it concise** - Maximum 3-4 words when possible + +**Patterns:** + +#### Build Jobs +- ✅ `Build XCFramework Slice` (not "Build XCFramework Variant Slice") +- ✅ `Assemble XCFramework Variant` (not "Assemble XCFramework" - be specific about variants) +- ✅ `Build App and Test Runner` +- ✅ `${{matrix.sdk}}` for platform-specific builds (e.g., "iphoneos", "macosx") +- ✅ `${{inputs.name}}${{inputs.suffix}}` for variant assembly (e.g., "Sentry-Dynamic") + +#### Test Jobs +- ✅ `Test ${{matrix.name}} V3 # Up the version with every change to keep track of flaky tests` +- ✅ `Unit ${{matrix.name}}` (for unit test matrices) +- ✅ `Run Benchmarks ${{matrix.suite}}` (for benchmarking matrices) +- ✅ `Test SwiftUI V4 # Up the version with every change to keep track of flaky tests` +- ✅ `Test Sentry Duplication V4 # Up the version with every change to keep track of flaky tests` + +**Note:** +- Version numbers (V1, V2, etc.) are included in test job names for flaky test tracking, with explanatory comments retained. +- For matrix-based jobs, use clean variable names that produce readable job names (e.g., `${{matrix.sdk}}`, `${{matrix.name}}`, `${{inputs.name}}${{inputs.suffix}}`). +- When matrix includes multiple iOS versions, add a descriptive `name` field to each matrix entry (e.g., "iOS 16 Swift", "iOS 17 Swift") for clear job identification. + +#### Validation Jobs +- ✅ `Validate XCFramework` (not "Validate XCFramework - Static") +- ✅ `Validate SPM Static` (not "Validate Swift Package Manager - Static") +- ✅ `Check API Stability` (not "API Stability Check") + +#### Lint Jobs +- ✅ `Lint` (job name when workflow already specifies the tool, e.g., "Lint SwiftLint") +- ❌ `SwiftLint` (redundant with workflow name "Lint SwiftLint") +- ❌ `Clang Format` (redundant with workflow name "Lint Clang") + +#### Utility Jobs +- ✅ `Collect App Metrics` (not "Collect app metrics") +- ✅ `Detect File Changes` (not "Detect Changed Files") +- ✅ `Release New Version` (not "Release a new version") + +### Version Tracking for Flaky Test Management + +For UI test jobs that need version tracking for flaky test management, include the version number in BOTH the job name AND a comment: + +**Format:** `[Job Name] V{number} # Up the version with every change to keep track of flaky tests` + +**Example:** +```yaml +name: Test iOS Swift V5 # Up the version with every change to keep track of flaky tests +``` + +**Rationale:** +- Version numbers must be in the job name because failure rate monitoring captures job names and ignores comments +- Comments are kept to provide context and instructions for developers + +### Matrix Variables in Names + +When using matrix variables, prefer descriptive names over technical details: + +**Examples:** +- ✅ `Test ${{matrix.name}}` where name = "iOS Objective-C", "tvOS Swift" +- ✅ `Test ${{matrix.name}}` where name = "iOS 16 Swift", "iOS 17 Swift", "iOS 18 Swift" +- ✅ `Unit ${{matrix.name}}` where name = "iOS 16 Sentry", "macOS 15 Sentry", "tvOS 18 Sentry" +- ✅ `Run Benchmarks ${{matrix.suite}}` where suite = "High-end device", "Low-end device" +- ✅ `Check API Stability (${{ matrix.version }})` where version = "default", "v9" +- ❌ `Test iOS Swift Xcode ${{matrix.xcode}}` (version-specific) + +### Reusable Workflow Names + +For reusable workflows (workflow_call), use descriptive names that indicate their purpose: + +**Examples:** +- ✅ `Build XCFramework Slice` +- ✅ `Assemble XCFramework Variant` +- ✅ `UI Tests Common` + +### Benefits of This Convention + +1. **Status Check Stability** - Names won't break when tool versions change +2. **Cleaner GitHub UI** - Shorter, more readable names in PR checks +3. **Better Organization** - Consistent patterns make workflows easier to understand +4. **Future-Proof** - Version-agnostic naming reduces maintenance overhead +5. **Branch Protection Compatibility** - Stable names work well with GitHub's branch protection rules + +### Anti-Patterns to Avoid + +❌ **Don't include:** +- Tool versions (Xcode 15.4, Swift 5.9, etc.) unless they are relevant to the job +- Redundant workflow prefixes ("Release /", "UI Tests /") +- Overly verbose descriptions +- Technical implementation details in user-facing names +- Lowercase inconsistency + +❌ **Examples of what NOT to do:** +- "Release / Build XCFramework Variant Slice (Sentry, mh_dylib, -Dynamic, sentry-dynamic) / Build XCFramework Slice" +- "UI Tests / UI Tests for iOS-Swift Xcode 15.4 - V5" +- "Lint Swiftlint Formatting / SwiftLint" (redundant job name) +- "Build Sentry Cocoa XCFramework Variant Slice" + +### Implementation Notes + +- Always include version numbers in test job names AND keep explanatory comments for flaky test management +- Keep matrix variable usage minimal and descriptive +- Ensure names remain meaningful when viewed in GitHub's status check UI +- Test names in the GitHub PR interface before committing changes +- For lint workflows, use simple "Lint" job name since the tool is already specified in the workflow name + +--- + +## GitHub Actions Concurrency Strategy + +### Overview + +This document outlines the concurrency configuration strategy for all GitHub Actions workflows in the Sentry Cocoa repository. The strategy optimizes CI resource usage while ensuring critical runs (like main branch pushes) are never interrupted. + +### Core Principles + +#### 1. Resource Optimization +- **Cancel outdated PR runs** - When new commits are pushed to a PR, cancel the previous workflow run since only the latest commit matters for merge decisions +- **Protect critical runs** - Never cancel workflows running on main branch, release branches, or scheduled runs as these are essential for maintaining baseline quality and release integrity +- **Per-branch grouping** - Use `github.ref` for consistent concurrency grouping across all branch types + +#### 2. Consistent Patterns +All workflows follow standardized concurrency patterns based on their trigger types and criticality. + +### Concurrency Patterns + +#### Pattern 1: Conditional Cancellation (Most Common) +**Used by:** Most workflows that run on both main/release branches AND pull requests + +```yaml +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} +``` + +**Behavior:** +- ✅ Cancels in-progress runs when new commits are pushed to PRs +- ✅ Never cancels runs on main branch pushes +- ✅ Never cancels runs on release branch pushes +- ✅ Never cancels scheduled runs +- ✅ Never cancels manual workflow_dispatch runs + +**Examples:** `test.yml`, `build.yml`, `benchmarking.yml`, `ui-tests.yml`, all lint workflows + +#### Pattern 2: Always Cancel (PR-Only Workflows) +**Used by:** Workflows that ONLY run on pull requests + +```yaml +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +``` + +**Behavior:** +- ✅ Always cancels in-progress runs (safe since they only run on PRs) +- ✅ Provides immediate feedback on latest changes + +**Examples:** `danger.yml`, `api-stability.yml`, `changes-in-high-risk-code.yml` + +#### Pattern 3: Fixed Group Name (Special Cases) +**Used by:** Utility workflows with specific requirements + +```yaml +concurrency: + group: "auto-update-tools" + cancel-in-progress: true +``` + +**Example:** `auto-update-tools.yml` (uses fixed group name for global coordination) + +### Implementation Details + +#### Group Naming Convention +- **Standard:** `${{ github.workflow }}-${{ github.ref }}` +- **Benefits:** + - Unique per workflow and branch/PR + - Consistent across all workflow types + - Works with main, release, and feature branches + - Handles PRs and direct pushes uniformly + +#### Why `github.ref` Instead of `github.head_ref || github.run_id`? +- **Simpler logic** - No conditional expressions needed +- **Consistent behavior** - Same pattern works for all trigger types +- **Per-branch grouping** - Natural grouping by branch without special cases +- **Better maintainability** - Single pattern to understand and maintain + +#### Cancellation Logic Evolution +**Before:** +```yaml +cancel-in-progress: ${{ !(github.event_name == 'push' && github.ref == 'refs/heads/main') && github.event_name != 'schedule' }} +``` + +**After:** +```yaml +cancel-in-progress: ${{ github.event_name == 'pull_request' }} +``` + +**Why simplified:** +- ✅ Much more readable and maintainable +- ✅ Functionally identical behavior +- ✅ Clear intent: "only cancel on pull requests" +- ✅ Less prone to errors + +### Workflow-Specific Configurations + +#### High-Resource Workflows +**Examples:** `benchmarking.yml`, `ui-tests.yml` +- Use conditional cancellation to protect expensive main branch runs +- Include detailed comments explaining resource considerations +- May include special cleanup steps (e.g., SauceLabs job cancellation) + +#### Fast Validation Workflows +**Examples:** All lint workflows, `danger.yml` +- Use appropriate cancellation strategy based on trigger scope +- Focus on providing quick feedback on latest changes + +#### Critical Infrastructure Workflows +**Examples:** `test.yml`, `build.yml`, `release.yml` +- Never cancel on main/release branches to maintain quality gates +- Ensure complete validation of production-bound code + +### Documentation Requirements + +Each workflow's concurrency block must include comments explaining: + +1. **Purpose** - Why concurrency control is needed for this workflow +2. **Resource considerations** - Any expensive operations (SauceLabs, device time, etc.) +3. **Branch protection logic** - Why main/release branches need complete runs +4. **User experience** - How the configuration improves feedback timing + +#### Example Documentation: +```yaml +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple benchmark runs on the same code, +# as benchmarks are extremely resource-intensive and require dedicated device time on SauceLabs. +# - For pull requests, we cancel in-progress runs when new commits are pushed to avoid wasting +# expensive external testing resources and provide timely performance feedback. +# - For main branch pushes, we never cancel benchmarks to ensure we have complete performance +# baselines for every main branch commit, which are critical for performance regression detection. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} +``` + +### Maintenance Guidelines + +#### When Adding New Workflows +1. **Identify trigger scope** - Does it run on main/release branches? +2. **Choose appropriate pattern** - Conditional vs always cancel +3. **Add documentation** - Explain the resource and timing considerations +4. **Follow naming convention** - Use standard group naming pattern + +#### When Modifying Existing Workflows +1. **Preserve protection** - Don't break main/release branch safeguards +2. **Update documentation** - Keep comments accurate and helpful +3. **Test edge cases** - Verify behavior with scheduled/manual triggers +4. **Consider resource impact** - Evaluate cost of additional runs + +#### Red Flags to Avoid +- ❌ Never use `cancel-in-progress: true` on workflows that run on main/release branches +- ❌ Don't create complex conditional logic when simple patterns work +- ❌ Avoid custom group names unless absolutely necessary +- ❌ Don't skip documentation - future maintainers need context diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 4afb3c41bdf..fca69cd3f26 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @philipphofmann @armcknight @philprime @noahsmartin @itaybre +* @philipphofmann @philprime @noahsmartin @itaybre diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index 51eeebdd755..125284f386b 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -1,7 +1,6 @@ name: 🐞 Bug Report description: Tell us about something that's not working the way we (probably) intend. -labels: ["Platform: Cocoa", "Type: Bug"] -type: Bug +labels: ["Cocoa", "Bug"] body: - type: dropdown id: platform diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml index 92997a819ce..8d409b42a63 100644 --- a/.github/ISSUE_TEMPLATE/feature.yml +++ b/.github/ISSUE_TEMPLATE/feature.yml @@ -1,7 +1,6 @@ name: 💡 Feature Request description: Tell us about a problem our SDK could solve but doesn't. -labels: ["Platform: Cocoa", "Type: Feature Request"] -type: Feature +labels: ["Cocoa", "Feature"] body: - type: textarea id: problem diff --git a/.github/ISSUE_TEMPLATE/flaky-test.yml b/.github/ISSUE_TEMPLATE/flaky-test.yml index 74de3ebefb7..564dfe5670d 100644 --- a/.github/ISSUE_TEMPLATE/flaky-test.yml +++ b/.github/ISSUE_TEMPLATE/flaky-test.yml @@ -1,7 +1,6 @@ name: Flaky Test description: For reporting a flaky test. -labels: ["Platform: Cocoa", "Type: Flaky Test"] -type: Task +labels: ["Cocoa", "Task", "Type: Flaky Test"] body: - type: input id: GitHubActionRunLink diff --git a/.github/ISSUE_TEMPLATE/maintainer-blank.yml b/.github/ISSUE_TEMPLATE/maintainer-blank.yml index c38be249352..cd6e06e38a0 100644 --- a/.github/ISSUE_TEMPLATE/maintainer-blank.yml +++ b/.github/ISSUE_TEMPLATE/maintainer-blank.yml @@ -1,6 +1,6 @@ name: Blank Issue description: Blank Issue. Reserved for maintainers. -labels: ["Platform: Cocoa"] +labels: ["Cocoa"] body: - type: textarea id: description diff --git a/.github/actions/prepare-package.swift/action.yml b/.github/actions/prepare-package.swift/action.yml new file mode 100644 index 00000000000..46f46d48085 --- /dev/null +++ b/.github/actions/prepare-package.swift/action.yml @@ -0,0 +1,40 @@ +name: "Prepare Package.swift" +description: "Prepares Package.swift" +inputs: + is-pr: + description: "Whether the build is a PR" + required: true + default: "false" + package-file: + description: "The package file to prepare" + required: true + default: "Package.swift" +runs: + using: "composite" + steps: + - name: Remove newer package files + # Remove newer package files when processing Package.swift to prevent interference + if: ${{ inputs.package-file == 'Package.swift' }} + shell: bash + run: rm -rf Package@swift* + - name: Remove Sentry-Dynamic-WithARM64e target + # We don't build it on PRs, so we need to remove it from the package.swift file. + if: ${{ inputs.is-pr == 'true' }} + shell: bash + env: + PACKAGE_FILE: ${{ inputs.package-file }} + run: | + sed -i '' '/Sentry-Dynamic-WithARM64e/d' $PACKAGE_FILE + sed -i '' '/Sentry-WithoutUIKitOrAppKit-WithARM64e/d' $PACKAGE_FILE + sed -i '' '/^[[:space:]]*\.binaryTarget($/{N;/\n[[:space:]]*),$/d;}' $PACKAGE_FILE + - name: Change path of the framework + shell: bash + env: + PACKAGE_FILE: ${{ inputs.package-file }} + run: | + sed -i '' 's/url.*//g' $PACKAGE_FILE + sed -i '' 's/checksum: ".*" \/\/Sentry-Static/path: "Sentry.xcframework.zip"/g' $PACKAGE_FILE + sed -i '' 's/checksum: ".*" \/\/Sentry-Dynamic-WithARM64e/path: "Sentry-Dynamic-WithARM64e.xcframework.zip"/g' $PACKAGE_FILE + sed -i '' 's/checksum: ".*" \/\/Sentry-Dynamic/path: "Sentry-Dynamic.xcframework.zip"/g' $PACKAGE_FILE + sed -i '' 's/checksum: ".*" \/\/Sentry-WithoutUIKitOrAppKit-WithARM64e/path: "Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework.zip"/g' $PACKAGE_FILE + sed -i '' 's/checksum: ".*" \/\/Sentry-WithoutUIKitOrAppKit/path: "Sentry-WithoutUIKitOrAppKit.xcframework.zip"/g' $PACKAGE_FILE diff --git a/.github/file-filters.yml b/.github/file-filters.yml index d08ff897b71..fbd7279c604 100644 --- a/.github/file-filters.yml +++ b/.github/file-filters.yml @@ -1,7 +1,6 @@ # This is used by the action https://github.com/dorny/paths-filter high_risk_code: &high_risk_code - - ".github/workflows/changes-in-high-risk-code.yml" - "Sources/Sentry/SentryNSURLSessionTaskSearch.m" - "Sources/Sentry/SentryNetworkTracker.m" - "Sources/Sentry/SentryUIViewControllerSwizzling.m" @@ -15,3 +14,483 @@ high_risk_code: &high_risk_code - "Sources/Sentry/SentryFileManager.m" - "Sources/Sentry/SentrySerialization.m" - "Sources/Sentry/SentrySerialization.h" + + # GH Actions + - ".github/workflows/changes-in-high-risk-code.yml" + - ".github/file-filters.yml" + +run_unit_tests_for_prs: &run_unit_tests_for_prs + - "Sources/**" + - "Tests/**" + - "SentryTestUtils/**" + - "SentryTestUtilsDynamic/**" + + # GH Actions + - ".github/workflows/test.yml" + - ".github/file-filters.yml" + + # Scripts + - "scripts/ci-select-xcode.sh" + - "scripts/ci-diagnostics.sh" + - "scripts/ci-utils.sh" + - "scripts/sentry-xcodebuild.sh" + - "scripts/start-test-server.sh" + - "scripts/tests-with-thread-sanitizer.sh" + + # Test infrastructure + - "test-server/**" + - "**/*.xctestplan" + - "Plans/**" + + # Project files + - "Sentry.xcodeproj/**" + - "Sentry.xcworkspace/**" + + # Build configuration + - "fastlane/**" + - "Makefile" + - "Brewfile*" + - ".codecov.yml" + +run_api_stability_for_prs: &run_api_stability_for_prs + - "Sources/**" + + # GH Actions + - ".github/workflows/api-stability.yml" + - ".github/file-filters.yml" + + # Project files + - "Sentry.xcworkspace/**" + - "Sentry.xcodeproj/**" + - "Package*.swift" + + # Scripts + - "scripts/build-xcframework-local.sh" + - "scripts/build-xcframework-slice.sh" + - "scripts/assemble-xcframework.sh" + - "scripts/update-api.sh" + - "scripts/ci-select-xcode.sh" + - "scripts/ci-diagnostics.sh" + + # API files + - "sdk_api.json" + - "sdk_api_v9.json" + + # Build configuration + - "Makefile" + +run_integration_test_for_prs: &run_integration_test_for_prs + - "Sources/**" + - "Samples/iOS-Cocoapods-*/**" + + # GH Actions + - ".github/workflows/integration-test.yml" + - ".github/file-filters.yml" + + # Project files + - "*.xcodeproj/**" + - "*.xcworkspace/**" + - "*.podspec" + - "Plans/iOS-Cocoapods-Swift6_Base.xctestplan" + + # Scripts + - "scripts/ci-select-xcode.sh" + - "scripts/ci-diagnostics.sh" + + # Build configuration + - "fastlane/**" + - "Gemfile.lock" + +run_benchmarking_for_prs: &run_benchmarking_for_prs + - "Sources/**" + + # GH Actions + - ".github/workflows/benchmarking.yml" + - ".github/workflows/build-xcframework-variant-slices.yml" + - ".github/workflows/assemble-xcframework-variant.yml" + - ".github/file-filters.yml" + + # Benchmarking implementation + - "Samples/iOS-Swift/**" + - ".sauce/benchmarking-config.yml" + - "Plans/iOS-Benchmarking_Base.xctestplan" + + # Scripts + - "scripts/ci-select-xcode.sh" + - "scripts/ci-diagnostics.sh" + - "scripts/build-xcframework-slice.sh" + - "scripts/assemble-xcframework.sh" + + # Project files + - "Samples/iOS-Swift/iOS-Swift.yml" + - "Samples/iOS-Swift/iOS-Swift.xcconfig" + - "Samples/iOS-Swift/iOS-SwiftClip.xcconfig" + - "Samples/iOS-Swift/iOS-Benchmarking.xcconfig" + + # Build configuration + - "fastlane/**" + +run_test_cross_platform_for_prs: &run_test_cross_platform_for_prs + - "Sources/**" + + # GH Actions + - ".github/workflows/test-cross-platform.yml" + - ".github/file-filters.yml" + + # Project files + - "Sentry.podspec" + - "SentrySwiftUI.podspec" + - "Package*.swift" + - "Tests/HybridSDKTest/HybridPod.podspec" + + # Scripts + - "scripts/ci-select-xcode.sh" + - "scripts/ci-diagnostics.sh" + + # Build configuration + - "Makefile" + - "Brewfile*" + +run_lint_clang_formatting_for_prs: &run_lint_clang_formatting_for_prs + - "**/*.h" + - "**/*.hpp" + - "**/*.c" + - "**/*.cpp" + - "**/*.m" + - "**/*.mm" + + # GH Actions + - ".github/workflows/lint-clang-formatting.yml" + - ".github/file-filters.yml" + + # Formatting configuration + - ".clang-format" + - "scripts/.clang-format-version" + - "scripts/check-clang-format.py" + + # Scripts + - "scripts/ci-diagnostics.sh" + + # Build configuration + - "Makefile" + - "Brewfile*" + +run_objc_conversion_analysis_for_prs: &run_objc_conversion_analysis_for_prs + - "SwiftConversion/**" + + # GH Actions + - ".github/workflows/objc-conversion-analysis.yml" + - ".github/file-filters.yml" + + # Scripts + - "scripts/ci-diagnostics.sh" + + # Build configuration + - "Brewfile*" + +run_auto_update_tools_for_prs: &run_auto_update_tools_for_prs + - ".github/workflows/auto-update-tools.yml" + - ".github/file-filters.yml" + + # Tool configuration + - ".pre-commit-config.yaml" + - "scripts/.clang-format-version" + - "scripts/.swiftlint-version" + + # Scripts + - "scripts/check-tooling-versions.sh" + - "scripts/ci-diagnostics.sh" + - "scripts/update-tooling-versions.sh" + + # Build configuration + - "Brewfile*" + - "Makefile" + +run_lint_cocoapods_specs_for_prs: &run_lint_cocoapods_specs_for_prs + - "Sources/**" + - "Tests/**" + - "Samples/**" + + # GH Actions + - ".github/workflows/lint-cocoapods-specs.yml" + - ".github/file-filters.yml" + + # Scripts + - "scripts/ci-select-xcode.sh" + - "scripts/ci-diagnostics.sh" + - "scripts/pod-lib-lint.sh" + + # Project files + - "Sentry.xcodeproj/**" + - "*.podspec" + - "Tests/HybridSDKTest/HybridPod.podspec" + + # Build configuration + - "Makefile" + - "Brewfile*" + - "Gemfile.lock" + - ".swiftlint.yml" + +run_release_for_prs: &run_release_for_prs + - "Sources/**" + + # GH Actions + - ".github/workflows/build-xcframework.yml" + - ".github/workflows/release.yml" + - ".github/workflows/build-xcframework-variant-slices.yml" + - ".github/workflows/assemble-xcframework-variant.yml" + - ".github/workflows/ui-tests-common.yml" + - ".github/file-filters.yml" + + # Scripts + - "scripts/ci-select-xcode.sh" + - "scripts/ci-diagnostics.sh" + - "scripts/build-xcframework-slice.sh" + - "scripts/build-xcframework-local.sh" + - "scripts/assemble-xcframework.sh" + - "scripts/generate_release_matrix.sh" + - "scripts/xcframework-generated-run.sh" + + # Project files + - "Sentry.xcworkspace/**" + - "Sentry.xcodeproj/**" + - "Package*.swift" + + # Sample projects + - "Samples/macOS-SPM-CommandLine/**" + - "Samples/SPM-Dynamic/**" + + # Build configuration + - "fastlane/**" + - "Makefile" + + # Test files + - "Tests/Perf/metrics-test.yml" + +run_lint_swift_formatting_for_prs: &run_lint_swift_formatting_for_prs + - "**/*.swift" + + # GH Actions + - ".github/workflows/lint-swift-formatting.yml" + - ".github/file-filters.yml" + + # Formatting + - ".swiftlint.yml" + - "scripts/.swiftlint-version" + + # Scripts + - "scripts/ci-diagnostics.sh" + + # Build configuration + - "Makefile" + - "Brewfile*" + +run_lint_shellcheck_for_prs: &run_lint_shellcheck_for_prs + - "**/*.sh" + + # GH Actions + - ".github/workflows/lint-shellcheck-formatting.yml" + - ".github/file-filters.yml" + +run_lint_dprint_for_prs: &run_lint_dprint_for_prs + - "**/*.yml" + - "**/*.yaml" + - "**/*.json" + - "**/*.md" + + # GH Actions + - ".github/workflows/lint-dprint-formatting.yml" + - ".github/file-filters.yml" + + # Formatting + - "dprint.json" + +run_lint_xcode_analyze_for_prs: &run_lint_xcode_analyze_for_prs + - "Sources/**" + - "Tests/**" + - "Samples/**" + + # GH Actions + - ".github/workflows/lint-xcode-analyze.yml" + - ".github/file-filters.yml" + + # Scripts + - "scripts/ci-select-xcode.sh" + - "scripts/ci-diagnostics.sh" + + # Project files + - "Sentry.xcodeproj/**" + - "Sentry.xcworkspace/**" + - "*.podspec" + + # Build configuration + - "Makefile" + +run_build_for_prs: &run_build_for_prs + - "Sources/**" + - "Samples/**" + + # GH Actions + - ".github/workflows/build.yml" + - ".github/file-filters.yml" + + # Project files + - "Sentry.xcworkspace/**" + - "Sentry.xcodeproj/**" + - "Package*.swift" + + # Scripts + - "scripts/ci-select-xcode.sh" + - "scripts/ci-diagnostics.sh" + - "scripts/sentry-xcodebuild.sh" + - "scripts/check-uikit-linkage.sh" + + # Build configuration + - "fastlane/**" + - "Gemfile.lock" + - "Makefile" + - "Brewfile*" + +run_testflight_for_prs: &run_testflight_for_prs + - ".github/workflows/testflight.yml" + - ".github/file-filters.yml" + +run_testflight_for_pushes: &run_testflight_for_pushes + - "Sources/**" + - "Samples/iOS-Swift/**" + + # GH Actions + - ".github/workflows/testflight.yml" + - ".github/file-filters.yml" + + # Scripts + - "scripts/ci-select-xcode.sh" + - "scripts/ci-diagnostics.sh" + + # Build configuration + - "fastlane/**" + - "Makefile" + +run_codeql_analysis_for_prs: &run_codeql_analysis_for_prs + - "Sources/**" + + # GH Actions + - ".github/workflows/codeql-analysis.yml" + - ".github/file-filters.yml" + + # Project files + - "Sentry.xcworkspace/**" + - "Sentry.xcodeproj/**" + + # Scripts + - "scripts/ci-diagnostics.sh" + + # Build configuration + - "Makefile" + +run_version_bump_util_for_prs: &run_version_bump_util_for_prs + - ".github/workflows/version-bump-util.yml" + - ".github/file-filters.yml" + + # Version bump utilities + - "Utils/VersionBump/**" + + # Scripts + - "scripts/bump.sh" + + # Version-related source files + - "Sources/Sentry/SentryMeta.m" + + # Project files with version info + - "Sentry.podspec" + - "SentryPrivate.podspec" + - "SentrySwiftUI.podspec" + - "Package*.swift" + - "Tests/HybridSDKTest/HybridPod.podspec" + + # Configuration files + - "Sources/Configuration/SDK.xcconfig" + - "Sources/Configuration/Versioning.xcconfig" + - "Sources/Configuration/SentrySwiftUI.xcconfig" + +run_ui_tests_for_prs: &run_ui_tests_for_prs + - "Sources/**" + - "Tests/**" + + # GH Actions + - ".github/workflows/ui-tests.yml" + - ".github/workflows/ui-tests-common.yml" + - ".github/workflows/build-xcframework-variant-slices.yml" + - ".github/workflows/assemble-xcframework-variant.yml" + - ".github/file-filters.yml" + + # Scripts + - "scripts/ci-select-xcode.sh" + - "scripts/build-xcframework-slice.sh" + - "scripts/assemble-xcframework.sh" + - "scripts/ci-diagnostics.sh" + + # Test plans + - "**/*.xctestplan" + - "Plans/**" + + # Sample projects + - "Samples/iOS-SwiftUI/**" + - "Samples/iOS-Swift/**" + - "Samples/iOS-Swift6/**" + - "Samples/SentrySampleShared/**" + - "Samples/Shared/**" + + # Build configuration + - "fastlane/**" + - "Makefile" + - "Brewfile*" + +run_ui_tests_critical_for_prs: &run_ui_tests_critical_for_prs + - "Sources/**" + - "TestSamples/**" + + # GH Actions + - ".github/workflows/ui-tests-critical.yml" + - ".github/workflows/ui-tests-common.yml" + - ".github/file-filters.yml" + + # Test plans + - "**/*.xctestplan" + - "Plans/**" + + # Scripts + - "scripts/ci-boot-simulator.sh" + - "scripts/ci-select-xcode.sh" + - "scripts/ci-diagnostics.sh" + + # Build configuration + - "fastlane/**" + - "Gemfile.lock" + - "Makefile" + - "Brewfile*" + +run_lint_swiftlint_for_prs: &run_lint_swiftlint_for_prs + - "Sources/**" + - "Tests/**" + - "Samples/**" + + # GH Actions + - ".github/workflows/lint-swiftlint-formatting.yml" + - ".github/file-filters.yml" + + # SwiftLint configuration + - ".swiftlint.yml" + - "scripts/.swiftlint-version" + + # Scripts + - "scripts/ci-select-xcode.sh" + - "scripts/ci-diagnostics.sh" + + # Project files + - "Sentry.xcodeproj/**" + - "*.podspec" + + # Build configuration + - "Makefile" + - "Brewfile*" diff --git a/.github/last-release-runid b/.github/last-release-runid index 963c1f67f43..25237d0e8cd 100644 --- a/.github/last-release-runid +++ b/.github/last-release-runid @@ -1 +1 @@ -16176105837 +17733239540 diff --git a/.github/workflows/api-stability.yml b/.github/workflows/api-stability.yml index 7384e498ad6..ae9f097feef 100644 --- a/.github/workflows/api-stability.yml +++ b/.github/workflows/api-stability.yml @@ -2,36 +2,69 @@ name: API Stability Check on: pull_request: - paths: - - "Sources/**" - - "test-server/**" - - ".github/workflows/api-stability.yml" - - Sentry.xcworkspace/** - - Sentry.xcodeproj/** - - "Package.swift" - - "scripts/build-xcframework-local.sh" + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple API stability checks on the same code, +# as these analyze public API changes and generate detailed breaking change reports. +# - We always cancel in-progress runs since this workflow only runs on pull requests, and only +# the latest commit's API changes matter for determining if the PR introduces breaking changes. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true jobs: + # This job detects if the PR contains changes that require running API stability checks. + # If yes, the job will output a flag that will be used by the next job to run the API stability checks. + # If no, the job will output a flag that will be used by the next job to skip running the API stability checks. + # At the end of this workflow, we run a check that validates that either all API stability checks passed or were + # skipped, called api-stability-required-check. + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + # Map a step output to a job output + outputs: + run_api_stability_for_prs: ${{ steps.changes.outputs.run_api_stability_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + api-stability: + name: Check API Stability (${{ matrix.version }}) + if: needs.files-changed.outputs.run_api_stability_for_prs == 'true' + needs: files-changed runs-on: macos-15 + strategy: + matrix: + version: [default, v9] steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - - run: ./scripts/ci-select-xcode.sh 16.3 + - run: ./scripts/ci-select-xcode.sh 16.4 - name: Generate HEAD SDK run: | - mv sdk_api.json sdk_api_base.json - make generate-public-api + if [ "${{ matrix.version }}" = "v9" ]; then + mv sdk_api_v9.json sdk_api_base.json + make generate-public-api CONFIG=V9 + mv sdk_api_v9.json sdk_api.json + else + mv sdk_api.json sdk_api_base.json + make generate-public-api + fi - name: Diagnose breaking changes run: | if diff -q "sdk_api_base.json" "sdk_api.json" > /dev/null; then - echo "No API changes detected." + echo "No API changes detected for ${{ matrix.version }} version." else - echo "❌ Public API changes are detected. If they’re intended run "make generate-public-api" and commit the changes." + echo "❌ Public API changes are detected for ${{ matrix.version }} version. If they're intended run "make generate-public-api" and commit the changes." diff "sdk_api_base.json" "sdk_api.json" || true xcrun --sdk iphoneos swift-api-digester \ -diagnose-sdk \ @@ -43,3 +76,28 @@ jobs: cat result.json exit 1 fi + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + # This check validates that either all API stability checks passed or were skipped, which allows us + # to make API stability checks a required check with only running the API stability checks when required. + # So, we don't have to run API stability checks, for example, for Changelog or ReadMe changes. + + api-stability-required-check: + needs: + [ + files-changed, + api-stability, + ] + name: API Stability + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the API stability check jobs has failed." && exit 1 diff --git a/.github/workflows/assemble-xcframework-variant.yml b/.github/workflows/assemble-xcframework-variant.yml index 8336b99df85..238e3880ca8 100644 --- a/.github/workflows/assemble-xcframework-variant.yml +++ b/.github/workflows/assemble-xcframework-variant.yml @@ -1,9 +1,9 @@ -name: "Assemble Sentry Cocoa XCFramework variant" +name: Assemble XCFramework Variant on: workflow_call: inputs: - name: + scheme: description: |- The Sentry project target to build an XCFramework slice for. Possible values: Sentry, SentrySwiftUI. @@ -51,13 +51,25 @@ on: required: false type: string + excluded-archs: + description: |- + The archs to exclude from the XCFramework. + required: false + type: string + + override-name: + description: |- + The name to use for the XCFramework. If not provided, the default name will be used. + required: false + type: string + jobs: assemble-xcframework-variant: - name: Assemble ${{inputs.name}}${{inputs.suffix}} XCFramework Variant + name: ${{ inputs.override-name || format('{0}{1}', inputs.scheme, inputs.suffix) }} runs-on: macos-14 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: ruby/setup-ruby@v1 if: ${{ inputs.signed }} @@ -78,30 +90,50 @@ jobs: - name: Get version id: get-version + env: + RELEASE_VERSION: ${{ inputs.release-version }} run: | - if [ -n "${{ inputs.release-version }}" ]; then - echo "VERSION=${{ inputs.release-version }}" >> $GITHUB_ENV + if [ -n "$RELEASE_VERSION" ]; then + echo "VERSION=$RELEASE_VERSION" >> $GITHUB_ENV else echo "VERSION=$(grep MARKETING_VERSION Sources/Configuration/Versioning.xcconfig | cut -d ' ' -f 3)+${{ github.sha }}" >> $GITHUB_ENV fi shell: sh + - name: Set XCFramework name + id: set-xcframework-name + env: + OVERRIDE_NAME: ${{ inputs.override-name }} + SCHEME: ${{ inputs.scheme }} + SUFFIX: ${{ inputs.suffix }} + run: | + if [ -n "$OVERRIDE_NAME" ]; then + echo "XCFRAMEWORK_NAME=$OVERRIDE_NAME" >> $GITHUB_ENV + else + echo "XCFRAMEWORK_NAME=$SCHEME$SUFFIX" >> $GITHUB_ENV + fi + - name: Compute cache key + env: + SDKS: ${{ inputs.sdks }} + VARIANT_ID: ${{ inputs.variant-id }} + SIGNED: ${{ inputs.signed }} + VERSION: ${{ env.VERSION }} run: | - sdks_string=${{inputs.sdks}} - sdks_string_slugified=${sdks_string//,/_} - echo "SENTRY_XCFRAMEWORK_CACHE_KEY=${{runner.os}}-xcframework-${{inputs.variant-id}}-$sdks_string_slugified-${{inputs.signed}}-${{env.VERSION}}-${{hashFiles('Sources/**')}}-${{hashFiles('Sentry.xcodeproj/**')}}" >> $GITHUB_ENV + sdks_string="$SDKS" + sdks_string_slugified="${sdks_string//,/_}" + echo "SENTRY_XCFRAMEWORK_CACHE_KEY=${{runner.os}}-xcframework-$VARIANT_ID-$sdks_string_slugified-$SIGNED-$VERSION-${{hashFiles('Sources/**')}}-${{hashFiles('Sentry.xcodeproj/**')}}" >> $GITHUB_ENV - name: Restore XCFramework cache id: cache-xcframework uses: actions/cache@v4 with: key: ${{env.SENTRY_XCFRAMEWORK_CACHE_KEY}} - path: ${{inputs.name}}${{inputs.suffix}}.xcframework.zip + path: ${{env.XCFRAMEWORK_NAME}}.xcframework.zip - name: Download ${{inputs.variant-id}} Slices if: steps.cache-xcframework.outputs.cache-hit != 'true' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: pattern: xcframework-${{inputs.variant-id}}-slice-* path: xcframework-slices @@ -112,26 +144,69 @@ jobs: find xcframework-slices -type f -print0 | xargs -t0I @ unzip @ -d xcframework-slices shell: bash + - name: Remove excluded archs + if: ${{ steps.cache-xcframework.outputs.cache-hit != 'true' && inputs.excluded-archs != '' }} + env: + EXCLUDED_ARCHS: ${{ inputs.excluded-archs }} + run: ./scripts/remove-architectures.sh xcframework-slices/ "$EXCLUDED_ARCHS" + shell: bash + - name: Assemble XCFramework if: steps.cache-xcframework.outputs.cache-hit != 'true' - run: ./scripts/assemble-xcframework.sh "${{inputs.name}}" "${{inputs.suffix}}" "${{inputs.configuration-suffix}}" "${{inputs.sdks}}" "/Users/runner/work/sentry-cocoa/sentry-cocoa/xcframework-slices/SDK_NAME.xcarchive" + env: + SCHEME: ${{ inputs.scheme }} + SUFFIX: ${{ inputs.suffix }} + CONFIGURATION_SUFFIX: ${{ inputs.configuration-suffix }} + SDKS: ${{ inputs.sdks }} + run: ./scripts/assemble-xcframework.sh "$SCHEME" "$SUFFIX" "$CONFIGURATION_SUFFIX" "$SDKS" "/Users/runner/work/sentry-cocoa/sentry-cocoa/xcframework-slices/SDK_NAME.xcarchive" + shell: bash + + - name: Rename XCFramework + env: + OVERRIDE_NAME: ${{ inputs.override-name }} + XCFRAMEWORK_NAME: ${{ env.XCFRAMEWORK_NAME }} + SCHEME: ${{ inputs.scheme }} + SUFFIX: ${{ inputs.suffix }} + if: ${{ inputs.override-name != '' }} + run: | + mv "${{env.SCHEME}}${{env.SUFFIX}}.xcframework" "${{env.OVERRIDE_NAME}}.xcframework" shell: bash + - name: Validate XCFramework structure + # only validate if the xcframework was not cached + if: steps.cache-xcframework.outputs.cache-hit != 'true' + run: ./scripts/validate-xcframework-format.sh "${{env.XCFRAMEWORK_NAME}}.xcframework" + shell: bash + env: + XCFRAMEWORK_NAME: ${{ env.XCFRAMEWORK_NAME }} + - name: Zip XCFramework if: steps.cache-xcframework.outputs.cache-hit != 'true' - run: ./scripts/compress-xcframework.sh ${{inputs.signed && '--sign' || '--not-signed'}} ${{inputs.name}}${{inputs.suffix}} + env: + SIGNED: ${{ inputs.signed }} + SCHEME: ${{ inputs.scheme }} + SUFFIX: ${{ inputs.suffix }} + run: | + if [ "$SIGNED" = "true" ]; then + ./scripts/compress-xcframework.sh --sign "${{env.XCFRAMEWORK_NAME}}" + else + ./scripts/compress-xcframework.sh --not-signed "${{env.XCFRAMEWORK_NAME}}" + fi shell: bash - name: Cache XCFramework uses: actions/cache@v4 with: key: ${{env.SENTRY_XCFRAMEWORK_CACHE_KEY}} - path: ${{inputs.name}}${{inputs.suffix}}.xcframework.zip + path: ${{env.XCFRAMEWORK_NAME}}.xcframework.zip - name: Upload XCFramework uses: actions/upload-artifact@v4 with: overwrite: true - name: xcframework-${{github.sha}}-${{inputs.variant-id}} + name: xcframework-${{github.sha}}-${{inputs.override-name || inputs.variant-id}} if-no-files-found: error - path: ${{inputs.name}}${{inputs.suffix}}.xcframework.zip + path: ${{env.XCFRAMEWORK_NAME}}.xcframework.zip + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh diff --git a/.github/workflows/auto-update-tools.yml b/.github/workflows/auto-update-tools.yml index 141d4ad99ba..2088b9c2d89 100644 --- a/.github/workflows/auto-update-tools.yml +++ b/.github/workflows/auto-update-tools.yml @@ -12,13 +12,6 @@ on: - cron: "0 0 * * *" workflow_dispatch: pull_request: - paths: - - ".github/workflows/auto-update-tools.yml" - - "Brewfile*" - - "Makefile" - - "scripts/.clang-format-version" - - "scripts/.swiftlint-version" - - ".pre-commit-config.yaml" # Permissions configuration: # - 'contents: write' is required to allow the workflow to commit changes to the repository @@ -43,11 +36,33 @@ concurrency: cancel-in-progress: true jobs: + # This job detects if the PR contains changes that require running auto-update-tools. + # If yes, the job will output a flag that will be used by the next job to run the auto-update-tools. + # If no, the job will output a flag that will be used by the next job to skip running the auto-update-tools. + # At the end of this workflow, we run a check that validates that either auto_update_tools-required-check passed or were + # skipped, which is called auto_update_tools-required-check. + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + # Map a step output to a job output + outputs: + run_auto_update_tools_for_prs: ${{ steps.changes.outputs.run_auto_update_tools_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + auto-update-tools: + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_auto_update_tools_for_prs == 'true' + needs: files-changed runs-on: macos-15 steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Update Homebrew run: brew update @@ -89,3 +104,28 @@ jobs: title: "chore(deps): Update swiftlint version" sign-commits: true base: main + + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + # This check validates that either auto-update-tools passed or was skipped, which allows us + # to make auto-update-tools a required check with only running the auto-update-tools when required. + # So, we don't have to run auto-update-tools, for example, for unrelated changes. + auto_update_tools-required-check: + needs: + [ + files-changed, + auto-update-tools, + ] + name: Auto Update Tools + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the auto-update-tools jobs has failed." && exit 1 diff --git a/.github/workflows/benchmarking.yml b/.github/workflows/benchmarking.yml index f90b9676b3d..9f2ee182d17 100644 --- a/.github/workflows/benchmarking.yml +++ b/.github/workflows/benchmarking.yml @@ -5,40 +5,51 @@ on: - main pull_request: - paths: - # test changes to Sentry SDK sources - - "Sources/**" - # test changes to benchmarking implementation - - "Samples/iOS-Swift/**" - - ".github/workflows/benchmarking.yml" - - ".sauce/benchmarking-config.yml" - - "fastlane/**" - - "scripts/ci-select-xcode.sh" - - "Samples/iOS-Swift/iOS-Swift.yml" - - "Samples/iOS-Swift/iOS-Swift.xcconfig" - - "Samples/iOS-Swift/iOS-SwiftClilp.xcconfig" - - "Samples/iOS-Swift/iOS-Benchmarking.xcconfig" - - "scripts/build-xcframework-slice.sh" - - "scripts/assemble-xcframework.sh" - - ".github/workflows/build-xcframework-variant-slices.yml" - - ".github/workflows/assemble-xcframework-variant.yml" - -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple benchmark runs on the same code, +# as benchmarks are extremely resource-intensive and require dedicated device time on SauceLabs. +# - For pull requests, we cancel in-progress runs when new commits are pushed to avoid wasting +# expensive external testing resources and provide timely performance feedback. +# - For main branch pushes, we never cancel benchmarks to ensure we have complete performance +# baselines for every main branch commit, which are critical for performance regression detection. concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_benchmarking_for_prs: ${{ steps.changes.outputs.run_benchmarking_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + build-benchmark-test-target: - name: Build app and test runner - runs-on: macos-13 + name: Build App and Test Runner + # Run the job only for PRs with related changes or non-PR events. + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_benchmarking_for_prs == 'true' + needs: files-changed + runs-on: macos-14 steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 15.2 + - uses: actions/checkout@v5 + - run: ./scripts/ci-select-xcode.sh 15.4 - uses: ruby/setup-ruby@v1 with: bundler-cache: true + - name: Install old xcodegen + # Install xcodegen 2.43.0 for since newer versions don't work with Xcode older than Xcode 16 + # We need to set HOMEBREW_DEVELOPER=1 to allow installing from a local formula + run: | + HOMEBREW_DEVELOPER=1 brew install --formula ./scripts/xcodegen.rb + brew pin xcodegen - run: make init-ci-build - run: make xcode-ci - name: Install SentryCli @@ -86,18 +97,27 @@ jobs: path: | **/Debug-iphoneos/iOS-Swift.app **/Debug-iphoneos/iOS-Benchmarking-Runner.app + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh run-ui-tests-with-sauce: - name: Run benchmarks on Sauce Labs + name: Run Benchmarks ${{matrix.suite}} + # Run the job only for PRs with related changes or non-PR events. + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_benchmarking_for_prs == 'true' runs-on: ubuntu-latest - needs: build-benchmark-test-target + needs: + [ + files-changed, + build-benchmark-test-target, + ] strategy: fail-fast: false matrix: suite: ["High-end device", "Mid-range device", "Low-end device"] steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 + - uses: actions/checkout@v5 + - uses: actions/download-artifact@v5 with: name: DerivedData-Xcode - run: npm install -g saucectl@0.186.0 @@ -119,11 +139,16 @@ jobs: id: should-retry-test # Note: We need to use always() here, because the previous run step might be marked as failed. if: ${{ always() && steps.run-benchmarks-in-sauce-lab.outcome == 'failure' }} - uses: actions/github-script@v7 + uses: actions/github-script@v8 env: SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} with: + # Retry Logic: This step only runs when the benchmark test has failed. + # We determine if the failure was due to SauceLabs infrastructure issues + # (which can be fixed by retrying) or legitimate test failures (which cannot). + # SauceLabs internal errors frequently cause CI failures that can be resolved + # by re-running the test. See scripts/saucelabs-helpers.js for detailed logic. script: | const fs = require('fs'); const { execSync } = require('child_process'); @@ -171,3 +196,26 @@ jobs: --config .sauce/benchmarking-config.yml \ --tags benchmark \ --verbose + + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + benchmarking-required-check: + needs: + [ + files-changed, + build-benchmark-test-target, + run-ui-tests-with-sauce, + ] + name: Benchmarking + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the benchmark jobs has failed." && exit 1 diff --git a/.github/workflows/build-xcframework-variant-slices.yml b/.github/workflows/build-xcframework-variant-slices.yml index 5f7fc21c2ee..8f401273e08 100644 --- a/.github/workflows/build-xcframework-variant-slices.yml +++ b/.github/workflows/build-xcframework-variant-slices.yml @@ -1,4 +1,4 @@ -name: "Build Sentry Cocoa XCFramework variant slices" +name: Build XCFramework Slice on: workflow_call: @@ -65,7 +65,7 @@ jobs: sdk: ${{ fromJson(inputs.sdk-list) }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # We have to compile on Xcode 15.2 because compiling on Xcode 15.4 fails with # Data+SentryTracing.swift:21:62: error: 'ReadingOptions' aliases 'Foundation.ReadingOptions' @@ -144,3 +144,7 @@ jobs: name: raw-build-output-build-xcframework-${{inputs.variant-id}}-${{matrix.sdk}} path: | *.log + + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2b8dec3eda1..1bd18c7fd3c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -6,32 +6,44 @@ on: - release/** pull_request: - paths: - - "Sources/**" - - "test-server/**" - - "Samples/**" - - ".github/workflows/build.yml" - - "fastlane/**" - - "scripts/ci-select-xcode.sh" - - Sentry.xcworkspace/** - - Sentry.xcodeproj/** - - Gemfile.lock - - "Package.swift" - -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple build runs of the same code, +# which would waste CI resources without providing additional value. +# - For pull requests, we cancel in-progress builds when new commits are pushed since only the +# latest commit's build results matter for merge decisions. +# - For main branch pushes, we never cancel builds to ensure all release and sample builds complete, +# as broken builds on main could block releases and affect downstream consumers. concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_build_for_prs: ${{ steps.changes.outputs.run_build_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + # We had issues that the release build was broken on main. # With this we catch potential issues already in the PR. ios-swift-release: name: Release Build of iOS Swift + # Run the job only for PRs with related changes or non-PR events. + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' + needs: files-changed runs-on: macos-15 steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 16.3 + - uses: actions/checkout@v5 + - run: ./scripts/ci-select-xcode.sh 16.4 - uses: ruby/setup-ruby@v1 with: bundler-cache: true @@ -48,8 +60,14 @@ jobs: MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} run: bundle exec fastlane build_ios_swift + - name: Debug Xcode environment + if: ${{ failure() || cancelled() }} + run: ./scripts/ci-diagnostics.sh + build-sample: - name: Sample ${{ matrix.scheme }} + name: Sample ${{ matrix.scheme }} ${{ matrix.config }} + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' + needs: files-changed runs-on: macos-15 strategy: fail-fast: false @@ -57,28 +75,47 @@ jobs: # other sample projects are built in ui-tests include: - scheme: macOS-Swift + config: Debug - scheme: iOS13-Swift + config: Debug - scheme: watchOS-Swift WatchKit App + config: Debug - scheme: macOS-SwiftUI + config: Debug - scheme: SessionReplay-CameraTest + config: Debug + - scheme: visionOS-Swift + config: Debug + - scheme: iOS-Swift + config: DebugV9 + - scheme: macOS-Swift + config: DebugV9 + - scheme: tvOS-Swift + config: DebugV9 - scheme: visionOS-Swift + config: DebugV9 + - scheme: iOS-SwiftUI + config: DebugV9 + - scheme: iOS-ObjectiveC + config: DebugV9 steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 16.3 + - uses: actions/checkout@v5 + - run: ./scripts/ci-select-xcode.sh 16.4 - run: make init-ci-build - run: make xcode-ci # Note: Due to complexity in implementing the CODE_SIGNING_ALLOWED flag in the sentry-xcodebuild.sh script, # we did not yet migrate this step to use the script yet. - run: >- - env NSUnbufferedIO=YES - xcodebuild + set -o pipefail && NSUnbufferedIO=YES xcodebuild -workspace Sentry.xcworkspace -scheme '${{matrix.scheme}}' - -configuration Debug + -configuration '${{matrix.config}}' CODE_SIGNING_ALLOWED="NO" - build + build 2>&1 + | tee raw-build-output.log + | xcbeautify --preserve-unbeautified - name: Archiving Raw Build Logs uses: actions/upload-artifact@v4 @@ -87,105 +124,190 @@ jobs: name: raw-build-output-scheme-${{matrix.scheme}} path: | raw-build-output.log + + - name: Debug Xcode environment + if: ${{ failure() || cancelled() }} + run: ./scripts/ci-diagnostics.sh + build-spm: name: Build with SPM runs-on: macos-15 # Don't run this on release branches, cause the SPM Package.swift points to the unreleased versions. - if: startsWith(github.ref, 'refs/heads/release/') == false + if: startsWith(github.ref, 'refs/heads/release/') == false && (github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true') + needs: files-changed steps: - - uses: actions/checkout@v4 - # Only watchOS is compiling with SPM so far, the rest of the targets need profiling support which is still a work in progress due to the ObjC++ usage - - run: rm -r Sentry.xcodeproj && rm -r Sentry.xcworkspace && EXPERIMENTAL_SPM_BUILDS=1 xcodebuild build -scheme SentrySPM -sdk watchos -destination 'generic/platform=watchOS' + - uses: actions/checkout@v5 + + - run: ./scripts/ci-select-xcode.sh 16.4 shell: sh + - run: rm -r Sentry.xcodeproj && rm -r Sentry.xcworkspace + - run: set -o pipefail && NSUnbufferedIO=YES EXPERIMENTAL_SPM_BUILDS=1 xcodebuild build -scheme SentrySPM -sdk watchos -destination 'generic/platform=watchOS' | tee raw-build-output-spm-watchos.log | xcbeautify + shell: sh + - run: set -o pipefail && NSUnbufferedIO=YES EXPERIMENTAL_SPM_BUILDS=1 xcodebuild build -scheme SentrySPM -sdk iphoneos -destination 'generic/platform=iphoneos' | tee raw-build-output-spm-iphoneos.log | xcbeautify + shell: sh + + - name: Upload SPM Build Logs + uses: actions/upload-artifact@v4 + if: ${{ failure() || cancelled() }} + with: + name: raw-build-output-spm + path: | + raw-build-output-spm-watchos.log + raw-build-output-spm-iphoneos.log + + - name: Debug Xcode environment + if: ${{ failure() || cancelled() }} + run: ./scripts/ci-diagnostics.sh build-v9: name: Build SDK v9 + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' + needs: files-changed runs-on: macos-15 steps: - - uses: actions/checkout@v4 - - run: ./scripts/sentry-xcodebuild.sh --platform iOS --os latest --device "iPhone 16" --command build --configuration DebugV9 + - uses: actions/checkout@v5 + - run: ./scripts/ci-select-xcode.sh 16.4 + - run: | + ./scripts/sentry-xcodebuild.sh \ + --platform iOS \ + --os 18.4 \ + --command build \ + --device "iPhone 16 Pro" \ + --configuration DebugV9 + - name: Archiving Raw Build Logs + uses: actions/upload-artifact@v4 + if: ${{ failure() || cancelled() }} + with: + name: raw-build-output-v9 + path: | + raw-build-output.log + - name: Debug Xcode environment + if: ${{ failure() || cancelled() }} + run: ./scripts/ci-diagnostics.sh check-debug-without-UIKit: name: Check no UIKit linkage (DebugWithoutUIKit) - runs-on: macos-13 + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' + needs: files-changed + runs-on: macos-15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 + + - run: ./scripts/ci-select-xcode.sh 16.4 + - name: Build for Debug run: | ./scripts/sentry-xcodebuild.sh \ --platform iOS \ - --os latest \ + --os 18.4 \ --ref ${{ github.ref }} \ --command build \ - --device "iPhone 14" \ + --device "iPhone 16 Pro" \ --configuration DebugWithoutUIKit \ --derived-data uikit-check-build + - name: Ensure UIKit is not linked run: ./scripts/check-uikit-linkage.sh DebugWithoutUIKit uikit-check-build unlinked SentryWithoutUIKit + - name: Debug Xcode environment + if: ${{ failure() || cancelled() }} + run: ./scripts/ci-diagnostics.sh + check-release-without-UIKit: name: Check no UIKit linkage (ReleaseWithoutUIKit) - runs-on: macos-13 + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' + needs: files-changed + runs-on: macos-15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 + + - run: ./scripts/ci-select-xcode.sh 16.4 + - name: Build for Release run: | ./scripts/sentry-xcodebuild.sh \ --platform iOS \ - --os latest \ + --os 18.4 \ --ref ${{ github.ref }} \ --command build \ - --device "iPhone 14" \ + --device "iPhone 16 Pro" \ --configuration ReleaseWithoutUIKit \ --derived-data uikit-check-build + - name: Ensure UIKit is not linked run: ./scripts/check-uikit-linkage.sh ReleaseWithoutUIKit uikit-check-build unlinked SentryWithoutUIKit + - name: Debug Xcode environment + if: ${{ failure() || cancelled() }} + run: ./scripts/ci-diagnostics.sh + check-debug-with-UIKit: name: Check UIKit linkage (Debug) - runs-on: macos-13 + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' + needs: files-changed + runs-on: macos-15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 + + - run: ./scripts/ci-select-xcode.sh 16.4 + - name: Build for Debug run: | ./scripts/sentry-xcodebuild.sh \ --platform iOS \ - --os latest \ + --os 18.4 \ --ref ${{ github.ref }} \ --command build \ - --device "iPhone 14" \ + --device "iPhone 16 Pro" \ --configuration Debug \ --derived-data uikit-check-build + - name: Ensure UIKit is linked run: ./scripts/check-uikit-linkage.sh Debug uikit-check-build linked Sentry + - name: Debug Xcode environment + if: ${{ failure() || cancelled() }} + run: ./scripts/ci-diagnostics.sh + check-release-with-UIKit: name: Check UIKit linkage (Release) - runs-on: macos-13 + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' + needs: files-changed + runs-on: macos-15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 + + - run: ./scripts/ci-select-xcode.sh 16.4 + - name: Build for Release run: | ./scripts/sentry-xcodebuild.sh \ --platform iOS \ - --os latest \ + --os 18.4 \ --ref ${{ github.ref }} \ --command build \ - --device "iPhone 14" \ + --device "iPhone 16 Pro" \ --configuration Release \ --derived-data uikit-check-build + - name: Ensure UIKit is linked run: ./scripts/check-uikit-linkage.sh Release uikit-check-build linked Sentry + - name: Debug Xcode environment + if: ${{ failure() || cancelled() }} + run: ./scripts/ci-diagnostics.sh + # The compiler only evaluates SentryAsyncSafeLogs that get printed based on the SENTRY_ASYNC_SAFE_LOG_LEVEL. # So if the level is set to error, which is the default, and a SENTRY_ASYNC_SAFE_LOG_DEBUG has a compiler error, # you only get the compiler error when setting the SENTRY_ASYNC_SAFE_LOG_LEVEL to SENTRY_ASYNC_SAFE_LOG_LEVEL_DEBUG or lower. check-compiling-async-safe-logs: name: Check compiling Async Safe Logs + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_build_for_prs == 'true' + needs: files-changed runs-on: macos-15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 # If the SentryAsyncSafeLog doesn't contain the SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR this fails. - name: Async Safe Log Level is Error @@ -196,14 +318,44 @@ jobs: sed -i '' 's/#define SENTRY_ASYNC_SAFE_LOG_LEVEL SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR/#define SENTRY_ASYNC_SAFE_LOG_LEVEL SENTRY_ASYNC_SAFE_LOG_LEVEL_TRACE/' Sources/Sentry/SentryAsyncSafeLog.h shell: bash - - run: ./scripts/ci-select-xcode.sh 16.3 + - run: ./scripts/ci-select-xcode.sh 16.4 - name: Build for Debug run: | ./scripts/sentry-xcodebuild.sh \ --platform iOS \ - --os latest \ + --os 18.4 \ --ref ${{ github.ref }} \ --command build \ - --device "iPhone 16" \ + --device "iPhone 16 Pro" \ --configuration Debug + + - name: Debug Xcode environment + if: ${{ failure() || cancelled() }} + run: ./scripts/ci-diagnostics.sh + + build-required-check: + needs: + [ + files-changed, + ios-swift-release, + build-sample, + build-spm, + build-v9, + check-debug-without-UIKit, + check-release-without-UIKit, + check-debug-with-UIKit, + check-release-with-UIKit, + check-compiling-async-safe-logs, + ] + name: Build + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the build jobs has failed." && exit 1 diff --git a/.github/workflows/changes-in-high-risk-code.yml b/.github/workflows/changes-in-high-risk-code.yml index 4f8e16d95d9..0bb747ac8d6 100644 --- a/.github/workflows/changes-in-high-risk-code.yml +++ b/.github/workflows/changes-in-high-risk-code.yml @@ -2,21 +2,25 @@ name: Changes In High Risk Code on: pull_request: -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple high-risk code analysis runs, +# as these detect changes to critical code paths and trigger additional validation workflows. +# - We always cancel in-progress runs since this workflow only runs on pull requests, and only +# the latest commit's high-risk code changes matter for determining which additional tests to run. concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: files-changed: - name: Detect changed files + name: Detect File Changes runs-on: ubuntu-latest # Map a step output to a job output outputs: high_risk_code: ${{ steps.changes.outputs.high_risk_code }} high_risk_code_files: ${{ steps.changes.outputs.high_risk_code_files }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Get changed files id: changes uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 @@ -29,12 +33,13 @@ jobs: list-files: csv validate-high-risk-code: + name: Validate High-Risk Code if: needs.files-changed.outputs.high_risk_code == 'true' needs: files-changed runs-on: ubuntu-latest steps: - name: Remove previous comments - uses: actions/github-script@v7 + uses: actions/github-script@v8 with: script: | core.debug('Listing comments') @@ -59,7 +64,7 @@ jobs: } } - name: Comment on PR to notify of changes in high risk files - uses: actions/github-script@v7 + uses: actions/github-script@v8 env: high_risk_code: ${{ needs.files-changed.outputs.high_risk_code_files }} with: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e22f4b94738..94e90dc9450 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -1,4 +1,4 @@ -name: "CodeQL" +name: CodeQL on: push: @@ -7,17 +7,39 @@ on: branches: - main schedule: - - cron: "40 4 * * 6" + - cron: "40 4 * * 6" # Weekly scheduled run to catch issues regardless of changes -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple CodeQL security analysis runs, +# as these are comprehensive security scans that shouldn't run simultaneously. +# - For pull requests, we cancel in-progress runs when new commits are pushed since only the +# latest security analysis results matter for identifying potential vulnerabilities. +# - For main branch pushes and scheduled runs, we never cancel security analysis to ensure +# complete security validation and maintain our security baseline with weekly scheduled scans. concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_codeql_analysis_for_prs: ${{ steps.changes.outputs.run_codeql_analysis_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + analyze: - name: Analyze - runs-on: macos-13 + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_codeql_analysis_for_prs == 'true' + needs: files-changed + name: Analyze (${{ matrix.language }}) + runs-on: macos-14 strategy: fail-fast: false @@ -26,7 +48,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Initialize CodeQL uses: github/codeql-action/init@v3 @@ -38,10 +60,35 @@ jobs: -workspace Sentry.xcworkspace \ -scheme Sentry \ -configuration Release \ - -destination platform="iOS Simulator,OS=latest,name=iPhone 14 Pro" \ + -destination platform="iOS Simulator,OS=16.4,name=iPhone 14 Pro" \ build 2>&1 | tee raw-analyze-output.log | xcbeautify - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 + + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + # This check validates that either analyze passed or was skipped, which allows us + # to make CodeQL analysis a required check with only running the analysis when required. + # So, we don't have to run CodeQL analysis, for example, for unrelated changes. + codeql_analysis-required-check: + needs: + [ + files-changed, + analyze, + ] + name: Analyze + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the CodeQL analysis jobs has failed." && exit 1 diff --git a/.github/workflows/create-issue-for-unreferenced-pr.yml b/.github/workflows/create-issue-for-unreferenced-pr.yml new file mode 100644 index 00000000000..cfe192e0689 --- /dev/null +++ b/.github/workflows/create-issue-for-unreferenced-pr.yml @@ -0,0 +1,103 @@ +# This GitHub Action workflow checks if a new or updated pull request +# references a GitHub issue in its title or body. If no reference is found, +# it automatically creates a new issue. This helps ensure all work is +# tracked, especially when syncing with tools like Linear. + +name: Create issue for unreferenced PR + +# This action triggers on pull request events +on: + pull_request: + types: [opened, edited, reopened, synchronize, ready_for_review] + +# Cancel in progress workflows on pull_requests. +# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + check_for_issue_reference: + runs-on: ubuntu-latest + steps: + - name: Check PR Body and Title for Issue Reference + uses: actions/github-script@v8 + with: + script: | + const pr = context.payload.pull_request; + if (!pr) { + core.setFailed('Could not get PR from context.'); + return; + } + + // Don't create an issue for draft PRs + if (pr.draft) { + console.log(`PR #${pr.number} is a draft, skipping issue creation.`); + return; + } + + // Check if the PR is already approved + const reviewsResponse = await github.rest.pulls.listReviews({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr.number, + }); + + if (reviewsResponse.data.some(review => review.state === 'APPROVED')) { + console.log(`PR #${pr.number} is already approved, skipping issue creation.`); + return; + } + + const prBody = pr.body || ''; + const prTitle = pr.title || ''; + const prAuthor = pr.user.login; + const prUrl = pr.html_url; + const prNumber = pr.number; + + // Regex for GitHub issue references (e.g., #123, fixes #456) + const issueRegexGitHub = /(?:(?:close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)\s*)?#\d+/i; + + // Regex for Linear issue references (e.g., ENG-123, resolves ENG-456) + const issueRegexLinear = /(?:(?:close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)\s*)?[A-Z]+-\d+/i; + + const contentToCheck = `${prTitle} ${prBody}`; + const hasIssueReference = issueRegexGitHub.test(contentToCheck) || issueRegexLinear.test(contentToCheck); + + if (hasIssueReference) { + console.log(`PR #${prNumber} contains a valid issue reference.`); + return; + } + + core.warning(`PR #${prNumber} does not have an issue reference. Creating a new issue so it can be tracked in Linear.`); + + // Construct the title and body for the new issue + const issueTitle = `${prTitle}`; + const issueBody = `> [!NOTE] + > The pull request "[${prTitle}](${prUrl})" was created by @${prAuthor} but did not reference an issue. Therefore this issue was created for better visibility in external tools like Linear. + + ${prBody} + `; + + // Create the issue using the GitHub API + const newIssue = await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: issueTitle, + body: issueBody, + assignees: [prAuthor] + }); + + const issueID = newIssue.data.number; + console.log(`Created issue #${issueID}.`); + + // Update the PR body to reference the new issue + const updatedPrBody = `${prBody}\n\nCloses #${issueID}`; + + await github.rest.pulls.update({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + body: updatedPrBody + }); + + console.log(`Updated PR #${prNumber} to reference newly created issue #${issueID}.`); diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index 000b75ff3ee..ec59d740892 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -4,6 +4,16 @@ on: pull_request: types: [opened, synchronize, reopened, edited, ready_for_review] +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple Danger runs on the same PR, +# as Danger performs PR validation and comment generation that should be based on the latest code. +# - We always cancel in-progress runs since this workflow only runs on pull requests, and only +# the latest commit's validation results matter for providing accurate PR feedback and reviews. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: danger: + name: Danger uses: getsentry/github-workflows/.github/workflows/danger.yml@v2 diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index 5b274bb4a2a..4583cb9d51b 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -1,33 +1,48 @@ -name: CocoaPods Integration Tests +name: Test CocoaPods on: push: branches: - main pull_request: - paths: - - ".github/workflows/integration-test.yml" - - "*.xcodeproj" - - "*.xcworkspace" - - "Samples/iOS-Cocoapods-*/**" - - "scripts/ci-select-xcode.sh" - - "Sources/**" - -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple CocoaPods integration tests, +# as these tests involve complex dependency resolution and build processes. +# - For pull requests, we cancel in-progress runs when new commits are pushed since only the +# latest integration test results matter for validating CocoaPods compatibility. +# - For main branch pushes, we never cancel integration tests to ensure our CocoaPods +# integration remains functional for all downstream consumers relying on our library. concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: - cocoapods: - name: Integration Test + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_integration_test_for_prs: ${{ steps.changes.outputs.run_integration_test_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + + test: + name: CocoaPods Integration + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_integration_test_for_prs == 'true' + needs: files-changed runs-on: macos-15 steps: - name: Checkout Repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Select Xcode - run: ./scripts/ci-select-xcode.sh 16.2 + run: ./scripts/ci-select-xcode.sh 16.4 - name: Setup Ruby uses: ruby/setup-ruby@32110d4e311bd8996b2a82bf2a43b714ccc91777 # v1.221.0 @@ -44,3 +59,29 @@ jobs: with: name: integration-test-iOS-Cocoapods-Swift6.xcresult path: Samples/iOS-Cocoapods-Swift6/fastlane/test_results/results.xcresult + + - name: Run CI Diagnostics + if: failure() + shell: bash + run: ./scripts/ci-diagnostics.sh + + # This check validates that either all integration tests passed or were skipped, which allows us + # to make integration tests a required check with only running the integration tests when required. + # So, we don't have to run integration tests, for example, for Changelog or ReadMe changes. + integration_test-required-check: + needs: + [ + files-changed, + test, + ] + name: Integration Test + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the integration test jobs has failed." && exit 1 diff --git a/.github/workflows/lint-clang-formatting.yml b/.github/workflows/lint-clang-formatting.yml index e9315874bac..07854da1e67 100644 --- a/.github/workflows/lint-clang-formatting.yml +++ b/.github/workflows/lint-clang-formatting.yml @@ -1,37 +1,48 @@ -name: Check Code Formatting +name: Lint Clang + on: push: branches: - main - paths: - - "**/*.h" - - "**/*.hpp" - - "**/*.c" - - "**/*.cpp" - - "**/*.m" - - "**/*.mm" - - ".github/workflows/lint-clang-formatting.yml" - - ".clang-format" pull_request: - paths: - - "**/*.h" - - "**/*.hpp" - - "**/*.c" - - "**/*.cpp" - - "**/*.m" - - "**/*.mm" - - ".github/workflows/lint-clang-formatting.yml" - - ".clang-format" + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, +# as linting checks are deterministic and don't require parallel validation. +# - For pull requests, we cancel in-progress runs when new commits are pushed since only the +# latest linting matters for merge decisions. +# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent style +# standards across the entire project. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: - format-code: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_lint_clang_formatting_for_prs: ${{ steps.changes.outputs.run_lint_clang_formatting_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + + lint: # While ubuntu runners have clang-format preinstalled, they use an older version. We want to use the most recent one, # that we can easily install locally via brew. - name: Check Formatting of Clang Format + name: Lint + # Run the job only for PRs with related changes or non-PR events. + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_clang_formatting_for_prs == 'true' + needs: files-changed runs-on: macos-15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Install tooling run: make init-ci-format @@ -48,3 +59,25 @@ jobs: else echo "✅ All code is formatted correctly." fi + + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + lint_clang_formatting-required-check: + needs: + [ + files-changed, + lint, + ] + name: Lint Clang + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the clang formatting check jobs has failed." && exit 1 diff --git a/.github/workflows/lint-cocoapods-specs.yml b/.github/workflows/lint-cocoapods-specs.yml new file mode 100644 index 00000000000..81fa144d040 --- /dev/null +++ b/.github/workflows/lint-cocoapods-specs.yml @@ -0,0 +1,93 @@ +name: Lint CocoaPods Specs + +on: + push: + branches: + - main + pull_request: + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, +# as linting checks are deterministic and don't require parallel validation. +# - For pull requests, we cancel in-progress runs when new commits are pushed since only the +# latest linting matters for merge decisions. +# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent style +# standards across the entire project. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_lint_cocoapods_specs_for_prs: ${{ steps.changes.outputs.run_lint_cocoapods_specs_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + + lint-podspec: + name: ${{ matrix.podspec}} ${{ matrix.library_type }} ${{ matrix.platform}} + # Run the job only for PRs with related changes or non-PR events. + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_cocoapods_specs_for_prs == 'true' + needs: files-changed + runs-on: macos-14 + strategy: + fail-fast: false + matrix: + podspec: ["Sentry", "SentrySwiftUI"] + platform: ["ios", "macos", "tvos", "watchos"] + library_type: ["dynamic", "static"] + + steps: + - uses: actions/checkout@v5 + - run: ./scripts/ci-select-xcode.sh 15.4 + # We need to update the spec-repo, because it can happen that it is not up to date and then the lint fails. + - run: pod repo update + - name: Validate Podspec + run: ./scripts/pod-lib-lint.sh ${{ matrix.platform }} ${{ matrix.podspec}} ${{ matrix.library_type}} + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + lint-hybrid-sdk-podspec: + name: Sentry/HybridSDK + # Run the job only for PRs with related changes or non-PR events. + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_cocoapods_specs_for_prs == 'true' + needs: files-changed + runs-on: macos-14 + + steps: + - uses: actions/checkout@v5 + - run: ./scripts/ci-select-xcode.sh 15.4 + - run: pod repo update + - name: Validate HybridPod Podspec + run: pod lib lint ./Tests/HybridSDKTest/HybridPod.podspec --allow-warnings --verbose --platforms=ios "--include-podspecs={Sentry.podspec}" + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + lint_cocoapods_Specs-required-check: + needs: + [ + files-changed, + lint-podspec, + lint-hybrid-sdk-podspec, + ] + name: Lint CocoaPods Specs + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the CocoaPods specs linting jobs has failed." && exit 1 diff --git a/.github/workflows/lint-dprint-formatting.yml b/.github/workflows/lint-dprint-formatting.yml new file mode 100644 index 00000000000..7242d7acd3c --- /dev/null +++ b/.github/workflows/lint-dprint-formatting.yml @@ -0,0 +1,66 @@ +# We want to run dprint for only the files it checks without running the other linters, which are +# expensive. For example, dprint should run for markdown changes, but pod lib lint doesn't need to +# run for markdown changes. Therefore, we run it in an extra workflow. + +name: Lint dprint + +on: + push: + branches: + - main + + pull_request: + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, +# as linting checks are deterministic and don't require parallel validation. +# - For pull requests, we cancel in-progress runs when new commits are pushed since only the latest +# linting matters for merge decisions. +# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent +# style standards across the entire project. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_lint_dprint_for_prs: ${{ steps.changes.outputs.run_lint_dprint_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + + lint: + name: Lint + # Run the job only for PRs with related changes or non-PR events. + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_dprint_for_prs == 'true' + needs: files-changed + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: dprint/check@v2.3 + + lint-dprint-required-check: + needs: + [ + files-changed, + lint, + ] + name: Lint dprint + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the lint dprint jobs has failed." && exit 1 diff --git a/.github/workflows/lint-dprint.yml b/.github/workflows/lint-dprint.yml deleted file mode 100644 index 56d56e0247d..00000000000 --- a/.github/workflows/lint-dprint.yml +++ /dev/null @@ -1,29 +0,0 @@ -# We want to run dprint for only the files it checks without running the other linters, which are -# expensive. For example, dprint should run for markdown changes, but pod lib lint doesn't need to -# run for markdown changes. Therefore, we run it in an extra workflow. - -name: lint-dprint -on: - push: - branches: - - main - paths: - - "**/*.yml" - - "**/*.yaml" - - "**/*.json" - - "**/*.md" - - pull_request: - paths: - - "**/*.yml" - - "**/*.yaml" - - "**/*.json" - - "**/*.md" - -jobs: - lint-dprint: - name: Run dprint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: dprint/check@v2.3 diff --git a/.github/workflows/lint-shellcheck-formatting.yml b/.github/workflows/lint-shellcheck-formatting.yml new file mode 100644 index 00000000000..5823276b352 --- /dev/null +++ b/.github/workflows/lint-shellcheck-formatting.yml @@ -0,0 +1,66 @@ +# We want only to run the shellcheck when sh files change without running the other linters, which are +# expensive. For example, pod lib lint doesn't need to run for sh changes. Therefore, we run it in an +# extra workflow. + +name: Lint Shellcheck + +on: + push: + branches: + - main + + pull_request: + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, +# as linting checks are deterministic and don't require parallel validation. +# - For pull requests, we cancel in-progress runs when new commits are pushed since only the latest +# linting matters for merge decisions. +# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent +# style standards across the entire project. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_lint_shellcheck_for_prs: ${{ steps.changes.outputs.run_lint_shellcheck_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + + lint: + name: Lint + # Run the job only for PRs with related changes or non-PR events. + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_shellcheck_for_prs == 'true' + needs: files-changed + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - run: shellcheck **/*.sh + + lint-shellcheck-required-check: + needs: + [ + files-changed, + lint, + ] + name: Lint Shellcheck + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the shellcheck jobs has failed." && exit 1 diff --git a/.github/workflows/lint-shellcheck.yml b/.github/workflows/lint-shellcheck.yml deleted file mode 100644 index d18d53abc6a..00000000000 --- a/.github/workflows/lint-shellcheck.yml +++ /dev/null @@ -1,25 +0,0 @@ -# We want only to run the shellcheck when sh files change without running the other linters, which are -# expensive. For example, pod lib lint doesn't need to run for sh changes. Therefore, we run it in an -# extra workflow. - -name: lint-shellcheck -on: - push: - branches: - - main - paths: - - ".github/workflows/lint-shellcheck.yml" - - "**/*.sh" - - pull_request: - paths: - - ".github/workflows/lint-shellcheck.yml" - - "**/*.sh" - -jobs: - shellcheck: - name: Run Shellcheck - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - run: shellcheck **/*.sh diff --git a/.github/workflows/lint-swift-formatting.yml b/.github/workflows/lint-swift-formatting.yml index 4e6ac0efd80..0a8f019f5cd 100644 --- a/.github/workflows/lint-swift-formatting.yml +++ b/.github/workflows/lint-swift-formatting.yml @@ -1,25 +1,45 @@ -name: Check Code Formatting +name: Lint Swift + on: push: branches: - main - paths: - - "**/*.swift" - - ".github/workflows/lint-swift-formatting.yml" - - ".swiftlint.yml" - pull_request: - paths: - - "**/*.swift" - - ".github/workflows/lint-swift-formatting.yml" - - ".swiftlint.yml" + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, +# as linting checks are deterministic and don't require parallel validation. +# - For pull requests, we cancel in-progress runs when new commits are pushed since only the latest +# linting matters for merge decisions. +# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent +# style standards across the entire project. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: - format-code: - name: Check Formatting of Swiftlint Code + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_lint_swift_formatting_for_prs: ${{ steps.changes.outputs.run_lint_swift_formatting_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + + lint: + name: Lint + # Run the job only for PRs with related changes or non-PR events. + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_swift_formatting_for_prs == 'true' + needs: files-changed runs-on: macos-15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Install tooling run: make init-ci-format @@ -37,3 +57,24 @@ jobs: else echo "✅ All code is formatted correctly." fi + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + lint_swift_formatting-required-check: + needs: + [ + files-changed, + lint, + ] + name: Lint Swift Formatting + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the Swift formatting check jobs has failed." && exit 1 diff --git a/.github/workflows/lint-swiftlint-formatting.yml b/.github/workflows/lint-swiftlint-formatting.yml new file mode 100644 index 00000000000..6fd85bc6ba5 --- /dev/null +++ b/.github/workflows/lint-swiftlint-formatting.yml @@ -0,0 +1,71 @@ +name: Lint SwiftLint + +on: + push: + branches: + - main + + pull_request: + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, +# as linting checks are deterministic and don't require parallel validation. +# - For pull requests, we cancel in-progress runs when new commits are pushed since only the latest +# linting matters for merge decisions. +# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent +# style standards across the entire project. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_lint_swiftlint_for_prs: ${{ steps.changes.outputs.run_lint_swiftlint_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + + lint: + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_swiftlint_for_prs == 'true' + needs: files-changed + name: Lint + runs-on: macos-14 + steps: + - uses: actions/checkout@v5 + - name: Install tooling + run: make init-ci-format + - run: swiftlint --version + - name: Run SwiftLint + run: swiftlint --strict + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + # This check validates that either lint passed or was skipped, which allows us + # to make lint-swiftlint a required check with only running the lint when required. + # So, we don't have to run lint-swiftlint, for example, for unrelated changes. + lint_swiftlint-required-check: + needs: + [ + files-changed, + lint, + ] + name: Lint SwiftLint + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the lint-swiftlint jobs has failed." && exit 1 diff --git a/.github/workflows/lint-xcode-analyze.yml b/.github/workflows/lint-xcode-analyze.yml new file mode 100644 index 00000000000..3339a07b956 --- /dev/null +++ b/.github/workflows/lint-xcode-analyze.yml @@ -0,0 +1,65 @@ +name: Lint Xcode + +on: + push: + branches: + - main + pull_request: + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple lint runs on the same code, +# as linting checks are deterministic and don't require parallel validation. +# - For pull requests, we cancel in-progress runs when new commits are pushed since only the latest +# linting matters for merge decisions. +# - For main branch pushes, we never cancel formatting checks to ensure our code maintains consistent +# style standards across the entire project. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_lint_xcode_analyze_for_prs: ${{ steps.changes.outputs.run_lint_xcode_analyze_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + + lint: + name: Lint + # Run the job only for PRs with related changes or non-PR events. + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_lint_xcode_analyze_for_prs == 'true' + needs: files-changed + runs-on: macos-15 + steps: + - uses: actions/checkout@v5 + - run: ./scripts/ci-select-xcode.sh 16.4 + - run: make analyze + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + lint_xcode_analyze-required-check: + needs: + [ + files-changed, + lint, + ] + name: Lint Xcode + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the lint check jobs has failed." && exit 1 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index b706f5c85e8..00000000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,76 +0,0 @@ -name: lint -on: - push: - branches: - - main - paths: - - "Sources/**" - - "Tests/**" - - "test-server/**" - - "Samples/**" - - ".github/workflows/lint.yml" - - "scripts/ci-select-xcode.sh" - - pull_request: - paths: - - "Sources/**" - - "Tests/**" - - "test-server/**" - - "Samples/**" - - ".github/workflows/lint.yml" - - "scripts/ci-select-xcode.sh" - - "Sentry.xcodeproj/**" - - "*.podspec" - - "Gemfile.lock" - -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - swift-lint: - name: Swift Lint - runs-on: macos-13 - steps: - - uses: actions/checkout@v4 - - run: swiftlint --version - - name: Run SwiftLint - run: swiftlint --strict - - xcode-analyze: - name: Xcode Analyze - runs-on: macos-14 - steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 16.2 - - run: make analyze - - lint-podspec: - name: pod lint ${{ matrix.podspec}} ${{ matrix.library_type }} ${{ matrix.platform}} - runs-on: macos-14 - strategy: - fail-fast: false - matrix: - podspec: ["Sentry", "SentrySwiftUI"] - platform: ["ios", "macos", "tvos", "watchos"] - library_type: ["dynamic", "static"] - - steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 15.4 - # We need to update the spec-repo, because it can happen that it is not up to date and then the lint fails. - - run: pod repo update - - name: Validate Podspec - run: ./scripts/pod-lib-lint.sh ${{ matrix.platform }} ${{ matrix.podspec}} ${{ matrix.library_type}} - - lint-hybrid-sdk-podspec: - name: pod lint Sentry/HybridSDK - runs-on: macos-14 - - steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 15.4 - - run: pod repo update - - name: Validate HybridPod Podspec - run: pod lib lint ./Tests/HybridSDKTest/HybridPod.podspec --allow-warnings --verbose --platforms=ios "--include-podspecs={Sentry.podspec}" diff --git a/.github/workflows/objc-conversion-analysis.yml b/.github/workflows/objc-conversion-analysis.yml index 6c0af7b65a5..e9063916f23 100644 --- a/.github/workflows/objc-conversion-analysis.yml +++ b/.github/workflows/objc-conversion-analysis.yml @@ -5,23 +5,44 @@ on: branches: - main pull_request: - paths: - - ".github/workflows/objc-conversion-analysis.yml" - - "SwiftConversion/**" +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple Objective-C conversion analysis runs, +# as these analyze code conversion progress and generate tracking reports. +# - For pull requests, we cancel in-progress runs when new commits are pushed since only the +# latest conversion analysis matters for tracking progress on SwiftConversion changes. +# - For main branch pushes, we never cancel conversion analysis to ensure we maintain accurate +# tracking of our Objective-C to Swift conversion progress across the entire project. concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_objc_conversion_analysis_for_prs: ${{ steps.changes.outputs.run_objc_conversion_analysis_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + analyze-objc-conversion: name: Analyze Objective-C to Swift Conversion + # Run the job only for PRs with related changes or non-PR events. + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_objc_conversion_analysis_for_prs == 'true' + needs: files-changed runs-on: macos-15 timeout-minutes: 10 steps: - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Setup Ruby uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # pin@v5.4.3 @@ -56,3 +77,29 @@ jobs: SwiftConversion/objc_dependencies_topo.dot SwiftConversion/objc_dependencies_topo.svg retention-days: 30 + + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + # This check validates that either all Objective-C conversion analysis passed or was skipped, which allows us + # to make the analysis a required check with only running the analysis when required. + # So, we don't have to run analysis, for example, for Changelog or ReadMe changes. + + objc_conversion_analysis-required-check: + needs: + [ + files-changed, + analyze-objc-conversion, + ] + name: Objective-C Conversion Analysis + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the Objective-C conversion analysis jobs has failed." && exit 1 diff --git a/.github/workflows/release-upload-xcframework.yml b/.github/workflows/release-upload-xcframework.yml index f72e906b45a..b1549e5ccb0 100644 --- a/.github/workflows/release-upload-xcframework.yml +++ b/.github/workflows/release-upload-xcframework.yml @@ -24,12 +24,12 @@ jobs: upload-xcframeworks: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Get Release workflow run ID run: echo "FRAMEWORK_RUN_ID=$(./scripts/xcframework-generated-run.sh)" >> $GITHUB_ENV - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: name: xcframeworks.zip path: Carthage/ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f8527a2b89f..cdc60c13bcd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,21 +7,6 @@ on: - main pull_request: - paths: - - "Sources/**" - - "scripts/ci-select-xcode.sh" - - Sentry.xcworkspace/** - - Sentry.xcodeproj/** - - "Package.swift" - - ".github/workflows/build-xcframework.yml" - - "scripts/build-xcframework-slice.sh" - - "scripts/assemble-xcframework.sh" - - ".github/workflows/release.yml" - - ".github/workflows/build-xcframework-variant-slices.yml" - - ".github/workflows/assemble-xcframework-variant.yml" - - ".github/workflows/ui-tests-common.yml" - - Samples/macOS-SPM-CommandLine/** - - Samples/SPM-Dynamic/** workflow_dispatch: inputs: @@ -35,12 +20,55 @@ on: description: Target branch to merge into. Uses the default branch as a fallback (optional) required: false +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple release builds from running +# simultaneously, which could lead to race conditions in artifact generation and storage. +# - For pull requests, we cancel in-progress runs when testing release workflow changes since +# only the latest version needs validation before merging. +# - For main branch pushes (actual releases), we never cancel runs to ensure every release +# process completes fully, as partial releases could corrupt our distribution pipeline. concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_release_for_prs: ${{ steps.changes.outputs.run_release_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + + setup-matrix: + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_release_for_prs == 'true' + needs: files-changed + steps: + - uses: actions/checkout@v5 + - name: Setup matrix combinations + id: setup-matrix-combinations + run: | + ./scripts/generate_release_matrix.sh + env: + EVENT_NAME: ${{ github.event_name }} + outputs: + slices: ${{ steps.setup-matrix-combinations.outputs.slices }} + variants: ${{ steps.setup-matrix-combinations.outputs.variants }} + sdk-list-array: ${{ steps.setup-matrix-combinations.outputs.sdk-list-array }} + sdk-list-string: ${{ steps.setup-matrix-combinations.outputs.sdk-list-string }} + build-xcframework-variant-slices: + name: Build XCFramework Slices + # 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' + needs: [files-changed, setup-matrix] uses: ./.github/workflows/build-xcframework-variant-slices.yml with: name: ${{matrix.variant.name}} @@ -49,136 +77,152 @@ jobs: configuration-suffix: ${{matrix.variant.configuration-suffix}} variant-id: ${{matrix.variant.id}} release-version: ${{ github.event.inputs.version }} + sdk-list: ${{ needs.setup-matrix.outputs.sdk-list-array }} strategy: matrix: - variant: - - 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 + variant: ${{ fromJson(needs.setup-matrix.outputs.slices) }} assemble-xcframework-variant: - needs: build-xcframework-variant-slices + 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 XCFramework Variant uses: ./.github/workflows/assemble-xcframework-variant.yml secrets: inherit with: - name: ${{matrix.variant.name}} + scheme: ${{matrix.variant.scheme}} suffix: ${{matrix.variant.suffix}} configuration-suffix: ${{matrix.variant.configuration-suffix}} variant-id: ${{matrix.variant.id}} signed: true release-version: ${{ github.event.inputs.version }} + excluded-archs: ${{matrix.variant.excluded-archs}} + override-name: ${{matrix.variant.override-name}} + sdks: ${{ needs.setup-matrix.outputs.sdk-list-string }} strategy: matrix: - variant: - - 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 + variant: ${{ fromJson(needs.setup-matrix.outputs.variants) }} validate-xcframework: name: Validate XCFramework - runs-on: macos-13 - needs: assemble-xcframework-variant + runs-on: macos-14 + needs: [files-changed, assemble-xcframework-variant] + # 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' steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 + - uses: actions/checkout@v5 + - uses: actions/download-artifact@v5 with: pattern: xcframework-${{github.sha}}-sentry-static path: Carthage/ - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: pattern: xcframework-${{github.sha}}-sentry-swiftui path: Carthage/ - - run: find Carthage -name "*.zip" -print0 | xargs -t0I @ mv @ Carthage - - run: ./scripts/ci-select-xcode.sh 15.2 + - run: ./scripts/ci-select-xcode.sh 15.4 - run: make build-xcframework-sample + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh # Use github.event.pull_request.head.sha instead of github.sha when available as # the github.sha is be the pre merge commit id for PRs. # See https://github.community/t/github-sha-isnt-the-value-expected/17903/17906. validate-spm: - name: Validate Swift Package Manager - runs-on: macos-13 - needs: assemble-xcframework-variant + name: Validate SPM Static + runs-on: macos-14 + needs: [files-changed, assemble-xcframework-variant] + # 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' steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 + - uses: actions/checkout@v5 + - uses: actions/download-artifact@v5 with: pattern: xcframework-${{github.sha}}-* merge-multiple: true - - name: Change path of the framework - run: | - sed -i '' 's/url.*//g' Package.swift - sed -i '' 's/checksum: ".*" \/\/Sentry-Static/path: "Sentry.xcframework.zip"/g' Package.swift - sed -i '' 's/checksum: ".*" \/\/Sentry-Dynamic/path: "Sentry-Dynamic.xcframework.zip"/g' Package.swift - shell: bash + - name: Prepare Package.swift + uses: ./.github/actions/prepare-package.swift + with: + is-pr: ${{ github.event_name == 'pull_request' }} - run: swift build working-directory: Samples/macOS-SPM-CommandLine + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh validate-spm-dynamic: - name: Validate Swift Package Manager Dynamic - runs-on: macos-13 - needs: assemble-xcframework-variant + name: Validate SPM Dynamic + runs-on: macos-14 + needs: [files-changed, assemble-xcframework-variant] + # 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' steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 + - uses: actions/checkout@v5 + - uses: actions/download-artifact@v5 with: pattern: xcframework-${{github.sha}}-* merge-multiple: true - - name: Change path of the framework - run: | - sed -i '' 's/url.*//g' Package.swift - sed -i '' 's/checksum: ".*" \/\/Sentry-Static/path: "Sentry.xcframework.zip"/g' Package.swift - sed -i '' 's/checksum: ".*" \/\/Sentry-Dynamic/path: "Sentry-Dynamic.xcframework.zip"/g' Package.swift - shell: bash + - name: Prepare Package.swift + uses: ./.github/actions/prepare-package.swift + with: + is-pr: ${{ github.event_name == 'pull_request' }} - run: swift build working-directory: Samples/SPM-Dynamic + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh swift-build: - name: Build with Swift - runs-on: macos-13 - needs: assemble-xcframework-variant + name: Build Swift Static + runs-on: macos-14 + needs: [files-changed, assemble-xcframework-variant] + # 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' steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 + - uses: actions/checkout@v5 + - uses: actions/download-artifact@v5 with: pattern: xcframework-${{github.sha}}-* merge-multiple: true - - name: Change path of the framework - run: | - sed -i '' 's/url.*//g' Package.swift - sed -i '' 's/checksum: ".*" \/\/Sentry-Static/path: "Sentry.xcframework.zip"/g' Package.swift - sed -i '' 's/checksum: ".*" \/\/Sentry-Dynamic/path: "Sentry-Dynamic.xcframework.zip"/g' Package.swift - shell: bash + - name: Prepare Package.swift + uses: ./.github/actions/prepare-package.swift + with: + is-pr: ${{ github.event_name == 'pull_request' }} - run: swift build + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + validate-spm-visionos: + name: Validate SPM Static visionOS + runs-on: macos-14 + needs: [files-changed, assemble-xcframework-variant] + # 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' + steps: + - uses: actions/checkout@v5 + - uses: actions/download-artifact@v5 + with: + pattern: xcframework-${{github.sha}}-* + merge-multiple: true + - name: Prepare Package.swift + uses: ./.github/actions/prepare-package.swift + with: + is-pr: ${{ github.event_name == 'pull_request' }} + - run: set -o pipefail &&xcodebuild build -scheme visionOS-SPM -sdk xros -destination 'generic/platform=xros' | tee raw-build-output-spm-visionOS.log | xcbeautify + working-directory: Samples/visionOS-SPM + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh duplication-tests: - name: UI Tests for project with Sentry duplicated - V4 # Up the version with every change to keep track of flaky tests + name: Test Sentry Duplication V4 # Up the version with every change to keep track of flaky tests uses: ./.github/workflows/ui-tests-common.yml - needs: assemble-xcframework-variant + needs: [files-changed, assemble-xcframework-variant] + # 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' + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} with: fastlane_command: duplication_test xcode_version: 16.4 @@ -186,13 +230,16 @@ jobs: needs_xcframework: true app-metrics: - name: Collect app metrics + name: Collect App Metrics runs-on: macos-15 - needs: assemble-xcframework-variant + needs: [files-changed, assemble-xcframework-variant] + # 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' + timeout-minutes: 20 steps: - name: Git checkout - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 16.3 + uses: actions/checkout@v5 + - run: ./scripts/ci-select-xcode.sh 16.4 - uses: ruby/setup-ruby@v1 with: bundler-cache: true @@ -212,7 +259,7 @@ jobs: MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: pattern: xcframework-${{github.sha}}-sentry-dynamic path: Carthage/ @@ -233,11 +280,15 @@ jobs: config: Tests/Perf/metrics-test.yml sauce-user: ${{ secrets.SAUCE_USERNAME }} sauce-key: ${{ secrets.SAUCE_ACCESS_KEY }} + - name: Debug Xcode environment + if: ${{ failure() || cancelled() }} + run: ./scripts/ci-diagnostics.sh job_release: runs-on: ubuntu-latest - name: "Release a new version" + name: "Release New Version" needs: [ + files-changed, validate-xcframework, validate-spm, validate-spm-dynamic, @@ -249,17 +300,17 @@ jobs: steps: - name: Get auth token id: token - uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6 + uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1 with: app-id: ${{ vars.SENTRY_RELEASE_BOT_CLIENT_ID }} private-key: ${{ secrets.SENTRY_RELEASE_BOT_PRIVATE_KEY }} - name: Check out current commit (${{ github.sha }}) - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: token: ${{ steps.token.outputs.token }} fetch-depth: 0 - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v5 with: pattern: xcframework-${{github.sha}}-* merge-multiple: true @@ -288,3 +339,32 @@ jobs: version: ${{ github.event.inputs.version }} force: ${{ github.event.inputs.force }} merge_target: ${{ github.event.inputs.merge_target }} + + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + release-required-check: + needs: + [ + files-changed, + build-xcframework-variant-slices, + assemble-xcframework-variant, + validate-xcframework, + validate-spm, + validate-spm-dynamic, + swift-build, + duplication-tests, + app-metrics, + ] + name: Release + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the release check jobs has failed." && exit 1 diff --git a/.github/workflows/test-cross-platform.yml b/.github/workflows/test-cross-platform.yml index 61637eca5b7..ff0f568100f 100644 --- a/.github/workflows/test-cross-platform.yml +++ b/.github/workflows/test-cross-platform.yml @@ -1,21 +1,47 @@ -name: Test Cross-Platform Sentry SDK Installation +name: Test Cross Platform on: push: branches: - main pull_request: - paths: - - ".github/workflows/test-cross-platform.yml" - - "Sources/**" - - "Sentry.podspec" + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple cross-platform tests, +# as these involve complex React Native and cross-platform integration setups. +# - For pull requests, we cancel in-progress runs when new commits are pushed since only the +# latest cross-platform compatibility results matter for validating multi-platform support. +# - For main branch pushes, we never cancel cross-platform tests to ensure our SDK remains +# compatible with React Native and other cross-platform frameworks that depend on us. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_test_cross_platform_for_prs: ${{ steps.changes.outputs.run_test_cross_platform_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + test-react-native: - name: React Native - runs-on: macos-15 + name: React Native Installation + # Run the job only for PRs with related changes or non-PR events. + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_test_cross_platform_for_prs == 'true' + needs: files-changed + runs-on: macos-14 + # This job can take a while to run, so we set a timeout. + timeout-minutes: 30 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: repository: getsentry/sentry-cocoa path: sentry-cocoa @@ -25,7 +51,7 @@ jobs: working-directory: sentry-cocoa - name: Clone Sentry React Native Repository - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: repository: getsentry/sentry-react-native path: sentry-react-native @@ -34,11 +60,12 @@ jobs: working-directory: sentry-react-native run: npm i -g corepack - - uses: actions/setup-node@v4 + - uses: actions/setup-node@v5 with: node-version: 18 cache: "yarn" cache-dependency-path: sentry-react-native/yarn.lock + - run: ./sentry-cocoa/scripts/ci-select-xcode.sh 16.2 - name: Install SDK JS Dependencies working-directory: sentry-react-native @@ -50,6 +77,10 @@ jobs: - name: Add Sentry/HybridSDK Dependency to RNSentryCocoaTester/Podfile run: sed -i '' -e "s/RNSentry.podspec'/RNSentry.podspec'\\n pod 'Sentry\/HybridSDK', :path => '..\/..\/..\/..\/sentry-cocoa'/" sentry-react-native/packages/core/RNSentryCocoaTester/Podfile + - name: Disable test parallelization + working-directory: sentry-react-native/packages/core/RNSentryCocoaTester + run: sed -i '' "s/parallelizable = \"YES\"/parallelizable = \"NO\"/" RNSentryCocoaTester.xcodeproj/xcshareddata/xcschemes/RNSentryCocoaTester.xcscheme + - name: Install App Pods working-directory: sentry-react-native/packages/core/RNSentryCocoaTester run: pod install @@ -59,10 +90,33 @@ jobs: env: SCHEME: RNSentryCocoaTester CONFIGURATION: Release - DESTINATION: "platform=iOS Simulator,OS=latest,name=iPhone 16" + DESTINATION: "platform=iOS Simulator,OS=17.5,name=iPhone 15 Pro" run: | + set -o pipefail env NSUnbufferedIO=YES \ xcodebuild -workspace *.xcworkspace \ -scheme $SCHEME -configuration $CONFIGURATION \ -destination "$DESTINATION" \ - test | xcbeautify + test SWIFT_ACTIVE_COMPILATION_CONDITIONS=CROSS_PLATFORM_TEST GCC_PREPROCESSOR_DEFINITIONS"=CROSS_PLATFORM_TEST=1" | xcbeautify + + - name: Run CI Diagnostics + if: failure() + run: ./sentry-cocoa/scripts/ci-diagnostics.sh + + test_cross_platform-required-check: + needs: + [ + files-changed, + test-react-native, + ] + name: Test Cross Platform + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the cross-platform test jobs has failed." && exit 1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 01928cbd5a7..fa69858c0f4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,50 +6,71 @@ on: - release/** pull_request: - paths: - - "Sources/**" - - "Tests/**" - - "SentryTestUtils/**" - - "test-server/**" - - ".github/workflows/test.yml" - - "fastlane/**" - - "scripts/tests-with-thread-sanitizer.sh" - - "scripts/ci-select-xcode.sh" - - "scripts/sentry-xcodebuild.sh" - - ".codecov.yml" - - "Sentry.xcodeproj" - - "**/*.xctestplan" - -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to allow independent test runs across different workflows +# while preventing multiple runs of the same test suite on the same branch/commit. +# - For pull requests, we cancel in-progress runs when new commits are pushed to save CI resources +# and provide faster feedback on the latest changes. +# - For main branch pushes and scheduled runs, we never cancel in-progress runs to ensure the complete +# test suite always finishes, maintaining the integrity of our main branch quality gates. concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + # This job detects if the PR contains changes that require running unit tests. + # If yes, the job will output a flag that will be used by the next job to run the unit tests. + # If no, the job will output a flag that will be used by the next job to skip running the unit tests. + # At the end of this workflow, we run a check that validates that either all unit tests passed or were + # called unit-tests-required-check. + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + # Map a step output to a job output + outputs: + run_unit_tests_for_prs: ${{ steps.changes.outputs.run_unit_tests_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml build-test-server: name: Build test server - runs-on: macos-13 + if: needs.files-changed.outputs.run_unit_tests_for_prs == 'true' + needs: files-changed + runs-on: macos-15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Cache for Test Server id: cache_test_server uses: actions/cache@v4 with: path: ./test-server/.build - key: test-server-${{ hashFiles('./test-server') }} + key: test-server-${{ hashFiles('./test-server') }}-universal restore-keys: | - test-server-${{ hashFiles('./test-server') }} + test-server-${{ hashFiles('./test-server') }}-universal test-server- - - name: Build Test Server + - name: Build Test Server for Intel CPU if: steps.cache_test_server.outputs.cache-hit != 'true' working-directory: test-server run: >- - swift build -c release 2>&1 | tee test-server-build.log + swift build -c release --triple x86_64-apple-macosx 2>&1 | tee test-server-build-intel.log - - name: Copy exec + - name: Build Test Server for M1 CPU + if: steps.cache_test_server.outputs.cache-hit != 'true' working-directory: test-server - run: cp $(swift build --show-bin-path -c release)/Run test-server-exec + run: >- + swift build -c release --arch arm64 2>&1 | tee test-server-build-arm64.log + + - name: Combine Test Server + working-directory: test-server + run: >- + lipo -create -output test-server-exec $(swift build --show-bin-path -c release --triple arm64-apple-macosx)/Run $(swift build --show-bin-path -c release --triple x86_64-apple-macosx)/Run - name: Archiving DerivedData uses: actions/upload-artifact@v4 @@ -62,12 +83,17 @@ jobs: uses: actions/upload-artifact@v4 if: ${{ failure() || cancelled() }} with: - name: test-server-build-log-${{matrix.platform}}-xcode-${{matrix.xcode}}-os-${{matrix.test-destination-os}} + name: test-server-build-log path: | - raw-test-output.log + test-server-build-intel.log + test-server-build-arm64.log + + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh unit-tests: - name: Unit ${{matrix.platform}} - Xcode ${{matrix.xcode}} - OS ${{matrix.test-destination-os}} ${{matrix.scheme}} + name: Unit ${{matrix.name}} runs-on: ${{matrix.runs-on}} timeout-minutes: 20 needs: build-test-server @@ -80,27 +106,39 @@ jobs: # We are running tests on iOS 17 and later, as there were OS-internal changes introduced in succeeding versions. # iOS 16 - - runs-on: macos-13 + - name: iOS 16 Sentry + runs-on: macos-13 platform: "iOS" xcode: "14.3.1" test-destination-os: "16.4" - device: "iPhone 14" + device: "iPhone 14 Pro" scheme: "Sentry" # iOS 17 - - runs-on: macos-14 + - name: iOS 17 Sentry + runs-on: macos-14 platform: "iOS" xcode: "15.4" - test-destination-os: "17.2" - device: "iPhone 15" + test-destination-os: "17.5" + device: "iPhone 15 Pro" scheme: "Sentry" # iOS 18 - - runs-on: macos-15 + - name: iOS 18 Sentry + runs-on: macos-15 + platform: "iOS" + xcode: "16.4" + test-destination-os: "18.4" + device: "iPhone 16 Pro" + scheme: "Sentry" + + # iOS 26 with Xcode 26 + - name: iOS 26 Sentry + runs-on: macos-15 platform: "iOS" - xcode: "16.2" - test-destination-os: "18.2" - device: "iPhone 16" + xcode: "26.0" + test-destination-os: "26.0" + device: "iPhone 16 Pro" scheme: "Sentry" # We don't run the unit tests on macOS 13 cause we run them on all on GH actions available iOS versions. @@ -108,31 +146,35 @@ jobs: # We are running tests on macOS 14 and later, as there were OS-internal changes introduced in succeeding versions. # macOS 14 - - runs-on: macos-14 + - name: macOS 14 Sentry + runs-on: macos-14 platform: "macOS" xcode: "15.4" test-destination-os: "latest" scheme: "Sentry" # macOS 15 - - runs-on: macos-15 + - name: macOS 15 Sentry + runs-on: macos-15 platform: "macOS" - xcode: "16.2" + xcode: "16.4" test-destination-os: "latest" scheme: "Sentry" # Catalyst. We test the latest version, as the risk something breaking on Catalyst and not # on an older iOS or macOS version is low. # In addition we are running tests on macOS 14, as there were OS-internal changes introduced in succeeding versions. - - runs-on: macos-14 + - name: Catalyst 14 Sentry + runs-on: macos-14 platform: "Catalyst" xcode: "15.4" test-destination-os: "latest" scheme: "Sentry" - - runs-on: macos-15 + - name: Catalyst 15 Sentry + runs-on: macos-15 platform: "Catalyst" - xcode: "16.2" + xcode: "16.4" test-destination-os: "latest" scheme: "Sentry" @@ -141,41 +183,47 @@ jobs: # We are running tests on tvOS 17 and latest, as there were OS-internal changes introduced in succeeding versions. # tvOS 17 - - runs-on: macos-14 + - name: tvOS 17 Sentry + runs-on: macos-14 platform: "tvOS" xcode: "15.4" test-destination-os: "17.5" scheme: "Sentry" # iOS 17 - - runs-on: macos-14 + - name: iOS 17 SentrySwiftUI + runs-on: macos-14 platform: "iOS" xcode: "15.4" - test-destination-os: "17.2" - device: "iPhone 15" + test-destination-os: "17.5" + device: "iPhone 15 Pro" scheme: "SentrySwiftUI" # tvOS 18 - - runs-on: macos-15 + - name: tvOS 18 Sentry + runs-on: macos-15 platform: "tvOS" - xcode: "16.2" - test-destination-os: "18.1" + xcode: "16.4" + test-destination-os: "18.4" scheme: "Sentry" steps: - - uses: actions/checkout@v4 - - uses: actions/download-artifact@v4 + - uses: actions/checkout@v5 + - uses: actions/download-artifact@v5 with: name: test-server - - name: Print hardware info - run: system_profiler SPHardwareDataType - - name: Start Test Server run: ./scripts/start-test-server.sh - - run: ./scripts/ci-select-xcode.sh ${{matrix.xcode}} + - name: Install required platforms for Xcode 26 + if: matrix.xcode == '26.0' && matrix.platform != '' + run: ./scripts/ci-install-xOS-26-platforms.sh --platforms "${{matrix.platform}}" + + - name: Create simulator device for Xcode 26 + if: matrix.xcode == '26.0' && matrix.platform != '' + run: ./scripts/ci-create-simulator.sh --platform "${{matrix.platform}}" --os-version "${{matrix.test-destination-os}}" --device-name "${{matrix.device}}" - name: Install Slather run: gem install slather @@ -208,7 +256,7 @@ jobs: --scheme ${{matrix.scheme}} - name: Publish Test Report - uses: mikepenz/action-junit-report@a83fd2b5d58d4fc702e690c1ea688d702d28d281 # v5.6.1 + uses: mikepenz/action-junit-report@3585e9575db828022551b4231f165eb59a0e74e3 # v5.6.2 if: always() with: report_paths: "build/reports/junit.xml" @@ -216,10 +264,6 @@ jobs: fail_on_parse_error: true detailed_summary: true - - name: Slowest Tests - if: ${{ always() }} - run: ./scripts/xcode-slowest-tests.sh - - name: Archiving DerivedData Logs uses: actions/upload-artifact@v4 if: steps.build_tests.outcome == 'failure' @@ -246,6 +290,9 @@ jobs: path: | ~/Library/Logs/DiagnosticReports/** + - name: Gather code coverage information via slather + run: slather coverage --configuration TestCI --scheme Sentry + # We can upload all coverage reports, because codecov merges them. # See https://docs.codecov.io/docs/merging-reports # Checkout .codecov.yml to see the config of Codecov @@ -253,7 +300,7 @@ jobs: # We don't upload codecov for scheduled runs as CodeCov only accepts a limited amount of uploads per commit. - name: Push code coverage to codecov id: codecov_1 - uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # pin@v5.4.3 + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # pin@v5.5.1 if: ${{ contains(matrix.platform, 'iOS') && !contains(github.ref, 'release') && github.event.schedule == '' }} with: # Although public repos should not have to specify a token there seems to be a bug with the Codecov GH action, which can @@ -265,9 +312,45 @@ jobs: # Sometimes codecov uploads etc can fail. Retry one time to rule out e.g. intermittent network failures. - name: Push code coverage to codecov id: codecov_2 - uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # pin@v5.4.3 + uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7 # pin@v5.5.1 if: ${{ steps.codecov_1.outcome == 'failure' && contains(matrix.platform, 'iOS') && !contains(github.ref, 'release') && github.event.schedule == '' }} with: token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: true verbose: true + + - name: Codecov test analytics + if: ${{ !cancelled() && !contains(github.ref, 'release') && github.event.schedule == '' }} + uses: codecov/test-results-action@47f89e9acb64b76debcd5ea40642d25a4adced9f # pin@v1.1.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + verbose: true + name: sentry-cocoa-unit-tests + flags: unittests-${{ matrix.platform }}-${{ matrix.xcode }}-${{ matrix.test-destination-os }}, unittests + + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + # This check validates that either all unit tests passed or were skipped, which allows us + # to make unit tests a required check with only running the unit tests when required. + # So, we don't have to run unit tests, for example, for Changelog or ReadMe changes. + + unit-tests-required-check: + needs: + [ + files-changed, + build-test-server, + unit-tests, + ] + name: Unit Tests + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the unit test jobs has failed." && exit 1 diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml index bdda716fb21..985201e0164 100644 --- a/.github/workflows/testflight.yml +++ b/.github/workflows/testflight.yml @@ -5,25 +5,43 @@ on: - main - release/** - paths: - - "Sources/**" - - "Samples/iOS-Swift/**" - - ".github/workflows/testflight.yml" - - "fastlane/**" - - "scripts/ci-select-xcode.sh" - pull_request: - paths: - - ".github/workflows/testflight.yml" workflow_dispatch: +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple TestFlight uploads of the same build, +# as these operations involve app building, signing, and upload to Apple's servers. +# - For pull requests, we cancel in-progress runs when testing workflow changes since only the +# latest configuration needs validation before merging. +# - For main branch pushes (actual uploads), we never cancel uploads to ensure every main branch +# commit gets properly built and distributed to TestFlight for testing by our team. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_testflight_for_changes: ${{ github.event_name == 'pull_request' && steps.changes.outputs.run_testflight_for_prs || steps.changes.outputs.run_testflight_for_pushes }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + upload_to_testflight: + if: needs.files-changed.outputs.run_testflight_for_changes == 'true' + needs: files-changed name: Build and Upload iOS-Swift to Testflight runs-on: macos-15 steps: - - uses: actions/checkout@v4 - - run: ./scripts/ci-select-xcode.sh 16.2 + - uses: actions/checkout@v5 + - run: ./scripts/ci-select-xcode.sh 16.4 - uses: ruby/setup-ruby@v1 with: bundler-cache: true @@ -64,3 +82,28 @@ jobs: ${{ github.workspace }}/iOS-Swift.* ${{ github.workspace }}/*.dSYM.zip ${{ github.workspace }}/dSYMs/ + + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + # This check validates that either upload_to_testflight passed or was skipped, which allows us + # to make testflight a required check with only running the upload_to_testflight when required. + # So, we don't have to run upload_to_testflight, for example, for unrelated changes. + testflight-required-check: + needs: + [ + files-changed, + upload_to_testflight, + ] + name: Testflight + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the testflight jobs has failed." && exit 1 diff --git a/.github/workflows/ui-tests-common.yml b/.github/workflows/ui-tests-common.yml index 5ecb29f95ee..d408635d07d 100644 --- a/.github/workflows/ui-tests-common.yml +++ b/.github/workflows/ui-tests-common.yml @@ -7,11 +7,6 @@ on: description: "The fastlane command to run" required: true type: string - fastlane_command_extra_arguments: - description: "Extra arguments for the fastlane command" - required: false - default: "" - type: string files_suffix: description: "Suffix for the files to upload" required: false @@ -35,32 +30,61 @@ on: required: false default: false type: boolean + codecov_test_analytics: + description: "Whether or not to push results to Codecov for analytics." + required: false + default: false + type: boolean + test-destination-os: + description: "Test destination OS" + required: false + default: "" + type: string + device: + description: "Device" + required: false + default: "" + type: string + platform: + description: "Additional platform to install" + required: false + default: "" + type: string + secrets: + CODECOV_TOKEN: + required: true jobs: common-ui-tests: name: UI Tests Common runs-on: ${{ inputs.macos_version }} steps: - - uses: actions/checkout@v4 - - - name: Print hardware info - shell: bash - run: system_profiler SPHardwareDataType - - - name: Print available disk space - shell: bash - run: df -h + - uses: actions/checkout@v5 - name: Setup Ruby uses: ruby/setup-ruby@13e7a03dc3ac6c3798f4570bfead2aed4d96abfb # v1.244.0 with: bundler-cache: true + - name: Install old xcodegen + if: ${{ inputs.xcode_version == '14.3.1' || inputs.xcode_version == '15.4' }} + # Install xcodegen 2.43.0 for since newer versions don't work with Xcode older than Xcode 16 + # We need to set HOMEBREW_DEVELOPER=1 to allow installing from a local formula + run: | + HOMEBREW_DEVELOPER=1 brew install --formula ./scripts/xcodegen.rb + brew pin xcodegen + - name: Select Xcode version run: ./scripts/ci-select-xcode.sh "$XCODE_VERSION" env: XCODE_VERSION: ${{ inputs.xcode_version }} + - name: Install required platforms for Xcode 26 + if: ${{ inputs.xcode_version == '26.0' }} + run: ./scripts/ci-install-xOS-26-platforms.sh --platforms "${{inputs.platform}}" + - name: Create simulator device for Xcode 26 + if: ${{ inputs.xcode_version == '26.0' }} + run: ./scripts/ci-create-simulator.sh --platform "${{inputs.platform}}" --os-version "${{inputs.test-destination-os}}" --device-name "${{inputs.device}}" - run: make init-ci-build if: ${{ inputs.build_with_make }} @@ -72,7 +96,7 @@ jobs: - name: Download XCFramework if: ${{ inputs.needs_xcframework }} - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v5 with: name: xcframework-${{github.sha}}-sentry-static path: Carthage/ @@ -85,16 +109,15 @@ jobs: - name: Run Fastlane env: FASTLANE_COMMAND: ${{ inputs.fastlane_command }} - FASTLANE_EXTRA_ARGS: ${{ inputs.fastlane_command_extra_arguments }} run: | - if [ -n "$FASTLANE_EXTRA_ARGS" ]; then - bundle exec fastlane "$FASTLANE_COMMAND" "$FASTLANE_EXTRA_ARGS" + if [ -n "${{inputs.device}}" ] && [ -n "${{inputs.test-destination-os}}" ]; then + bundle exec fastlane "$FASTLANE_COMMAND" device:"${{inputs.device}} (${{inputs.test-destination-os}})" else bundle exec fastlane "$FASTLANE_COMMAND" fi - name: Publish Test Report - uses: mikepenz/action-junit-report@a83fd2b5d58d4fc702e690c1ea688d702d28d281 # v5.6.1 + uses: mikepenz/action-junit-report@3585e9575db828022551b4231f165eb59a0e74e3 # v5.6.2 if: always() with: report_paths: build/reports/*junit.xml @@ -102,6 +125,15 @@ jobs: fail_on_parse_error: true detailed_summary: true + - name: Codecov test analytics + if: ${{ !cancelled() && inputs.codecov_test_analytics }} + uses: codecov/test-results-action@47f89e9acb64b76debcd5ea40642d25a4adced9f # pin@v1.1.1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + verbose: true + name: sentry-cocoa-unit-tests + flags: ui-tests-${{ inputs.fastlane_command }}-${{ inputs.xcode_version }}, ui-tests + - name: Upload Result Bundle uses: actions/upload-artifact@v4 if: ${{ failure() }} @@ -132,3 +164,7 @@ jobs: if: failure() with: suffix: ${{ inputs.fastlane_command }}${{ inputs.files_suffix }} + + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh diff --git a/.github/workflows/ui-tests-critical.yml b/.github/workflows/ui-tests-critical.yml index 924b987022a..b9f401cc313 100644 --- a/.github/workflows/ui-tests-critical.yml +++ b/.github/workflows/ui-tests-critical.yml @@ -1,66 +1,106 @@ -name: UI Tests Critical +name: Test UI Critical on: push: branches: - main pull_request: - paths: - - "Sources/**" - - ".github/workflows/ui-tests-critical.yml" - - ".github/workflows/ui-tests-common.yml" - - "fastlane/**" - - "TestSamples/**" - - "**/*.xctestplan" - # Explicitly list used scripts to avoid unnecessary runs - - "scripts/ci-boot-simulator.sh" - - "scripts/ci-select-xcode.sh" - -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple critical UI test runs, +# as these test the most essential user interface functionality and are resource-intensive. +# - For pull requests, we cancel in-progress runs when new commits are pushed to provide +# faster feedback on critical functionality and avoid wasting expensive testing resources. +# - For main branch pushes, we never cancel critical UI tests to ensure the most important +# user interface features are always validated before code reaches production. concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_ui_tests_critical_for_prs: ${{ steps.changes.outputs.run_ui_tests_critical_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + run-tests: - name: Test iOS on Xcode ${{matrix.platform.xcode}} - ${{ matrix.command.fastlane_command }} - V4 # Up the version with every change to keep track of flaky tests + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_ui_tests_critical_for_prs == 'true' + needs: files-changed + name: Test ${{matrix.name}} V4 # Up the version with every change to keep track of flaky tests uses: ./.github/workflows/ui-tests-common.yml with: - fastlane_command: ${{ matrix.command.fastlane_command }} + fastlane_command: ui_critical_tests_ios_swiftui_envelope build_with_make: true xcode_version: ${{matrix.platform.xcode}} macos_version: ${{matrix.platform.runs-on}} files_suffix: _${{matrix.platform.xcode}} + platform: ${{matrix.platform.platform}} + device: ${{matrix.platform.device}} + test-destination-os: ${{matrix.platform.test-destination-os}} strategy: fail-fast: false matrix: - platform: + include: # As of 25th March 2025, the preinstalled iOS simulator version is 16.4 for macOS 13 and Xcode 14.3.1; see # https://github.com/actions/runner-images/blob/main/images/macos/macos-13-Readme.md#installed-sdks - - runs-on: macos-13 - xcode: "14.3.1" + - name: iOS 16 + platform: + runs-on: macos-13 + xcode: "14.3.1" + platform: "iOS" + device: "iPhone 14 Pro" + test-destination-os: "16.4" # macos-14 iOS 17 not included due to the XCUIServerNotFound errors causing flaky tests - # As of 25th March 2025, the preinstalled iOS simulator version is 18.2 for macOS 15 and Xcode 16.2; see + # As of 14th August 2025, the preinstalled iOS simulator version is 18.4 for macOS 15 and Xcode 16.4; see # https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md#installed-sdks - - runs-on: macos-15 - xcode: "16.2" - command: - - fastlane_command: ui_critical_tests_ios_swiftui_envelope + - name: iOS 18 + platform: + runs-on: macos-15 + xcode: "16.4" + platform: "iOS" + device: "iPhone 16 Pro" + test-destination-os: "18.4" + + - name: iOS 26 + platform: + runs-on: macos-15 + xcode: "26.0" + platform: "iOS" + device: "iPhone 16 Pro" + test-destination-os: "26.0" + + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} run-swiftui-crash-test: + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_ui_tests_critical_for_prs == 'true' + needs: files-changed name: Run SwiftUI Crash Test runs-on: macos-15 timeout-minutes: 15 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - - run: ./scripts/ci-select-xcode.sh 16.2 + - run: ./scripts/ci-select-xcode.sh 16.4 - run: make init-ci-build - run: make xcode-ci + - name: Enable screenshots permissions + shell: bash + run: ./scripts/ci-enable-permissions.sh + - name: Boot simulator run: ./scripts/ci-boot-simulator.sh @@ -74,3 +114,40 @@ jobs: with: name: swiftui-crash-test-screenshots path: swiftui-crash-test-screenshots + + - name: Collect Logs + if: always() + run: xcrun simctl spawn booted log collect --output $(pwd)/swiftui-crash-test-log.logarchive + + - name: Upload Logs + uses: actions/upload-artifact@v4 + if: always() + with: + name: swiftui-crash-test-log.logarchive + path: swiftui-crash-test-log.logarchive + + - name: Run CI Diagnostics + if: failure() + run: ./scripts/ci-diagnostics.sh + + # This check validates that either all UI tests critical passed or were skipped, which allows us + # to make UI tests critical a required check with only running the UI tests critical when required. + # So, we don't have to run UI tests critical, for example, for unrelated changes. + ui_tests_critical-required-check: + needs: + [ + files-changed, + run-tests, + run-swiftui-crash-test, + ] + name: UI Tests Critical + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the UI tests critical jobs has failed." && exit 1 diff --git a/.github/workflows/ui-tests.yml b/.github/workflows/ui-tests.yml index 9612e5507d6..7e5b4ad6256 100644 --- a/.github/workflows/ui-tests.yml +++ b/.github/workflows/ui-tests.yml @@ -5,83 +5,150 @@ on: - main pull_request: - paths: - - "Sources/**" - - "Tests/**" - - ".github/workflows/ui-tests.yml" - - ".github/workflows/ui-tests-common.yml" - - "fastlane/**" - - ".sauce/config.yml" - - "scripts/ci-select-xcode.sh" - - "**/*.xctestplan" - - "Samples/iOS-SwiftUI/**" - - "Samples/iOS-Swift/**" - - "Samples/iOS-Swift6/**" - - "Samples/SentrySampleShared/**" - - "Samples/Shared/**" - - "scripts/build-xcframework-slice.sh" - - "scripts/assemble-xcframework.sh" - - ".github/workflows/build-xcframework-variant-slices.yml" - - ".github/workflows/assemble-xcframework-variant.yml" -# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple UI test runs on the same code, +# as UI tests are resource-intensive and long-running operations. +# - For pull requests, we cancel in-progress runs when new commits are pushed to provide faster +# feedback and avoid wasting expensive UI testing resources on outdated code. +# - For main branch pushes, we never cancel UI tests to ensure complete validation of the user +# interface before the code reaches production, maintaining our quality standards. concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_ui_tests_for_prs: ${{ steps.changes.outputs.run_ui_tests_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + ui-tests: - name: UI Tests for ${{matrix.target}} - V3 # Up the version with every change to keep track of flaky tests + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_ui_tests_for_prs == 'true' + needs: files-changed + name: Test ${{matrix.name}} V3 # Up the version with every change to keep track of flaky tests uses: ./.github/workflows/ui-tests-common.yml strategy: matrix: - target: ["ios_objc", "tvos_swift"] + include: + - name: iOS Objective-C + target: ios_objc + - name: tvOS Swift + target: tvos_swift with: fastlane_command: ui_tests_${{matrix.target}} xcode_version: 16.2 build_with_make: true macos_version: macos-14 + codecov_test_analytics: true + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} # SwiftUI only supports iOS 14+ so we run it in a separate matrix here ui-tests-swift-ui: - name: UI Tests for SwiftUI - V4 # Up the version with every change to keep track of flaky tests + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_ui_tests_for_prs == 'true' + needs: files-changed + name: Test SwiftUI V4 # Up the version with every change to keep track of flaky tests uses: ./.github/workflows/ui-tests-common.yml with: fastlane_command: ui_tests_ios_swiftui xcode_version: 16.4 build_with_make: true macos_version: macos-15 - fastlane_command_extra_arguments: device:iPhone 16 (18.5) + codecov_test_analytics: true + device: iPhone 16 Pro + test-destination-os: "18.4" + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} ui-tests-swift: - name: UI Tests for iOS-Swift Xcode ${{matrix.xcode}} - V5 # Up the version with every change to keep track of flaky tests + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_ui_tests_for_prs == 'true' + needs: files-changed + name: Test Swift ${{matrix.name}} V5 # Up the version with every change to keep track of flaky tests uses: ./.github/workflows/ui-tests-common.yml strategy: fail-fast: false matrix: include: - - runs-on: macos-13 + - name: iOS 16 + runs-on: macos-13 xcode: "14.3.1" - device: iPhone 14 (16.4) - - runs-on: macos-14 + device: iPhone 14 Pro + test-destination-os: "16.4" + - name: iOS 17 + runs-on: macos-14 xcode: "15.4" - device: iPhone 15 (17.5) - - runs-on: macos-15 + device: iPhone 15 Pro + test-destination-os: "17.5" + - name: iOS 18 + runs-on: macos-15 xcode: "16.4" - device: iPhone 16 (18.5) + device: iPhone 16 Pro + test-destination-os: "18.4" + - name: iOS 26 + runs-on: macos-15 + platform: "iOS" + xcode: "26.0" + device: iPhone 16 Pro + test-destination-os: "26.0" with: fastlane_command: ui_tests_ios_swift - fastlane_command_extra_arguments: device:${{matrix.device}} files_suffix: _xcode_${{matrix.xcode}}-${{matrix.device}} xcode_version: ${{matrix.xcode}} build_with_make: true macos_version: ${{matrix.runs-on}} + platform: ${{matrix.platform}} + test-destination-os: ${{matrix.test-destination-os}} + device: ${{matrix.device}} + codecov_test_analytics: true + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} ui-tests-swift6: - name: UI Tests for iOS-Swift6 - V3 # Up the version with every change to keep track of flaky tests + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_ui_tests_for_prs == 'true' + needs: files-changed + name: Test iOS Swift6 V3 # Up the version with every change to keep track of flaky tests uses: ./.github/workflows/ui-tests-common.yml with: fastlane_command: ui_tests_ios_swift6 - xcode_version: 16.2 + xcode_version: 16.4 build_with_make: true macos_version: macos-15 + codecov_test_analytics: true + device: iPhone 16 Pro + test-destination-os: "18.4" + secrets: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + # This check validates that either UI tests passed or were skipped, which allows us + # to make UI tests a required check with only running the UI tests when required. + # So, we don't have to run UI tests, for example, for unrelated changes. + ui_tests-required-check: + needs: + [ + files-changed, + ui-tests, + ui-tests-swift-ui, + ui-tests-swift, + ui-tests-swift6, + ] + name: UI Tests + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the UI test jobs has failed." && exit 1 diff --git a/.github/workflows/version-bump-util.yml b/.github/workflows/version-bump-util.yml index 71c94ae5353..923da2232e4 100644 --- a/.github/workflows/version-bump-util.yml +++ b/.github/workflows/version-bump-util.yml @@ -6,29 +6,42 @@ on: - main pull_request: - paths: - - "Utils/VersionBump/**" - - ".github/workflows/version-bump-util.yml" - - "./Sentry.podspec" - - "./Package.swift" - - "./SentryPrivate.podspec" - - "./SentrySwiftUI.podspec" - - "./Sources/Sentry/SentryMeta.m" - - "./Tests/HybridSDKTest/HybridPod.podspec" - - "./Sources/Configuration/SDK.xcconfig" - - "./Sources/Configuration/Versioning.xcconfig" - - "./Sources/Configuration/SentrySwiftUI.xcconfig" - - "./Samples/Shared/Config/Versioning.xcconfig" - - "./scripts/bump.sh" + +# Concurrency configuration: +# - We use workflow-specific concurrency groups to prevent multiple version bump utility tests, +# as these test critical release infrastructure and version management tools. +# - For pull requests, we cancel in-progress runs when new commits are pushed since only the +# latest version utility behavior matters for validating release process changes. +# - For main branch pushes, we never cancel version utility tests to ensure our release +# infrastructure remains reliable and our version bumping tools work correctly. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: + files-changed: + name: Detect File Changes + runs-on: ubuntu-latest + outputs: + run_version_bump_util_for_prs: ${{ steps.changes.outputs.run_version_bump_util_for_prs }} + steps: + - uses: actions/checkout@v5 + - name: Get changed files + id: changes + uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2 + with: + token: ${{ github.token }} + filters: .github/file-filters.yml + run-version-bump: + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_version_bump_util_for_prs == 'true' + needs: files-changed # The release workflow uses the Makefile to bump the version so it needs to be tested. name: Run Version Bump (Makefile) # We intentionally run this on ubuntu because the release workflow also runs on ubuntu, which uses the version bump util. runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Generate Version Number id: generate-version-number run: | @@ -39,11 +52,13 @@ jobs: - run: make verify-version TO=${{ steps.generate-version-number.outputs.VERSION }} run-version-bump-script: + if: github.event_name != 'pull_request' || needs.files-changed.outputs.run_version_bump_util_for_prs == 'true' + needs: files-changed # Craft uses the shell script to bump the version so it needs to be tested. name: Run Version Bump (Shell Script) runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Generate Version Number id: generate-version-number run: | @@ -66,6 +81,9 @@ jobs: mkdir -p Carthage echo "" > Carthage/Sentry.xcframework.zip echo "" > Carthage/Sentry-Dynamic.xcframework.zip + echo "" > Carthage/Sentry-Dynamic-WithARM64e.xcframework.zip + echo "" > Carthage/Sentry-WithoutUIKitOrAppKit.xcframework.zip + echo "" > Carthage/Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework.zip - name: Bump version run: ./scripts/bump.sh ${{ steps.generate-version-number.outputs.OLD_VERSION }} ${{ steps.generate-version-number.outputs.NEW_VERSION }} @@ -78,4 +96,29 @@ jobs: ./scripts/verify-package-sha.sh \ --static-checksum "7062a80f8a80f8b6d812698af87384751567a6aaa0df6f03b0596d728b22dcfd" \ --dynamic-checksum "f6325cd8f05523d60222451fa61b3cd3d58148e5a21236f82abfd3f92750c87c" \ + --dynamic-with-arm64e-checksum "bbb84b054e5792aa705b95541aa4585f793e566a6b95638f8fef8e308d9782c3" \ + --without-uikit-or-appkit-checksum "c647afe93889063325b5dfcabf43101749f6a8f37008cca858833ed280d2a84e" \ + --without-uikit-or-appkit-with-arm64e-checksum "af5af7edc8e107fe04b905bd23524fdc93914fce8e1bd72ccf281408efff9a47" \ --last-release-runid "${{ github.run_id }}" + + # This check validates that either version-bump-util passed or was skipped, which allows us + # to make version-bump-util a required check with only running the version-bump-util when required. + # So, we don't have to run version-bump-util, for example, for unrelated changes. + version_bump_util-required-check: + needs: + [ + files-changed, + run-version-bump, + run-version-bump-script, + ] + name: Test Version Bump Util + # This is necessary since a failed/skipped dependent job would cause this job to be skipped + if: always() + runs-on: ubuntu-latest + steps: + # If any jobs we depend on fails gets cancelled or times out, this job will fail. + # Skipped jobs are not considered failures. + - name: Check for failures + if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') + run: | + echo "One of the version-bump-util jobs has failed." && exit 1 diff --git a/.gitignore b/.gitignore index 46435c2e3b1..69dad1ab6bb 100644 --- a/.gitignore +++ b/.gitignore @@ -100,5 +100,12 @@ TestSamples/SwiftUICrashTest/SwiftUICrashTest.xcodeproj Sentry.xcframework* Sentry-Dynamic.xcframework* +Sentry-Dynamic-WithARM64e.xcframework* SentrySwiftUI.xcframework* Sentry-WithoutUIKitOrAppKit.xcframework* +Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework* + +current_package_diff.patch + +uikit-check-build +*.xcarchive diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9581ee994f5..7bed5e2f150 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,7 +23,7 @@ repos: args: [--allow-multiple-documents] - id: detect-private-key - id: end-of-file-fixer - exclude: ^sdk_api.json$ + exclude: ^sdk_api.*\.json$ - repo: https://github.com/python-jsonschema/check-jsonschema rev: 0.27.3 @@ -72,14 +72,14 @@ repos: types_or: [json] entry: dprint language: system - exclude: ^sdk_api.json$ + exclude: ^sdk_api.*\.json$ args: - "fmt" - id: format-yaml name: Format YAML description: "Format YAML" - files: ^.*\.{yaml,yml}$ + files: ^.*\.(yaml|yml)$ types_or: [yaml] entry: dprint language: system diff --git a/.swiftlint.yml b/.swiftlint.yml index 10ded84ab4d..48fccbfe896 100755 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -9,6 +9,7 @@ excluded: - Tests/Perf - SentryTestUtils/Dynamic/** - .build/** + - .git/** only_rules: - class_delegate_protocol @@ -52,7 +53,7 @@ only_rules: - private_unit_test - prohibited_super_call - redundant_nil_coalescing - - redundant_optional_initialization + - implicit_optional_initialization - redundant_string_enum_value - redundant_void_return - return_arrow_whitespace diff --git a/CHANGELOG-v9.md b/CHANGELOG-v9.md new file mode 100644 index 00000000000..8e52cfa297f --- /dev/null +++ b/CHANGELOG-v9.md @@ -0,0 +1,24 @@ +# 9.0 + +### Breaking Changes + +Removes deprecated user feedback API, this is replaced with the new feedback API (#5591) +Removes unused SentryLogLevel (#5591) +Removes deprecated getStoreEndpoint (#5591) +Removes deprecated useSpan function (#5591) +Removes deprecated SentryDebugImageProvider class (#5598) +Makes app hang tracking V2 the default and removes the option to enable/disable it (#5615) +Removes segment property on SentryUser, SentryBaggage, and SentryTraceContext (#5638) +Removes public SentrySerializable conformance from many public models (#5636, #5840, #5982) +Removes Decodable conformances from the public API of model classes (#5691) +Removes enableTracing property from SentryOptions (#5694) +Removes deprecated `setExtraValue` from SentrySpan (#5864) +Removes `integrations` property from `SentryOptions` (#5749) +Makes `SentryEventDecodable` internal (#5808) +The `span` property on `SentryScope` is now readonly (#5866) + +### Fixes + +Fixes warnings about minimum OS version being lower than Xcode supported version (#5591) + +### Improvements diff --git a/CHANGELOG.md b/CHANGELOG.md index 32f91066fbf..1f407be9a16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,162 @@ # Changelog +## 8.56.0 + +### Features + +- Structured Logs: Flush logs on SDK flush/close (#5834) +- Add masking options for screenshots (#5401) +- Add significant time change breadcrumb (#6112) +- Add support for iOS 26, macOS 26, visionOS 26, watchOS 26, and tvOS 26 in device tests (#6063) + +### Improvements + +- Lazily CharacterSet only once in SentryBaggageSerialization (#5871) +- Structured Logging: Log `SentrySDK.logger` calls to `SentrySDKLog` (#5991) +- The build type in the app context now differentiates between `enterprise` and `adhoc` (#6044) +- visionOS no longer needs swift's interoperability mode (#6077) +- Ensure IP address is only inferred by Relay if sendDefaultPii is true (#5877) +- Sentry without UIKit / AppKit is available to install with SPM (#6160) + +### Fixes + +- Don't capture replays for events dropped in `beforeSend` (#5916) +- Fix linking with SentrySwiftUI on Xcode 26 for visionOS (#5823) +- Structured Logging: Logger called before `SentrySDK.start` becomes unusable (#5984) +- Add masking for AVPlayerView (#5910) +- Fix missing view hierachy when enabling `attachScreenshot` too (#5989) +- Fix macOS's frameworks not following the versioned framework structure (#6049) +- Add warning to addBreadcrumb when used before SDK init (#6083) +- Add null-handling for parsed DSN in SentryHTTPTransport (#5800) +- Fix crash in Session Replay when opening the camera UI on iOS 26+ by skipping redaction of internal views. + This may result in more of the camera screen being redacted. (#6045) +- Fix crash in SentryDependencyContainer init when using the SDK as a static framework (#6125) +- Fixes a React Native legacy build failure by adding the missing self references for explicit capture semantics (#6156) + +## 8.56.0-alpha.3 + +### Fixes + +- Fixes a React Native legacy build failure by adding the missing self references for explicit capture semantics (#6156) + +## 8.56.0-alpha.2 + +### Features + +- Add significant time change breadcrumb (#6112) +- Add support for iOS 26, macOS 26, visionOS 26, watchOS 26, and tvOS 26 in device tests (#6063) + +### Fixes + +- Fix crash in Session Replay when opening the camera UI on iOS 26+ by skipping redaction of internal views. + This may result in more of the camera screen being redacted. (#6045) +- Fix crash in SentryDependencyContainer init when using the SDK as a static framework (#6125) + +## 8.56.0-alpha.1 + +- No documented changes. + +## 8.56.0-alpha.0 + +### Features + +- Structured Logs: Flush logs on SDK flush/close (#5834) +- Add masking options for screenshots (#5401) + +### Fixes + +- Don't capture replays for events dropped in `beforeSend` (#5916) +- Fix linking with SentrySwiftUI on Xcode 26 for visionOS (#5823) +- Structured Logging: Logger called before `SentrySDK.start` becomes unusable (#5984) +- Add masking for AVPlayerView (#5910) +- Fix missing view hierachy when enabling `attachScreenshot` too (#5989) +- Fix macOS's frameworks not following the versioned framework structure (#6049) +- Add warning to addBreadcrumb when used before SDK init (#6083) +- Add null-handling for parsed DSN in SentryHTTPTransport (#5800) + +### Improvements + +- Lazily CharacterSet only once in SentryBaggageSerialization (#5871) +- Structured Logging: Log `SentrySDK.logger` calls to `SentrySDKLog` (#5991) +- The build type in the app context now differentiates between `enterprise` and `adhoc` (#6044) +- visionOS no longer needs swift's interoperability mode (#6077) +- Ensure IP address is only inferred by Relay if sendDefaultPii is true (#5877) + +## 8.55.1 + +### Features + +### Fixes + +- Fix macOS's frameworks not following the versioned framework structure (#6049) + +## 8.54.1-alpha.1 + +### Fixes + +- Add padding to tap area of widget button (#5949) + +## 8.55.0 + +> [!Important] +> Xcode 26 no longer allows individual frameworks to contain arm64e slices anymore if the main binary doesn't contain them. +> We have decided to split the Dynamic variant and Sentry-WithoutUIKitOrAppKit of Sentry into two variants: +> +> - `Sentry-Dynamic`: Without ARM64e +> - `Sentry-Dynamic-WithARM64e`: _With_ ARM64e slice +> - `Sentry-WithoutUIKitOrAppKit`: Without ARM64e +> - `Sentry-WithoutUIKitOrAppKit-WithARM64e`: _With_ ARM64e slice +> +> If your app does not need arm64e, you don't need to make any changes. +> But if your app _needs arm64e_ please use `Sentry-Dynamic-WithARM64e` or `Sentry-WithoutUIKitOrAppKit-WithARM64e` from 8.55.0 so you don't have issues uploading to the App Store. + +### Features + +- Add a new prebuilt framework with arm64e and remove it from the regular one (#5788) +- Add `beforeSendLog` callback to `SentryOptions` (#5678) +- Structured Logs: Flush logs on SDK flush/close (#5834) +- Add a new prebuilt framework with ARM64e for WithoutUIKitOrAppKit (#5897) +- Add source context and vars fields to SentryFrame (#5853) + +### Fixes + +- Add support for PDFKit views in session replay (#5750) +- Fix Infinite Session Replay Processing Loop (#5765) +- Fix memory leak in SessionReplayIntegration (#5770) +- Fix reporting of energy used while profiling (#5768) +- Fixed a build error in `SentryFeedback.swift` when building with cocoapods on Xcode 14.2 (#5917) +- Fix linking against Sentry on an app extension (#5813) + +### Internal + +- Add nullability property for `screenName` (#5782) + +## 8.54.0 + +### Features + +- Add experimental support for capturing structured logs via `SentrySDK.logger` (#5532, #5593, #5639, #5628, #5637, #5643) +- Add `isiOSAppOnMac` and `isMacCatalystApp` from ProcessInfo to the runtime context (#5570) +- The SDK will show a warning in the console if it detects it was loaded twice (#5298) + +### Fixes + +- Add null-handling for internal array sanitization (#5722) +- Fix video replay crashes due to video writer inputs not marked as finished on cancellation (#5608) +- Fix wrong flush timeout (#5565). When flush timed out before the SDK finished sending data, it always blocked the full flush timeout the next time being called. This is fixed now. +- Launch profiling now respects original configured options if they change on the next launch (#5417) +- User feedback no longer subject to sample rates or `beforeSend` (#5692) +- Build error in app extensions (#5682) +- Fix frame metrics including time while in background (#5681) + +### Improvements + +- Extract video processing to a new class (#5604) +- Move continuous profiling payload serialization off of the main thread (#5613) +- Improve video generation using apple recommended loop (#5612) +- Use -OSize for release builds (#5721) +- Mark The `integrations` parameter of `SentryOptions` as deprecated rather than printing a warning (#5749) + ## 8.53.2 ### Fixes diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000000..af84243c1ed --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,55 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Best Practices + +- Before forming a commit, ensure compilation succeeds for all platforms: iOS, macOS, tvOS, watchOS and visionOS. This should hold for: + - the SDK framework targets + - the sample apps + - the test targets for the SDK framework and sample apps +- Before submitting a branch for a PR, ensure there are no new issues being introduced for: + - static analysis + - runtime analysis, using thread, address and undefined behavior sanitizers + - cross platform dependencies: + - React Native + - Flutter + - .Net + - Unity +- While preparing changes, ensure that relevant documentation is added/updated in: + - headerdocs and inline comments + - readmes and maintainer markdown docs + - our docs repo and web app onboarding + - our cli and integration wizard + +## Helpful Commands + +- format code: `make format` +- run static analysis: `make analyze` +- run unit tests: `make run-test-server && make test` +- run important UI tests: `make test-ui-critical` +- build the XCFramework deliverables: `make build-xcframework` +- lint pod deliverable: make `pod-lint` + +## Resources & Documentation + +- **Main Documentation**: [docs.sentry.io/platforms/apple](https://docs.sentry.io/platforms/apple/) + - **Docs Repo**: [sentry-docs](https://github.com/getsentry/sentry-docs) +- **SDK Developer Documentation**: [develop.sentry.dev/sdk/](https://develop.sentry.dev/sdk/) + +### `sentry-cocoa` Maintainer Documentation + +- **README**: @README.md +- **Contributing**: @CONTRIBUTING.md +- **Developer README**: @develop-docs/README.md +- **Sample App collection README**: @Samples/README.md + +## Related Code & Repositories + +- [sentry-cli](https://github.com/getsentry/sentry-cli): uploading dSYMs for symbolicating stack traces gathered via the SDK +- [sentry-wizard](https://github.com/getsentry/sentry-wizard): automatically injecting SDK initialization code +- [sentry-cocoa onboarding](https://github.com/getsentry/sentry/blob/master/static/app/utils/gettingStartedDocs/apple.tsx): the web app's onboarding instructions for `sentry-cocoa` +- [sentry-unity](https://github.com/getsentry/sentry-unity): the Sentry Unity SDK, which depends on sentry-cocoa +- [sentry-dart](https://github.com/getsentry/sentry-dart): the Sentry Dart SDK, which depends on sentry-cocoa +- [sentry-react-native](https://github.com/getsentry/sentry-react-native): the Sentry React Native SDK, which depends on sentry-cocoa +- [sentry-dotnet](https://github.com/getsentry/sentry-dotnet): the Sentry .NET SDK, which depends on sentry-cocoa diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0bdae037aca..17725ab3844 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,6 +9,14 @@ We welcome suggested improvements and bug fixes for `sentry-cocoa`, in the form of pull requests. To get early feedback, we recommend opening up a [draft PR](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests). Please follow our official [Commit Guidelines](https://develop.sentry.dev/code-review/#commit-guidelines) and also prefix the title of your PR according to the [Commit Guidelines](https://develop.sentry.dev/code-review/#commit-guidelines). The guide below will help you get started, but if you have further questions, please feel free to reach out on [Discord](https://discord.gg/Ww9hbqr). +For more detailed information, see `develop-docs/README.md`. + +## Environment + +Run `make init` to get started. This will install `pre-commit`, `bundler` and `Homebrew` and their managed dependencies (see `Gemfile` and `Brewfile`). + +Please use `Sentry.xcworkspace` as the entry point when opening the project in Xcode. It also contains all samples for different environments. + ## PR reviews For feedback in PRs, we use the [LOGAF scale](https://develop.sentry.dev/engineering-practices/code-review/#logaf-scale) to specify how important a comment is. You only need one approval from a maintainer to be able to merge. For some PRs, asking specific or multiple people for review might be adequate. @@ -20,54 +28,12 @@ Our different types of reviews: 3. **Only comments.** You must address all the comments and need another review until you merge. 4. **Request changes.** Only use if something critical is in the PR that absolutely must be addressed. We usually use `h` comments for that. When someone requests changes, the same person must approve the changes to allow merging. Use this sparingly. -## Setting up an Environment - -Run `make init` to get started. This will install `pre-commit`, `bundler` and `Homebrew` and their managed dependencies (see `Gemfile` and `Brewfile`). - -## Tests - -The tests depend on our test server. To run the automated tests, you first need to have the server running locally with - -```sh -make run-test-server -``` - -Test guidelines: - -- We write our tests in Swift. When touching a test file written in Objective-C consider converting it to Swift and then add your tests. -- Make use of the fixture pattern for test setup code. For examples, checkout [SentryClientTest](/Tests/SentryTests/SentryClientTest.swift) or [SentryHttpTransportTests](/Tests/SentryTests/SentryHttpTransportTests.swift). -- Use [TestData](/Tests/SentryTests/Protocol/TestData.swift) when possible to avoid setting up data classes with test values. -- Name the variable of the class you are testing `sut`, which stands for [system under test](https://en.wikipedia.org/wiki/System_under_test). -- When calling `SentrySDK.start` in a test, specify only the minimum integrations required to minimize side effects for tests and reduce flakiness. - -Test can either be ran inside from Xcode or via - -```sh -make test -``` - -### Flaky tests - -If you see a test being flaky, you should ideally fix it immediately. If that's not feasible, you can disable the test in the test scheme by unchecking it in the associated test plan: - -![Disabling test cases via the Xcode Tests navigator](./develop-docs/disabling_tests_xcode_test_plan.png) - -Then create a GH issue with the [flaky test issue template](https://github.com/getsentry/sentry-cocoa/issues/new?assignees=&labels=Platform%3A+Cocoa%2CType%3A+Flaky+Test&template=flaky-test.yml). - -Disabling the test in the test plan has the advantage that the test report will state "X tests passed, Y tests failed, Z tests skipped", as well as maintaining a centralized list of skipped tests (look in the associated .xctestplan file source in //Plans/) and they will be grayed out when viewing in the Xcode Tests Navigator (⌘6): - -![How Xcode displays skipped tests in the Tests Navigator](./develop-docs/xcode_tests_navigator_with_skipped_test.png) - ## Code Formatting Please follow the convention of removing the copyright code comments at the top of files. We only keep them inside [SentryCrash](/SentryCrash/), as the code is based on [KSCrash](https://github.com/kstenerud/KSCrash). -All Objective-C, C and C++ needs to be formatted with [Clang Format](http://clang.llvm.org/docs/ClangFormat.html). The configuration can be found in [`.clang-format`](./.clang-format). Simply run the make task, which runs automatically with git pre commit, before submitting your changes for review: - -```sh -make format -``` +All Objective-C, C and C++ needs to be formatted with [Clang Format](http://clang.llvm.org/docs/ClangFormat.html). The configuration can be found in [`.clang-format`](./.clang-format). Formatting should happen automatically as part of our precommit hook, which uses `make format`. ### GH actions suddenly formats code differently @@ -86,43 +52,6 @@ We use [Swiftlint](https://github.com/realm/SwiftLint) and Clang-Format. For Swi make lint ``` -## Environment - -Please use `Sentry.xcworkspace` as the entry point when opening the project in Xcode. It also contains all samples for different environments. - -## Public Headers - -To make a header public follow these steps: - -- Move it into the folder [Public](/Sources/Sentry/Public). Both [CocoaPods](Sentry.podspec) and [Swift Package Manager](Package.swift) make all headers in this folder public. -- Add it to the Umbrella Header [Sentry.h](/Sources/Sentry/Public/Sentry.h). -- Set the target membership to public. - -## Converting to Swift - -Converting internal ObjC classes to Swift needs to be done following a partial order. The scripts in `SwiftConversion` generate this ordering and can be used to guide ObjC to Swift conversions. - -## Configuring certificates and provisioning profiles locally - -You can run samples in a real device without changing certificates and provisioning profiles if you are a Sentry employee with access to Sentry profiles repository and 1Password account. - -- Configure your environment to use SSH to access GitHub. Follow [this instructions](https://docs.github.com/en/authentication/connecting-to-github-with-ssh). -- You will need `Cocoa codesigning match encryption password` from your Sentry 1Password account. -- run `fastlane match_local` - -This will setup certificates and provisioning profiles into your machine, but in order to be able to run a sample in a real device you need to register that device with Sentry AppConnect account, add the device to the provisioning profile you want to use, download the profile again and open it with Xcode. - -## Promoting a beta release to a normal release - -We frequently release a beta version of our SDK and dogfood it with internal apps to increase our SDK stability. We continue to merge PRs to the main branch, so we can't promote a beta release by publishing it from the main branch. Instead, we create a branch from the GH tag of the beta release and promote it from there. To do this, follow these steps: - -1. Checkout a new branch from the GH tag of the beta release: `git checkout -b publish/x.x.x x.x.x-beta.1`. You can't use `release/x.x.x` or `x.x.x` as the branch name as craft will fail, as it creates a `release/x.x.x` branch for updating the changelog and it will create a tag `x.x.x` for the release. -2. Duplicate the Changelog.md entry of the beta release and change header of the version number to unreleased. -3. Commit and push the changes. -4. Trigger the release workflow with use workflow from the `publish/x.x.x` branch and set the target branch to merge into to `publish/x.x.x`, cause per default craft will merge into the main branch and this could lead to merge conflicts in the changelog. -5. After the successful release, validate that craft merged the changes back into `publish/x.x.x` branch and deleted the release branch. -6. Manually open a PR from the `publish/x.x.x` branch into the main branch and merge it. - ## Final Notes When contributing to the codebase, please make note of the following: diff --git a/Gemfile.lock b/Gemfile.lock index 174ee8c9b38..38f21f95209 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -173,7 +173,7 @@ GEM xcodeproj (>= 1.13.0, < 2.0.0) xcpretty (~> 0.4.1) xcpretty-travis-formatter (>= 0.0.3, < 2.0.0) - fastlane-plugin-sentry (1.30.0) + fastlane-plugin-sentry (1.33.0) os (~> 1.1, >= 1.1.4) fastlane-sirp (1.0.0) sysrandom (~> 1.0) @@ -235,7 +235,7 @@ GEM mime-types-data (3.2023.1003) mini_magick (4.13.2) mini_mime (1.1.5) - mini_portile2 (2.8.8) + mini_portile2 (2.8.9) minitest (5.25.1) molinillo (0.8.0) multi_json (1.15.0) @@ -246,7 +246,7 @@ GEM naturally (2.3.0) netrc (0.11.0) nkf (0.2.0) - nokogiri (1.18.8) + nokogiri (1.18.9) mini_portile2 (~> 2.8.2) racc (~> 1.4) optparse (0.6.0) diff --git a/Makefile b/Makefile index 362bf9c0123..004a24cae8a 100644 --- a/Makefile +++ b/Makefile @@ -88,14 +88,20 @@ format-yaml: generate-public-api: ./scripts/update-api.sh + ./scripts/update-api.sh V9 ## Current git reference name GIT-REF := $(shell git rev-parse --abbrev-ref HEAD) test: @echo "--> Running all tests" - ./scripts/sentry-xcodebuild.sh --platform iOS --os latest --ref $(GIT-REF) --command test --configuration Test - ./scripts/xcode-slowest-tests.sh + ./scripts/sentry-xcodebuild.sh \ + --platform iOS \ + --os 18.4 \ + --device "iPhone 16 Pro" \ + --ref $(GIT-REF) \ + --command test \ + --configuration Test .PHONY: test run-test-server: diff --git a/Package.swift b/Package.swift index 08478faf9e0..08a4cfd32b1 100644 --- a/Package.swift +++ b/Package.swift @@ -10,21 +10,39 @@ import MSVCRT import PackageDescription var products: [Product] = [ - .library(name: "Sentry", targets: ["Sentry"]), + .library(name: "Sentry", targets: ["Sentry", "SentryCppHelper"]), .library(name: "Sentry-Dynamic", targets: ["Sentry-Dynamic"]), - .library(name: "SentrySwiftUI", targets: ["Sentry", "SentrySwiftUI"]) + .library(name: "Sentry-Dynamic-WithARM64e", targets: ["Sentry-Dynamic-WithARM64e"]), + .library(name: "Sentry-WithoutUIKitOrAppKit", targets: ["Sentry-WithoutUIKitOrAppKit", "SentryCppHelper"]), + .library(name: "Sentry-WithoutUIKitOrAppKit-WithARM64e", targets: ["Sentry-WithoutUIKitOrAppKit-WithARM64e", "SentryCppHelper"]), + .library(name: "SentrySwiftUI", targets: ["Sentry", "SentrySwiftUI", "SentryCppHelper"]) ] var targets: [Target] = [ .binaryTarget( name: "Sentry", - url: "https://github.com/getsentry/sentry-cocoa/releases/download/8.53.2/Sentry.xcframework.zip", - checksum: "b4c0b46ea2752d5fbf2b98b2c4bddc71e8803714b1faff0f2e427082474a7d3e" //Sentry-Static + url: "https://github.com/getsentry/sentry-cocoa/releases/download/8.56.0/Sentry.xcframework.zip", + checksum: "ecc100b59f2044800650f17786c33f071ea580cb318d82e8ce1d403b643555a4" //Sentry-Static ), .binaryTarget( name: "Sentry-Dynamic", - url: "https://github.com/getsentry/sentry-cocoa/releases/download/8.53.2/Sentry-Dynamic.xcframework.zip", - checksum: "d0a293654ab99979c5aae2a4a7ce50a4c40c62e36c98fb3c7b2bc1adcc2621d1" //Sentry-Dynamic + url: "https://github.com/getsentry/sentry-cocoa/releases/download/8.56.0/Sentry-Dynamic.xcframework.zip", + checksum: "509cdbc89e4409614f6d584464ef7e1d26c47ad8afe3abc2bd1e1d71c068be1e" //Sentry-Dynamic + ), + .binaryTarget( + name: "Sentry-Dynamic-WithARM64e", + url: "https://github.com/getsentry/sentry-cocoa/releases/download/8.56.0/Sentry-Dynamic-WithARM64e.xcframework.zip", + checksum: "d62a5ced65465c7c63962ed40d06a9aadd8675b8d0909089f89f65bf233e38c3" //Sentry-Dynamic-WithARM64e + ), + .binaryTarget( + name: "Sentry-WithoutUIKitOrAppKit", + url: "https://github.com/getsentry/sentry-cocoa/releases/download/8.56.0/Sentry-WithoutUIKitOrAppKit.xcframework.zip", + checksum: "4abfe912bb543eedb7d7dd015df04c93c2b8e49437962046137653d4cf737d38" //Sentry-WithoutUIKitOrAppKit + ), + .binaryTarget( + name: "Sentry-WithoutUIKitOrAppKit-WithARM64e", + url: "https://github.com/getsentry/sentry-cocoa/releases/download/8.56.0/Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework.zip", + checksum: "0b6b454b48614f8cd2430cdc75e524ded46308309b95e73fdd9a90da81622e77" //Sentry-WithoutUIKitOrAppKit-WithARM64e ), .target ( name: "SentrySwiftUI", @@ -40,20 +58,33 @@ var targets: [Target] = [ sources: [ "SentryInternal/" ], - publicHeadersPath: "SentryInternal/") + publicHeadersPath: "SentryInternal/"), + .target( + name: "SentryCppHelper", + dependencies: ["Sentry"], + path: "Sources/SentryCppHelper", + linkerSettings: [ + .linkedLibrary("c++") + ] + ) ] let env = getenv("EXPERIMENTAL_SPM_BUILDS") if let env = env, String(cString: env, encoding: .utf8) == "1" { products.append(.library(name: "SentrySPM", type: .dynamic, targets: ["SentryObjc"])) targets.append(contentsOf: [ - // At least one source file is required - .target(name: "SentryHeaders", path: "Sources/Sentry", sources: ["SentryDsn.m"], publicHeadersPath: "Public"), + // At least one source file is required, therefore we use a dummy class to satisfy the SPM build system + .target( + name: "SentryHeaders", + path: "Sources/Sentry", + sources: ["SentryDummyPublicEmptyClass.m"], + publicHeadersPath: "Public" + ), .target( name: "_SentryPrivate", dependencies: ["SentryHeaders"], path: "Sources/Sentry", - sources: ["NSLocale+Sentry.m"], + sources: ["SentryDummyPrivateEmptyClass.m"], publicHeadersPath: "include", cSettings: [.headerSearchPath("include/HybridPublic")]), .target( @@ -62,16 +93,15 @@ if let env = env, String(cString: env, encoding: .utf8) == "1" { path: "Sources/Swift", swiftSettings: [ .unsafeFlags(["-enable-library-evolution"]), - // This flag is used to make some API breaking changes necessary for the framework to compile with SPM. - // We can either make more extensive changes to allow it to be backwards compatible, or release them as part of a V9 release. - // For now we use this flag so that CI can compile the SPM version. - .define("SENTRY_SWIFT_PACKAGE") + // Some API breaking changes are necessary for the framework to compile with SPM, we’ll ship + // those in V9. + .define("SDK_V9") ]), .target( name: "SentryObjc", dependencies: ["SentrySwift"], path: "Sources", - exclude: ["Sentry/SentryDsn.m", "Sentry/NSLocale+Sentry.m", "Swift", "SentrySwiftUI", "Resources", "Configuration"], + exclude: ["Sentry/SentryDummyPublicEmptyClass.m", "Sentry/SentryDummyPrivateEmptyClass.m", "Swift", "SentrySwiftUI", "Resources", "Configuration", "SentryCppHelper"], cSettings: [ .headerSearchPath("Sentry/include/HybridPublic"), .headerSearchPath("Sentry"), @@ -80,7 +110,8 @@ if let env = env, String(cString: env, encoding: .utf8) == "1" { .headerSearchPath("SentryCrash/Recording/Tools"), .headerSearchPath("SentryCrash/Installations"), .headerSearchPath("SentryCrash/Reporting/Filters"), - .headerSearchPath("SentryCrash/Reporting/Filters/Tools")]) + .headerSearchPath("SentryCrash/Reporting/Filters/Tools"), + .define("SDK_V9")]) ]) } diff --git a/Plans/iOS-Cocoapods-Swift6_Base.xctestplan b/Plans/iOS-Cocoapods-Swift6_Base.xctestplan index 743bc369371..6088e1ca213 100644 --- a/Plans/iOS-Cocoapods-Swift6_Base.xctestplan +++ b/Plans/iOS-Cocoapods-Swift6_Base.xctestplan @@ -17,11 +17,10 @@ }, "testTargets" : [ { - "parallelizable" : true, "target" : { "containerPath" : "container:iOS-Cocoapods-Swift6.xcodeproj", "identifier" : "D4DC1E792D6F0FAD00F562AA", - "name" : "iOS-Cocoapods-Swift6-UITests" + "name" : "UITests" } } ], diff --git a/Plans/macOS-SwiftUI_Base.xctestplan b/Plans/macOS-SwiftUI_Base.xctestplan deleted file mode 100644 index 0125f11968a..00000000000 --- a/Plans/macOS-SwiftUI_Base.xctestplan +++ /dev/null @@ -1,18 +0,0 @@ -{ - "configurations" : [ - { - "id" : "232A08C3-49ED-43CF-BE70-9AD86310BF97", - "name" : "Configuration 1", - "options" : { - - } - } - ], - "defaultOptions" : { - "uiTestingScreenshotsLifetime" : "keepAlways" - }, - "testTargets" : [ - - ], - "version" : 1 -} diff --git a/README.md b/README.md index c1aa5c3f57f..463d64ae18f 100644 --- a/README.md +++ b/README.md @@ -9,28 +9,17 @@ _Bad software is everywhere, and we're tired of it. Sentry is on a mission to he # Official Sentry SDK for iOS / tvOS / macOS / watchOS (1) [![Build](https://img.shields.io/github/actions/workflow/status/getsentry/sentry-cocoa/build.yml?branch=main)](https://github.com/getsentry/sentry-cocoa/actions/workflows/build.yml?query=branch%3Amain) -[![codebeat badge](https://codebeat.co/badges/07f0bc91-9102-4fd8-99a6-30b25dc98037)](https://codebeat.co/projects/github-com-getsentry-sentry-cocoa-master) [![codecov.io](https://codecov.io/gh/getsentry/sentry-cocoa/branch/master/graph/badge.svg)](https://codecov.io/gh/getsentry/sentry-cocoa) -[![CocoaPods compadible](https://img.shields.io/cocoapods/v/Sentry.svg)](https://cocoapods.org/pods/Sentry) +[![CocoaPods compatible](https://img.shields.io/cocoapods/v/Sentry.svg)](https://cocoapods.org/pods/Sentry) [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![SwiftPM compatible](https://img.shields.io/badge/spm-compatible-brightgreen.svg?style=flat)](https://swift.org/package-manager) ![platforms](https://img.shields.io/cocoapods/p/Sentry.svg?style=flat) [![Swift Package Index](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fgetsentry%2Fsentry-cocoa%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/getsentry/sentry-cocoa) -[![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K) +[![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.com/invite/sentry) -This SDK is written in Objective-C but also provides a nice Swift interface. +# Installation -# Releases - -This repo uses the following ways to release SDK updates: - -- `Pre-release`: We create pre-releases (alpha, beta, RC,…) for larger and potentially more impactful changes, such as new features or major versions. -- `Latest`: We continuously release major/minor/hotfix versions from the `main` branch. These releases go through all our internal quality gates and are very safe to use and intended to be the default for most teams. -- `Stable`: We promote releases from `Latest` when they have been used in the field for some time and in scale, considering time since release, adoption, and other quality and stability metrics. These releases will be indicated on the [releases page](https://github.com/getsentry/sentry-cocoa/releases/) with the `Stable` suffix. - -**Where is the master branch?** - -We renamed the default branch from `master` to `main`. +SPM is the recommended way to include Sentry into your project, but we also support [CocoaPods](https://cocoapods.org/pods/Sentry) and Carthage, and provide pre-built XCFrameworks on [our GitHub Releases page](https://github.com/getsentry/sentry-cocoa/releases). # Initialization @@ -77,7 +66,7 @@ For more information checkout the [docs](https://docs.sentry.io/platforms/apple) - [![Documentation](https://img.shields.io/badge/documentation-sentry.io-green.svg)](https://docs.sentry.io/platforms/apple/) - [![Discussions](https://img.shields.io/github/discussions/getsentry/sentry-cocoa.svg)](https://github.com/getsentry/sentry-cocoa/discussions) -- [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.gg/PXa5Apfe7K) +- [![Discord Chat](https://img.shields.io/discord/621778831602221064?logo=discord&logoColor=ffffff&color=7389D8)](https://discord.com/invite/sentry) - [![Stack Overflow](https://img.shields.io/badge/stack%20overflow-sentry-green.svg)](http://stackoverflow.com/questions/tagged/sentry) - [![Code of Conduct](https://img.shields.io/badge/code%20of%20conduct-sentry-green.svg)](https://github.com/getsentry/.github/blob/master/CODE_OF_CONDUCT.md) - [![Twitter Follow](https://img.shields.io/twitter/follow/getsentry?label=getsentry&style=social)](https://twitter.com/intent/follow?screen_name=getsentry) diff --git a/Samples/README.md b/Samples/README.md index 0237d94de91..2f542ec897a 100644 --- a/Samples/README.md +++ b/Samples/README.md @@ -1,9 +1,30 @@ # Samples -Sample applications used as test hosts and manual acceptance testing. +Sample applications used as UI test hosts and manual acceptance testing. Most subdirectories contain an xcodeproj per platform/version, with one or more targets describing variants of applications targeting it, and including the Sentry SDK via a subproject reference. Each sample xcodeproj is included in the top level Sentry.xcworkspace. +## Project Structure + +- Uses `xcodegen` with YAML configuration files for sample apps +- Sample configurations in `Samples/*/[AppName].yml` +- Shared configurations and code in `Samples/SentrySampleShared/` +- Run `make xcode` after checkout to ensure projects are up-to-date + +## SDK Configuration + +The iOS-Swift and iOS-ObjectiveC sample apps have schema launch args and environment variables available to customize how the SDK is configured. + +In iOS-Swift, these can also be modified at runtime, to help test various configurations in scenarios where using launch args and environment variables isn't possible, like TestFlight builds. Runtime overrides are set via `UserDefaults`. They interact with schema launch arguments and environment variables as follows: - Boolean flags are ORed together: if either a `true` is set in User Defaults, or a launch argument is set, then the override takes effect. - Values written to user defaults take precedence over schema environment variables by default. If you want to give precedence to schema environment vars over user defaults values, enable the launch arg `--io.sentry.special.schema-environment-variable-precedence`. + +Note that if a key we use to write a boolean value to defaults isn't present in defaults, then UserDefaults returns `false` for the query by default. We write all environment variables as strings, so that by default, if the associated key isn't present, `UserDefaults` returns `nil` (if we directly wrote and read Floats, for example, defaults would return `0` if the key isn't present, and we'd have to do more work to disambiguate that from having overridden it to 0, for cases where 0 isn't the default we want to set in the sample app). + +You can see the current override value being used in the "Features" tab. + +You can also remove all stored values in user defaults by launching with `--io.sentry.special.wipe-data`. See `SentrySDKWrapper.swift` and `SentrySDKOverrides.swift` for usages. + +Note that in-app overrides don't take effect until the app is relaunched (and not simply backgrounded and then foregrounded again). This means that if you want to test changes to launch profiling, you must change the settings, then relaunch the app for the launch profile configuration to be written to disk, and then relaunch once more for the launch profile scenario to actually be tested. + ## Automatically created Sentry tags To help pinpoint where to look to debug an issue we see on our Sentry dashboard for the `sentry-sdks` project for events coming from our sample apps, each sample app injects some information from the build environment automatically. @@ -13,3 +34,38 @@ To help pinpoint where to look to debug an issue we see on our Sentry dashboard - visionOS-Swift because I was unable to build and test it - `SentryUser.username` is automatically set to the `SIMULATOR_HOST_HOME` if it is defined, which is usually the value of `whoami` on a developer's work machine. This can be overridden in the scheme with the environment variable key `--io.sentry.user.username` if you need something more specific for your tests. - `SentryUser.email` is hardcoded to `"tony@example.comn"` but can be overridden using the environment variable `--io.sentry.user.email` in the scheme. + +## Code Signing + +This repository follows the [codesiging.guide](https://codesigning.guide/) in combination with [fastlane match](https://docs.fastlane.tools/actions/match/). +Therefore the sample apps use manual code signing, see [fastlane docs](https://docs.fastlane.tools/codesigning/xcode-project/): + +> In most cases, fastlane will work out of the box with Xcode 9 and up if you selected manual code signing and choose a provisioning profile name for each of your targets. + +### Creating new App Identifiers + +E.g. if you create a new extension target, like a File Provider for iOS-Swift, make sure it has a unique bundle identifier like `io.sentry.sample.iOS-Swift.FileProvider`. Then, run the following terminal command: + +``` +rbenv exec bundle exec fastlane produce -u andrew.mcknight@sentry.io --skip_itc -a io.sentry.sample.iOS-Swift.FileProvider +``` + +You'll be prompted for an Apple Developer Portal 2FA code, and the description for the identifier; in this example, "Sentry Cocoa Sample Swift File Provider Extension". + +### Creating provisioning profiles + +For an existing app identifier, run the terminal command, after changing the email address in the Matchfile to your personal ADP account's: + +``` +rbenv exec bundle exec fastlane match development --app_identifier io.sentry.sample.iOS-Swift.FileProvider +``` + +You can include the `--force` option to regenerate an existing profile. + +You can run samples in a real device without changing certificates and provisioning profiles if you are a Sentry employee with access to Sentry [profiles repository](https://github.com/getsentry/codesigning) and 1Password account. + +- Configure your environment to use SSH to access GitHub. Follow [this instructions](https://docs.github.com/en/authentication/connecting-to-github-with-ssh). +- You will need `Cocoa codesigning match encryption password` from your Sentry 1Password account. +- run `fastlane match_local` + +This will setup certificates and provisioning profiles into your machine, but in order to be able to run a sample in a real device you need to register that device with Sentry AppConnect account, add the device to the provisioning profile you want to use, download the profile again and open it with Xcode. diff --git a/Samples/SentrySampleShared/SentrySampleShared.xcconfig b/Samples/SentrySampleShared/SentrySampleShared.xcconfig index 8ae81dfd2c1..445fcb4c1dd 100644 --- a/Samples/SentrySampleShared/SentrySampleShared.xcconfig +++ b/Samples/SentrySampleShared/SentrySampleShared.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentrySampleShared INFOPLIST_FILE = SentrySampleShared/Info.plist diff --git a/Samples/SentrySampleShared/SentrySampleShared.yml b/Samples/SentrySampleShared/SentrySampleShared.yml index c06e7181aa4..30c0b4a041e 100644 --- a/Samples/SentrySampleShared/SentrySampleShared.yml +++ b/Samples/SentrySampleShared/SentrySampleShared.yml @@ -3,6 +3,7 @@ createIntermediateGroups: true generateEmptyDirectories: true configs: Debug: debug + DebugV9: debug Test: debug TestCI: debug Release: release @@ -24,6 +25,7 @@ targets: - target: Sentry/Sentry configFiles: Debug: SentrySampleShared.xcconfig + DebugV9: SentrySampleShared.xcconfig Release: SentrySampleShared.xcconfig Test: SentrySampleShared.xcconfig TestCI: SentrySampleShared.xcconfig diff --git a/Samples/SentrySampleShared/SentrySampleShared/SentrySDKOverrides.swift b/Samples/SentrySampleShared/SentrySampleShared/SentrySDKOverrides.swift index a2049f3a212..f98701f99c7 100644 --- a/Samples/SentrySampleShared/SentrySampleShared/SentrySDKOverrides.swift +++ b/Samples/SentrySampleShared/SentrySampleShared/SentrySDKOverrides.swift @@ -1,3 +1,5 @@ +// swiftlint:disable file_length + import Foundation public enum OverrideType { @@ -29,7 +31,7 @@ public enum SentrySDKOverrides: String, CaseIterable { } public static var schemaPrecedenceForEnvironmentVariables: Bool { - ProcessInfo.processInfo.arguments.contains("--io.sentry.schema-environment-variable-precedence") + ProcessInfo.processInfo.arguments.contains("--io.sentry.special.schema-environment-variable-precedence") } /// Helps quickly traverse using an NSIndexPath for driving a table view. @@ -39,103 +41,134 @@ public enum SentrySDKOverrides: String, CaseIterable { case .feedback: return SentrySDKOverrides.Feedback.allCases case .performance: return SentrySDKOverrides.Performance.allCases case .sessionReplay: return SentrySDKOverrides.SessionReplay.allCases + case .screenshot: return SentrySDKOverrides.Screenshot.allCases + case .events: return SentrySDKOverrides.Events.allCases case .other: return SentrySDKOverrides.Other.allCases case .tracing: return SentrySDKOverrides.Tracing.allCases case .profiling: return SentrySDKOverrides.Profiling.allCases + case .networking: return SentrySDKOverrides.Networking.allCases } } public enum Special: String, SentrySDKOverride { - case wipeDataOnLaunch = "--io.sentry.wipe-data" - case disableEverything = "--io.sentry.disable-everything" - case skipSDKInit = "--skip-sentry-init" - case disableDebugMode = "--io.sentry.disable-debug-mode" + case wipeDataOnLaunch = "--io.sentry.special.wipe-data" + case disableEverything = "--io.sentry.special.disable-everything" + case skipSDKInit = "--io.sentry.special.skip-sentry-init" + case disableDebugMode = "--io.sentry.special.disable-debug-mode" + case dsn = "--io.sentry.special.dsn" } case special = "Special" public enum Feedback: String, SentrySDKOverride { - case allDefaults = "--io.sentry.feedback.all-defaults" - case disableAutoInject = "--io.sentry.feedback.no-auto-inject-widget" - case noWidgetText = "--io.sentry.feedback.no-widget-text" - case noWidgetIcon = "--io.sentry.feedback.no-widget-icon" - case noUserInjection = "--io.sentry.feedback.dont-use-sentry-user" - case requireEmail = "--io.sentry.feedback.require-email" - case requireName = "--io.sentry.feedback.require-name" - case noAnimations = "--io.sentry.feedback.no-animations" - case injectScreenshot = "--io.sentry.feedback.inject-screenshot" - case useCustomFeedbackButton = "--io.sentry.feedback.use-custom-feedback-button" - case noScreenshots = "--io.sentry.feedback.no-screenshots" - case noShakeGesture = "--io.sentry.feedback.no-shake-gesture" + case allDefaults = "--io.sentry.feedback.all-defaults" + case disableAutoInject = "--io.sentry.feedback.no-auto-inject-widget" + case noWidgetText = "--io.sentry.feedback.no-widget-text" + case noWidgetIcon = "--io.sentry.feedback.no-widget-icon" + case noUserInjection = "--io.sentry.feedback.dont-use-sentry-user" + case requireEmail = "--io.sentry.feedback.require-email" + case requireName = "--io.sentry.feedback.require-name" + case noAnimations = "--io.sentry.feedback.no-animations" + case injectScreenshot = "--io.sentry.feedback.inject-screenshot" + case useCustomFeedbackButton = "--io.sentry.feedback.use-custom-feedback-button" + case noScreenshots = "--io.sentry.feedback.no-screenshots" + case noShakeGesture = "--io.sentry.feedback.no-shake-gesture" } case feedback = "Feedback" + public enum Events: String, SentrySDKOverride { + case sampleRate = "--io.sentry.events.sampleRate" + case rejectAll = "--io.sentry.events.reject-all" + } + case events = "Events" + public enum Performance: String, SentrySDKOverride { - case disableTimeToFullDisplayTracing = "--disable-time-to-full-display-tracing" - case disablePerformanceV2 = "--disable-performance-v2" - case disableAppHangTrackingV2 = "--disable-app-hang-tracking-v2" - case disableSessionTracking = "--disable-automatic-session-tracking" - case disableFileIOTracing = "--disable-file-io-tracing" - case disableUIVCTracing = "--disable-uiviewcontroller-tracing" - case disableNetworkTracing = "--disable-network-tracking" - case disableCoreDataTracing = "--disable-core-data-tracing" - case disableANRTracking = "--disable-anr-tracking" - case disableWatchdogTracking = "--disable-watchdog-tracking" - case disableUITracing = "--disable-ui-tracing" - case disablePrewarmedAppStartTracing = "--disable-prewarmed-app-start-tracing" - case disablePerformanceTracing = "--disable-auto-performance-tracing" - case sessionTrackingIntervalMillis = "--io.sentry.sessionTrackingIntervalMillis" + case disableTimeToFullDisplayTracing = "--io.sentry.performance.disable-time-to-full-display-tracing" + case disablePerformanceV2 = "--io.sentry.performance.disable-performance-v2" + case disableAppHangTrackingV2 = "--io.sentry.performance.disable-app-hang-tracking-v2" + case disableSessionTracking = "--io.sentry.performance.disable-automatic-session-tracking" + case disableFileIOTracing = "--io.sentry.performance.disable-file-io-tracing" + case disableUIVCTracing = "--io.sentry.performance.disable-uiviewcontroller-tracing" + case disableCoreDataTracing = "--io.sentry.performance.disable-core-data-tracing" + case disableANRTracking = "--io.sentry.performance.disable-anr-tracking" + case disableWatchdogTracking = "--io.sentry.performance.disable-watchdog-tracking" + case disableUITracing = "--io.sentry.performance.disable-ui-tracing" + case disablePrewarmedAppStartTracing = "--io.sentry.performance.disable-prewarmed-app-start-tracing" + case disablePerformanceTracing = "--io.sentry.performance.disable-auto-performance-tracing" + case sessionTrackingIntervalMillis = "--io.sentry.performance.sessionTrackingIntervalMillis" } case performance = "Performance" public enum SessionReplay: String, SentrySDKOverride { - case disableSessionReplay = "--disable-session-replay" - case disableViewRendererV2 = "--io.sentry.session-replay.disableViewRendereV2" - case enableFastViewRendering = "--io.sentry.session-replay.enableFastViewRendering" - case sampleRate = "--io.sentry.sessionReplaySampleRate" - case onErrorSampleRate = "--io.sentry.sessionReplayOnErrorSampleRate" - case quality = "--io.sentry.sessionReplayQuality" - case disableMaskAllText = "--io.sentry.session-replay.disable-mask-all-text" + case disable = "--io.sentry.session-replay.disable" + + case onErrorSampleRate = "--io.sentry.session-replay.on-error-sample-rate" + case sessionSampleRate = "--io.sentry.session-replay.session-sample-rate" + case quality = "--io.sentry.session-replay.quality" + + case disableViewRendererV2 = "--io.sentry.session-replay.disable-view-renderer-v2" + case enableFastViewRendering = "--io.sentry.session-replay.enable-fast-view-rendering" + case disableMaskAllImages = "--io.sentry.session-replay.disable-mask-all-images" + case disableMaskAllText = "--io.sentry.session-replay.disable-mask-all-text" } case sessionReplay = "Session Replay" + public enum Screenshot: String, SentrySDKOverride { + case disableViewRendererV2 = "--io.sentry.screenshot.disable-view-renderer-v2" + case enableFastViewRendering = "--io.sentry.screenshot.enable-fast-view-rendering" + case disableMaskAllImages = "--io.sentry.screenshot.disable-mask-all-images" + case disableMaskAllText = "--io.sentry.screenshot.disable-mask-all-text" + } + case screenshot = "Screenshot" + + public enum Networking: String, SentrySDKOverride { + case disableBreadcrumbs = "--io.sentry.networking.disable-breadcrumbs" + case disablePerformanceTracking = "--io.sentry.networking.disable-tracking" + case disableFailedRequestTracking = "--io.sentry.networking.disable-failed-request-tracking" + } + case networking = "Networking" + public enum Other: String, SentrySDKOverride { - case disableAttachScreenshot = "--disable-attach-screenshot" - case disableAttachViewHierarchy = "--disable-attach-view-hierarchy" - case rejectAllEvents = "--reject-all-events" - case rejectAllSpans = "--reject-all-spans" - case rejectScreenshots = "--reject-screenshots-in-before-capture-screenshot" - case rejectViewHierarchy = "--reject-view-hierarchy-in-before-capture-view-hierarchy" - case disableMetricKit = "--disable-metrickit-integration" - case disableMetricKitRawPayloads = "--disable-metrickit-raw-payloads" - case disableBreadcrumbs = "--disable-automatic-breadcrumbs" - case disableNetworkBreadcrumbs = "--disable-network-breadcrumbs" - case disableSwizzling = "--disable-swizzling" - case disableCrashHandling = "--disable-crash-handler" - case disableSpotlight = "--disable-spotlight" - case disableFileManagerSwizzling = "--disable-filemanager-swizzling" - case username = "--io.sentry.user.username" - case userFullName = "--io.sentry.user.name" - case userEmail = "--io.sentry.user.email" - case userID = "--io.sentry.user.id" - case environment = "--io.sentry.sdk-environment" + case disableAttachScreenshot = "--io.sentry.other.disable-attach-screenshot" + case disableAttachViewHierarchy = "--io.sentry.other.disable-attach-view-hierarchy" + case rejectAllSpans = "--io.sentry.other.reject-all-spans" + case rejectScreenshots = "--io.sentry.other.reject-screenshots-in-before-capture-screenshot" + case rejectViewHierarchy = "--io.sentry.other.reject-view-hierarchy-in-before-capture-view-hierarchy" + case disableMetricKit = "--io.sentry.other.disable-metrickit-integration" + case disableMetricKitRawPayloads = "--io.sentry.other.disable-metrickit-raw-payloads" + case disableBreadcrumbs = "--io.sentry.other.disable-automatic-breadcrumbs" + case disableSwizzling = "--io.sentry.other.disable-swizzling" + case disableCrashHandling = "--io.sentry.other.disable-crash-handler" + case disableSpotlight = "--io.sentry.other.disable-spotlight" + case disableFileManagerSwizzling = "--io.sentry.other.disable-filemanager-swizzling" + case base64AttachmentData = "--io.sentry.other.base64-attachment-data" + case disableHttpTransport = "--io.sentry.other.disable-http-transport" + case username = "--io.sentry.scope.user.username" + case userFullName = "--io.sentry.scope.user.name" + case userEmail = "--io.sentry.scope.user.email" + case userID = "--io.sentry.scope.user.id" + case environment = "--io.sentry.scope.sdk-environment" } case other = "Other" public enum Tracing: String, SentrySDKOverride { - case sampleRate = "--io.sentry.tracesSampleRate" - case samplerValue = "--io.sentry.tracesSamplerValue" - case disableTracing = "--io.sentry.disable-tracing" + case sampleRate = "--io.sentry.tracing.tracesSampleRate" + case samplerValue = "--io.sentry.tracing.tracesSamplerValue" + case disableTracing = "--io.sentry.tracing.disable-tracing" } case tracing = "Tracing" public enum Profiling: String, SentrySDKOverride { - case sampleRate = "--io.sentry.profilesSampleRate" - case samplerValue = "--io.sentry.profilesSamplerValue" - case disableAppStartProfiling = "--io.sentry.disable-app-start-profiling" - case manualLifecycle = "--io.sentry.profile-lifecycle-manual" - case sessionSampleRate = "--io.sentry.profile-session-sample-rate" - case disableUIProfiling = "--io.sentry.disable-ui-profiling" + #if !SDK_V9 + case sampleRate = "--io.sentry.profiling.profilesSampleRate" + case samplerValue = "--io.sentry.profiling.profilesSamplerValue" + #endif // !SDK_V9 + case disableAppStartProfiling = "--io.sentry.profiling.disable-app-start-profiling" + case manualLifecycle = "--io.sentry.profiling.profile-lifecycle-manual" + case sessionSampleRate = "--io.sentry.profiling.profile-session-sample-rate" + case disableUIProfiling = "--io.sentry.profiling.disable-ui-profiling" + case slowLoadMethod = "--io.sentry.profiling.slow-load-method" + case immediateStop = "--io.sentry.profiling.continuous-profiler-immediate-stop" } case profiling = "Profiling" } @@ -233,8 +266,12 @@ private extension SentrySDKOverride { extension SentrySDKOverrides.Profiling { public var overrideType: OverrideType { switch self { + #if SDK_V9 + case .sessionSampleRate: return .float + #else case .sampleRate, .samplerValue, .sessionSampleRate: return .float - case .disableAppStartProfiling, .manualLifecycle, .disableUIProfiling: return .boolean + #endif // !SDK_V9 + case .disableAppStartProfiling, .manualLifecycle, .disableUIProfiling, .slowLoadMethod, .immediateStop: return .boolean } } } @@ -248,10 +285,28 @@ extension SentrySDKOverrides.Tracing { } } +extension SentrySDKOverrides.Networking { + public var overrideType: OverrideType { + switch self { + case .disableBreadcrumbs, .disablePerformanceTracking, .disableFailedRequestTracking: return .boolean + } + } +} + +extension SentrySDKOverrides.Events { + public var overrideType: OverrideType { + switch self { + case .rejectAll: return .boolean + case .sampleRate: return .float + } + } + +} + extension SentrySDKOverrides.Other { public var overrideType: OverrideType { switch self { - case .disableAttachScreenshot, .disableAttachViewHierarchy, .rejectScreenshots, .rejectViewHierarchy, .disableMetricKit, .disableMetricKitRawPayloads, .disableBreadcrumbs, .disableNetworkBreadcrumbs, .disableSwizzling, .disableCrashHandling, .disableSpotlight, .disableFileManagerSwizzling, .rejectAllSpans, .rejectAllEvents: return .boolean + case .disableAttachScreenshot, .disableAttachViewHierarchy, .rejectScreenshots, .rejectViewHierarchy, .disableMetricKit, .disableMetricKitRawPayloads, .disableBreadcrumbs, .disableSwizzling, .disableCrashHandling, .disableSpotlight, .disableFileManagerSwizzling, .rejectAllSpans, .base64AttachmentData, .disableHttpTransport: return .boolean case .username, .userFullName, .userEmail, .userID, .environment: return .string } } @@ -260,7 +315,7 @@ extension SentrySDKOverrides.Other { extension SentrySDKOverrides.Performance { public var overrideType: OverrideType { switch self { - case .disableTimeToFullDisplayTracing, .disablePerformanceV2, .disableAppHangTrackingV2, .disableSessionTracking, .disableFileIOTracing, .disableUIVCTracing, .disableNetworkTracing, .disableCoreDataTracing, .disableANRTracking, .disableWatchdogTracking, .disableUITracing, .disablePrewarmedAppStartTracing, .disablePerformanceTracing: return .boolean + case .disableTimeToFullDisplayTracing, .disablePerformanceV2, .disableAppHangTrackingV2, .disableSessionTracking, .disableFileIOTracing, .disableUIVCTracing, .disableCoreDataTracing, .disableANRTracking, .disableWatchdogTracking, .disableUITracing, .disablePrewarmedAppStartTracing, .disablePerformanceTracing: return .boolean case .sessionTrackingIntervalMillis: return .string } } @@ -269,13 +324,21 @@ extension SentrySDKOverrides.Performance { extension SentrySDKOverrides.SessionReplay { public var overrideType: OverrideType { switch self { - case .disableSessionReplay, .disableViewRendererV2, .enableFastViewRendering, .disableMaskAllText, .disableMaskAllImages: return .boolean - case .onErrorSampleRate, .sampleRate: return .float + case .disable, .disableViewRendererV2, .enableFastViewRendering, .disableMaskAllText, .disableMaskAllImages: return .boolean + case .onErrorSampleRate, .sessionSampleRate: return .float case .quality: return .string } } } +extension SentrySDKOverrides.Screenshot { + public var overrideType: OverrideType { + switch self { + case .disableViewRendererV2, .enableFastViewRendering, .disableMaskAllText, .disableMaskAllImages: return .boolean + } + } +} + extension SentrySDKOverrides.Feedback { public var overrideType: OverrideType { switch self { @@ -288,6 +351,7 @@ extension SentrySDKOverrides.Special { public var overrideType: OverrideType { switch self { case .wipeDataOnLaunch, .disableEverything, .skipSDKInit, .disableDebugMode: return .boolean + case .dsn: return .string } } } @@ -299,7 +363,11 @@ extension SentrySDKOverrides.Special { extension SentrySDKOverrides.Profiling { public var ignoresDisableEverything: Bool { switch self { - case .sampleRate, .samplerValue, .sessionSampleRate, .manualLifecycle: return true + #if SDK_V9 + case .sessionSampleRate, .manualLifecycle, .slowLoadMethod, .immediateStop: return true + #else + case .sampleRate, .samplerValue, .sessionSampleRate, .manualLifecycle, .slowLoadMethod, .immediateStop: return true + #endif // SDK_V9 case .disableAppStartProfiling, .disableUIProfiling: return false } } @@ -314,11 +382,19 @@ extension SentrySDKOverrides.Tracing { } } +extension SentrySDKOverrides.Networking { + public var ignoresDisableEverything: Bool { return false } +} + +extension SentrySDKOverrides.Events { + public var ignoresDisableEverything: Bool { return false } +} + extension SentrySDKOverrides.Other { public var ignoresDisableEverything: Bool { switch self { - case .rejectScreenshots, .rejectViewHierarchy, .rejectAllSpans, .rejectAllEvents, .username, .userFullName, .userEmail, .userID, .environment: return true - case .disableAttachScreenshot, .disableAttachViewHierarchy, .disableMetricKit, .disableMetricKitRawPayloads, .disableBreadcrumbs, .disableNetworkBreadcrumbs, .disableSwizzling, .disableCrashHandling, .disableSpotlight, .disableFileManagerSwizzling: return false + case .rejectScreenshots, .rejectViewHierarchy, .rejectAllSpans, .username, .userFullName, .userEmail, .userID, .environment, .base64AttachmentData: return true + case .disableAttachScreenshot, .disableAttachViewHierarchy, .disableMetricKit, .disableMetricKitRawPayloads, .disableBreadcrumbs, .disableSwizzling, .disableCrashHandling, .disableSpotlight, .disableFileManagerSwizzling, .disableHttpTransport: return false } } } @@ -326,7 +402,7 @@ extension SentrySDKOverrides.Other { extension SentrySDKOverrides.Performance { public var ignoresDisableEverything: Bool { switch self { - case .disableTimeToFullDisplayTracing, .disablePerformanceV2, .disableAppHangTrackingV2, .disableSessionTracking, .disableFileIOTracing, .disableUIVCTracing, .disableNetworkTracing, .disableCoreDataTracing, .disableANRTracking, .disableWatchdogTracking, .disableUITracing, .disablePrewarmedAppStartTracing, .disablePerformanceTracing: return false + case .disableTimeToFullDisplayTracing, .disablePerformanceV2, .disableAppHangTrackingV2, .disableSessionTracking, .disableFileIOTracing, .disableUIVCTracing, .disableCoreDataTracing, .disableANRTracking, .disableWatchdogTracking, .disableUITracing, .disablePrewarmedAppStartTracing, .disablePerformanceTracing: return false case .sessionTrackingIntervalMillis: return true } } @@ -335,8 +411,16 @@ extension SentrySDKOverrides.Performance { extension SentrySDKOverrides.SessionReplay { public var ignoresDisableEverything: Bool { switch self { - case .disableSessionReplay: return false - case .disableViewRendererV2, .enableFastViewRendering, .disableMaskAllText, .disableMaskAllImages, .onErrorSampleRate, .sampleRate, .quality: return true + case .disable: return false + case .disableViewRendererV2, .enableFastViewRendering, .disableMaskAllText, .disableMaskAllImages, .onErrorSampleRate, .sessionSampleRate, .quality: return true + } + } +} + +extension SentrySDKOverrides.Screenshot { + public var ignoresDisableEverything: Bool { + switch self { + case .disableViewRendererV2, .enableFastViewRendering, .disableMaskAllText, .disableMaskAllImages: return false } } } @@ -352,7 +436,9 @@ extension SentrySDKOverrides.Feedback { extension SentrySDKOverrides.Special { public var ignoresDisableEverything: Bool { switch self { - case .wipeDataOnLaunch, .disableEverything, .skipSDKInit, .disableDebugMode: return true + case .wipeDataOnLaunch, .disableEverything, .skipSDKInit, .disableDebugMode, .dsn: return true } } } + +// swiftlint:enable file_length diff --git a/Samples/SentrySampleShared/SentrySampleShared/SentrySDKWrapper.swift b/Samples/SentrySampleShared/SentrySampleShared/SentrySDKWrapper.swift index b76d5a2d3dd..8a576115d18 100644 --- a/Samples/SentrySampleShared/SentrySampleShared/SentrySDKWrapper.swift +++ b/Samples/SentrySampleShared/SentrySampleShared/SentrySDKWrapper.swift @@ -33,8 +33,11 @@ public struct SentrySDKWrapper { func configureSentryOptions(options: Options) { options.dsn = dsn + if let sampleRate = SentrySDKOverrides.Events.sampleRate.floatValue { + options.sampleRate = NSNumber(value: sampleRate) + } options.beforeSend = { - guard !SentrySDKOverrides.Other.rejectAllEvents.boolValue else { return nil } + guard !SentrySDKOverrides.Events.rejectAll.boolValue else { return nil } return $0 } options.beforeSendSpan = { @@ -46,21 +49,18 @@ public struct SentrySDKWrapper { options.debug = !SentrySDKOverrides.Special.disableDebugMode.boolValue #if !os(macOS) && !os(watchOS) && !os(visionOS) - if #available(iOS 16.0, *), !SentrySDKOverrides.SessionReplay.disableSessionReplay.boolValue { + if #available(iOS 16.0, *), !SentrySDKOverrides.SessionReplay.disable.boolValue { options.sessionReplay = SentryReplayOptions( - sessionSampleRate: SentrySDKOverrides.SessionReplay.sampleRate.floatValue ?? 0, + sessionSampleRate: SentrySDKOverrides.SessionReplay.sessionSampleRate.floatValue ?? 0, onErrorSampleRate: SentrySDKOverrides.SessionReplay.onErrorSampleRate.floatValue ?? 1, maskAllText: !SentrySDKOverrides.SessionReplay.disableMaskAllText.boolValue, - maskAllImages: !SentrySDKOverrides.SessionReplay.disableMaskAllImages.boolValue + maskAllImages: !SentrySDKOverrides.SessionReplay.disableMaskAllImages.boolValue, + enableViewRendererV2: !SentrySDKOverrides.SessionReplay.disableViewRendererV2.boolValue, + // Disable the fast view rendering, because we noticed parts (like the tab bar) are not rendered correctly + enableFastViewRendering: SentrySDKOverrides.SessionReplay.enableFastViewRendering.boolValue ) - - let defaultReplayQuality = SentryReplayOptions.SentryReplayQuality.high + let defaultReplayQuality = options.sessionReplay.quality options.sessionReplay.quality = SentryReplayOptions.SentryReplayQuality(rawValue: (SentrySDKOverrides.SessionReplay.quality.stringValue as? NSString)?.integerValue ?? defaultReplayQuality.rawValue) ?? defaultReplayQuality - - options.sessionReplay.enableViewRendererV2 = !SentrySDKOverrides.SessionReplay.disableViewRendererV2.boolValue - - // Disable the fast view rendering, because we noticed parts (like the tab bar) are not rendered correctly - options.sessionReplay.enableFastViewRendering = SentrySDKOverrides.SessionReplay.enableFastViewRendering.boolValue } #if !os(tvOS) @@ -98,9 +98,19 @@ public struct SentrySDKWrapper { options.enablePreWarmedAppStartTracing = !isBenchmarking && !SentrySDKOverrides.Performance.disablePrewarmedAppStartTracing.boolValue options.enableUIViewControllerTracing = !SentrySDKOverrides.Performance.disableUIVCTracing.boolValue + + // -- Screenshot Options -- options.attachScreenshot = !SentrySDKOverrides.Other.disableAttachScreenshot.boolValue + options.screenshot.enableViewRendererV2 = !SentrySDKOverrides.Screenshot.disableViewRendererV2.boolValue + // The fast view renderer is opt-in, therefore it is assumed to be disabled by default. + options.screenshot.enableFastViewRendering = SentrySDKOverrides.Screenshot.enableFastViewRendering.boolValue + options.screenshot.maskAllImages = !SentrySDKOverrides.Screenshot.disableMaskAllImages.boolValue + options.screenshot.maskAllText = !SentrySDKOverrides.Screenshot.disableMaskAllText.boolValue + options.attachViewHierarchy = !SentrySDKOverrides.Other.disableAttachViewHierarchy.boolValue + #if !SDK_V9 options.enableAppHangTrackingV2 = !SentrySDKOverrides.Performance.disableAppHangTrackingV2.boolValue + #endif // SDK_V9 #endif // !os(macOS) && !os(watchOS) // disable during benchmarks because we run CPU for 15 seconds at full throttle which can trigger ANRs @@ -110,13 +120,17 @@ public struct SentrySDKWrapper { options.enableWatchdogTerminationTracking = !isUITest && !isBenchmarking && !SentrySDKOverrides.Performance.disableWatchdogTracking.boolValue options.enableAutoPerformanceTracing = !isBenchmarking && !SentrySDKOverrides.Performance.disablePerformanceTracing.boolValue + #if !SDK_V9 options.enableTracing = !isBenchmarking && !SentrySDKOverrides.Tracing.disableTracing.boolValue + #endif // !SDK_V9 + + options.enableNetworkTracking = !SentrySDKOverrides.Networking.disablePerformanceTracking.boolValue + options.enableCaptureFailedRequests = !SentrySDKOverrides.Networking.disableFailedRequestTracking.boolValue + options.enableNetworkBreadcrumbs = !SentrySDKOverrides.Networking.disableBreadcrumbs.boolValue options.enableFileIOTracing = !SentrySDKOverrides.Performance.disableFileIOTracing.boolValue options.enableAutoBreadcrumbTracking = !SentrySDKOverrides.Other.disableBreadcrumbs.boolValue - options.enableNetworkTracking = !SentrySDKOverrides.Performance.disableNetworkTracing.boolValue options.enableCoreDataTracing = !SentrySDKOverrides.Performance.disableCoreDataTracing.boolValue - options.enableNetworkBreadcrumbs = !SentrySDKOverrides.Other.disableNetworkBreadcrumbs.boolValue options.enableSwizzling = !SentrySDKOverrides.Other.disableSwizzling.boolValue options.enableCrashHandler = !SentrySDKOverrides.Other.disableCrashHandling.boolValue options.enablePersistingTracesWhenCrashing = true @@ -137,7 +151,9 @@ public struct SentrySDKWrapper { return breadcrumb } - options.initialScope = configureInitialScope(scope:) + options.initialScope = { scope in + configureInitialScope(scope: scope, options: options) + } #if !os(macOS) && !os(tvOS) && !os(watchOS) && !os(visionOS) if #available(iOS 13.0, *) { @@ -150,7 +166,7 @@ public struct SentrySDKWrapper { options.experimental.enableUnhandledCPPExceptionsV2 = true } - func configureInitialScope(scope: Scope) -> Scope { + func configureInitialScope(scope: Scope, options: Options) -> Scope { if let environmentOverride = SentrySDKOverrides.Other.environment.stringValue { scope.setEnvironment(environmentOverride) } else if isBenchmarking { @@ -169,6 +185,7 @@ public struct SentrySDKWrapper { scope.setTag(value: uiTestName, key: "ui-test-name") } + setTagsForConfiguredOverrides(scope: scope) injectGitInformation(scope: scope) let user = User(userId: SentrySDKOverrides.Other.userID.stringValue ?? "1") @@ -182,6 +199,7 @@ public struct SentrySDKWrapper { } let data = Data("hello".utf8) scope.addAttachment(Attachment(data: data, filename: "log.txt")) + return scope } @@ -201,6 +219,35 @@ public struct SentrySDKWrapper { } return username } + + private func setTagsForConfiguredOverrides(scope: Scope) { + for overrideCategory in SentrySDKOverrides.allCases { + for flag in overrideCategory.featureFlags { + let tagKey = cleanTagKey(from: flag.rawValue) + + switch flag.overrideType { + case .boolean: + if flag.boolValue { + scope.setTag(value: "true", key: tagKey) + } + case .string: + if let stringValue = flag.stringValue, !stringValue.isEmpty { + scope.setTag(value: stringValue, key: tagKey) + } + case .float: + if let floatValue = flag.floatValue { + scope.setTag(value: String(format: "%.2f", floatValue), key: tagKey) + } + } + } + } + } + + private func cleanTagKey(from rawValue: String) -> String { + return rawValue + .replacingOccurrences(of: "--io.sentry.", with: "") + .replacingOccurrences(of: ".", with: "_") + } } #if !os(macOS) && !os(tvOS) && !os(watchOS) && !os(visionOS) @@ -271,7 +318,7 @@ extension SentrySDKWrapper { } func configureFeedback(config: SentryUserFeedbackConfiguration) { - guard !args.contains("--io.sentry.feedback.all-defaults") else { + guard !args.contains(SentrySDKOverrides.Feedback.allDefaults.rawValue) else { config.configureWidget = { widget in widget.layoutUIOffset = self.layoutOffset } @@ -404,7 +451,7 @@ extension SentrySDKWrapper { /// For testing purposes, we want to be able to change the DSN and store it to disk. In a real app, you shouldn't need this behavior. var dsn: String? { do { - if let dsn = env["--io.sentry.dsn"] { + if let dsn = env[SentrySDKOverrides.Special.dsn.rawValue] { try DSNStorage.shared.saveDSN(dsn: dsn) } return try DSNStorage.shared.getDSN() ?? SentrySDKWrapper.defaultDSN @@ -416,13 +463,14 @@ extension SentrySDKWrapper { /// Whether or not profiling benchmarks are being run; this requires disabling certain other features for proper functionality. var isBenchmarking: Bool { args.contains("--io.sentry.test.benchmarking") } - var isUITest: Bool { env["--io.sentry.sdk-environment"] == "ui-tests" } + var isUITest: Bool { env[SentrySDKOverrides.Other.environment.rawValue] == "ui-tests" } } // MARK: Profiling configuration #if !os(tvOS) && !os(watchOS) && !os(visionOS) extension SentrySDKWrapper { func configureProfiling(_ options: Options) { + #if !SDK_V9 if let sampleRate = SentrySDKOverrides.Profiling.sampleRate.floatValue { options.profilesSampleRate = NSNumber(value: sampleRate) } @@ -432,6 +480,7 @@ extension SentrySDKWrapper { } } options.enableAppLaunchProfiling = !SentrySDKOverrides.Profiling.disableAppStartProfiling.boolValue + #endif // !SDK_V9 if !SentrySDKOverrides.Profiling.disableUIProfiling.boolValue { options.configureProfiling = { diff --git a/Samples/SentrySampleShared/SentrySampleUITestShared.xcconfig b/Samples/SentrySampleShared/SentrySampleUITestShared.xcconfig index 81ad13766fc..8d56b1870ed 100644 --- a/Samples/SentrySampleShared/SentrySampleUITestShared.xcconfig +++ b/Samples/SentrySampleShared/SentrySampleUITestShared.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentrySampleUITestShared INFOPLIST_FILE = SentrySampleUITestShared/Info.plist diff --git a/Samples/SessionReplay-CameraTest/SessionReplay-CameraTest.xcconfig b/Samples/SessionReplay-CameraTest/SessionReplay-CameraTest.xcconfig index 7c01f822cff..93bcd47c722 100644 --- a/Samples/SessionReplay-CameraTest/SessionReplay-CameraTest.xcconfig +++ b/Samples/SessionReplay-CameraTest/SessionReplay-CameraTest.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.sample.SessionReplay-CameraTest INFOPLIST_FILE = Sources/Info.plist diff --git a/Samples/Shared/Config/Architectures.xcconfig b/Samples/Shared/Config/Architectures.xcconfig index 38bc21077fd..4594cc094a7 100644 --- a/Samples/Shared/Config/Architectures.xcconfig +++ b/Samples/Shared/Config/Architectures.xcconfig @@ -1,4 +1,5 @@ ONLY_ACTIVE_ARCH_Debug = YES +ONLY_ACTIVE_ARCH_DebugV9 = YES ONLY_ACTIVE_ARCH_Test = YES ONLY_ACTIVE_ARCH_TestCI = YES ONLY_ACTIVE_ARCH_Release = NO diff --git a/Samples/Shared/Config/BuildOptions.xcconfig b/Samples/Shared/Config/BuildOptions.xcconfig index d5351b51be4..cc17ef5f0f6 100644 --- a/Samples/Shared/Config/BuildOptions.xcconfig +++ b/Samples/Shared/Config/BuildOptions.xcconfig @@ -1,16 +1,19 @@ DEBUG_INFORMATION_FORMAT_Debug = dwarf +DEBUG_INFORMATION_FORMAT_DebugV9 = dwarf DEBUG_INFORMATION_FORMAT_Test = dwarf-with-dsym DEBUG_INFORMATION_FORMAT_TestCI = dwarf-with-dsym DEBUG_INFORMATION_FORMAT_Release = dwarf-with-dsym DEBUG_INFORMATION_FORMAT = $(DEBUG_INFORMATION_FORMAT_$(CONFIGURATION)) ENABLE_TESTABILITY_Debug = YES +ENABLE_TESTABILITY_DebugV9 = YES ENABLE_TESTABILITY_Test = YES ENABLE_TESTABILITY_TestCI = YES ENABLE_TESTABILITY_Release = NO ENABLE_TESTABILITY = $(ENABLE_TESTABILITY_$(CONFIGURATION)) VALIDATE_PRODUCT_Debug = NO +VALIDATE_PRODUCT_DebugV9 = NO VALIDATE_PRODUCT_Test = YES VALIDATE_PRODUCT_TestCI = YES VALIDATE_PRODUCT_Release = YES diff --git a/Samples/Shared/Config/ClangPreprocessing.xcconfig b/Samples/Shared/Config/ClangPreprocessing.xcconfig index f2657bbc871..cec16945e42 100644 --- a/Samples/Shared/Config/ClangPreprocessing.xcconfig +++ b/Samples/Shared/Config/ClangPreprocessing.xcconfig @@ -1,12 +1,14 @@ ENABLE_STRICT_OBJC_MSGSEND = YES ENABLE_NS_ASSERTIONS_Debug = YES +ENABLE_NS_ASSERTIONS_DebugV9 = YES ENABLE_NS_ASSERTIONS_Test = NO ENABLE_NS_ASSERTIONS_TestCI = NO ENABLE_NS_ASSERTIONS_Release = NO ENABLE_NS_ASSERTIONS = $(ENABLE_NS_ASSERTIONS_$(CONFIGURATION)) GCC_PREPROCESSOR_DEFINITIONS_Debug = DEBUG=1 $(inherited) +GCC_PREPROCESSOR_DEFINITIONS_DebugV9 = SDK_V9=1 DEBUG=1 $(inherited) GCC_PREPROCESSOR_DEFINITIONS_Test = SENTRY_TEST=1 $(inherited) GCC_PREPROCESSOR_DEFINITIONS_TestCI = SENTRY_TESTCI=1 $(inherited) GCC_PREPROCESSOR_DEFINITIONS_Release = RELEASE=1 $(inherited) diff --git a/Samples/Shared/Config/CodeGeneration.xcconfig b/Samples/Shared/Config/CodeGeneration.xcconfig index ae321911ec9..61735c9e79e 100644 --- a/Samples/Shared/Config/CodeGeneration.xcconfig +++ b/Samples/Shared/Config/CodeGeneration.xcconfig @@ -2,6 +2,7 @@ GCC_DYNAMIC_NO_PIC = NO GCC_NO_COMMON_BLOCKS = YES GCC_OPTIMIZATION_LEVEL_Debug = 0 +GCC_OPTIMIZATION_LEVEL_DebugV9 = 0 GCC_OPTIMIZATION_LEVEL_Test = 0 GCC_OPTIMIZATION_LEVEL_TestCI = 0 GCC_OPTIMIZATION_LEVEL_Release = s diff --git a/Samples/Shared/Config/Metal.xcconfig b/Samples/Shared/Config/Metal.xcconfig index 60d39505e62..76a1bfb6820 100644 --- a/Samples/Shared/Config/Metal.xcconfig +++ b/Samples/Shared/Config/Metal.xcconfig @@ -1,4 +1,5 @@ MTL_ENABLE_DEBUG_INFO_Debug = INCLUDE_SOURCE +MTL_ENABLE_DEBUG_INFO_DebugV9 = INCLUDE_SOURCE MTL_ENABLE_DEBUG_INFO_Release = NO MTL_ENABLE_DEBUG_INFO_Test = NO MTL_ENABLE_DEBUG_INFO_TestCI = NO diff --git a/Samples/Shared/Config/Signing.xcconfig b/Samples/Shared/Config/Signing.xcconfig index 6e49bd1c92f..5928a2805d0 100644 --- a/Samples/Shared/Config/Signing.xcconfig +++ b/Samples/Shared/Config/Signing.xcconfig @@ -2,10 +2,12 @@ CODE_SIGN_STYLE = Automatic DEVELOPMENT_TEAM = 97JCY7859U CODE_SIGN_IDENTITY_Debug = iPhone Developer +CODE_SIGN_IDENTITY_DebugV9 = iPhone Developer CODE_SIGN_IDENTITY_Test = iPhone Developer CODE_SIGN_IDENTITY_TestCI = iPhone Developer CODE_SIGN_IDENTITY_Release = iPhone Distribution CODE_SIGN_IDENTITY_Debug[sdk=macosx*] = Apple Development +CODE_SIGN_IDENTITY_DebugV9[sdk=macosx*] = Apple Development CODE_SIGN_IDENTITY_Test[sdk=macosx*] = Apple Development CODE_SIGN_IDENTITY_TestCI[sdk=macosx*] = Apple Development CODE_SIGN_IDENTITY_Release[sdk=macosx*] = Apple Distribution diff --git a/Samples/Shared/Config/Swift.xcconfig b/Samples/Shared/Config/Swift.xcconfig index f8d427426da..fb695628f29 100644 --- a/Samples/Shared/Config/Swift.xcconfig +++ b/Samples/Shared/Config/Swift.xcconfig @@ -1,18 +1,21 @@ SWIFT_VERSION = 5.0 SWIFT_ACTIVE_COMPILATION_CONDITIONS_Debug = DEBUG $(inherited) +SWIFT_ACTIVE_COMPILATION_CONDITIONS_DebugV9 = SDK_V9 DEBUG $(inherited) SWIFT_ACTIVE_COMPILATION_CONDITIONS_Test = SENTRY_TEST $(inherited) SWIFT_ACTIVE_COMPILATION_CONDITIONS_TestCI = SENTRY_TESTCI $(inherited) SWIFT_ACTIVE_COMPILATION_CONDITIONS_Release = $(inherited) SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(SWIFT_ACTIVE_COMPILATION_CONDITIONS_$(CONFIGURATION)) SWIFT_COMPILATION_MODE_Debug = singlefile +SWIFT_COMPILATION_MODE_DebugV9 = singlefile SWIFT_COMPILATION_MODE_Test = wholemodule SWIFT_COMPILATION_MODE_TestCI = wholemodule SWIFT_COMPILATION_MODE_Release = wholemodule SWIFT_COMPILATION_MODE = $(SWIFT_COMPILATION_MODE_$(CONFIGURATION)) SWIFT_OPTIMIZATION_LEVEL_Debug = -Onone +SWIFT_OPTIMIZATION_LEVEL_DebugV9 = -Onone SWIFT_OPTIMIZATION_LEVEL_Test = -Onone SWIFT_OPTIMIZATION_LEVEL_TestCI = -Onone SWIFT_OPTIMIZATION_LEVEL_Release = -O diff --git a/Samples/Shared/Config/Versioning.xcconfig b/Samples/Shared/Config/Versioning.xcconfig deleted file mode 100644 index e414e0be6ca..00000000000 --- a/Samples/Shared/Config/Versioning.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -CURRENT_PROJECT_VERSION = 1 -MARKETING_VERSION = 8.53.2 diff --git a/Samples/Shared/Config/_Common.xcconfig b/Samples/Shared/Config/_Common.xcconfig new file mode 100644 index 00000000000..11446f884cd --- /dev/null +++ b/Samples/Shared/Config/_Common.xcconfig @@ -0,0 +1,23 @@ +#include "Architectures.xcconfig" +#include "BuildOptions.xcconfig" +#include "Deployment.xcconfig" +#include "Linking.xcconfig" +#include "Localization.xcconfig" +#include "Packaging.xcconfig" +#include "SearchPaths.xcconfig" +#include "Signing.xcconfig" +#include "CodeGeneration.xcconfig" +#include "ClangLanguage.xcconfig" +#include "ClangCppLanguage.xcconfig" +#include "ClangModules.xcconfig" +#include "ClangObjCLanguage.xcconfig" +#include "ClangPreprocessing.xcconfig" +#include "ClangWarnings.xcconfig" +#include "ClangWarningsCpp.xcconfig" +#include "ClangWarningsObjC.xcconfig" +#include "AssetCatalog.xcconfig" +#include "ClangAnalyzer.xcconfig" +#include "Swift.xcconfig" +#include "Metal.xcconfig" + +#include "../../../Sources/Configuration/Versioning.xcconfig" diff --git a/Samples/Shared/feature-flags.yml b/Samples/Shared/feature-flags.yml index a6721f05de8..6d0c0951bb3 100644 --- a/Samples/Shared/feature-flags.yml +++ b/Samples/Shared/feature-flags.yml @@ -2,21 +2,29 @@ schemeTemplates: SampleAppScheme: run: commandLineArguments: - "--io.sentry.schema-environment-variable-precedence": true - "--io.sentry.disable-everything": false - "--skip-sentry-init": false - "--io.sentry.wipe-data": false - "--io.sentry.disable-debug-mode": false + # special + "--io.sentry.special.schema-environment-variable-precedence": true + "--io.sentry.special.disable-everything": false + "--io.sentry.special.skip-sentry-init": false + "--io.sentry.special.wipe-data": false + "--io.sentry.special.disable-debug-mode": false + + # screenshot + "--io.sentry.screenshot.disable": false + "--io.sentry.screenshot.disable-view-renderer-v2": false + "--io.sentry.screenshot.disable-fast-view-rendering": false + "--io.sentry.screenshot.disable-mask-all-images": false + "--io.sentry.screenshot.disable-mask-all-text": false # session replay - "--disable-session-replay": false - "--io.sentry.session-replay.disableViewRendereV2": false - "--io.sentry.session-replay.enableFastViewRendering": false - "--io.sentry.session-replay.disable-mask-all-text": false + "--io.sentry.session-replay.disable": false + "--io.sentry.session-replay.disable-view-renderer-v2": false + "--io.sentry.session-replay.enable-fast-view-rendering": false "--io.sentry.session-replay.disable-mask-all-images": false + "--io.sentry.session-replay.disable-mask-all-text": false # user feedback - "--io.sentry.ui-test.use-custom-feedback-button": true + "--io.sentry.feedback.use-custom-feedback-button": false "--io.sentry.feedback.dont-use-sentry-user": false "--io.sentry.feedback.require-name": false "--io.sentry.feedback.require-email": false @@ -29,98 +37,109 @@ schemeTemplates: "--io.sentry.feedback.no-shake-gesture": false # profiling - "--io.sentry.disable-ui-profiling": false - "--io.sentry.profile-lifecycle-manual": false - "--io.sentry.slow-load-method": false - "--io.sentry.disable-app-start-profiling": false + "--io.sentry.profiling.disable-ui-profiling": false + "--io.sentry.profiling.profile-lifecycle-manual": false + "--io.sentry.profiling.slow-load-method": false + "--io.sentry.profiling.disable-app-start-profiling": false + "--io.sentry.profiling.continuous-profiler-immediate-stop": false + + # networking + "--io.sentry.networking.disable-breadcrumbs": false + "--io.sentry.networking.disable-tracking": false + "--io.sentry.networking.disable-failed-request-tracking": false # performance - "--disable-app-hang-tracking-v2": false - "--disable-time-to-full-display-tracing": false - "--disable-performance-v2": false - "--disable-attach-view-hierarchy": false - "--disable-attach-screenshot": false - "--disable-file-io-tracing": false - "--disable-automatic-session-tracking": false - "--disable-metrickit-integration": false - "--disable-metrickit-raw-payloads": false - "--disable-watchdog-tracking": false - "--disable-tracing": false - "--disable-crash-handler": false - "--disable-swizzling": false - "--disable-network-breadcrumbs": false - "--disable-core-data-tracing": false - "--disable-network-tracking": false - "--disable-uiviewcontroller-tracing": false - "--disable-automatic-breadcrumbs": false - "--disable-anr-tracking": false - "--disable-auto-performance-tracing": false - "--disable-ui-tracing": false - "--disable-filemanager-swizzling": false + "--io.sentry.performance.disable-app-hang-tracking-v2": false + "--io.sentry.performance.disable-time-to-full-display-tracing": false + "--io.sentry.performance.disable-performance-v2": false + "--io.sentry.other.disable-attach-view-hierarchy": false + "--io.sentry.other.disable-attach-screenshot": false + "--io.sentry.performance.disable-file-io-tracing": false + "--io.sentry.performance.disable-automatic-session-tracking": false + "--io.sentry.other.disable-metrickit-integration": false + "--io.sentry.other.disable-metrickit-raw-payloads": false + "--io.sentry.performance.disable-watchdog-tracking": false + "--io.sentry.tracing.disable-tracing": false + "--io.sentry.other.disable-crash-handler": false + "--io.sentry.other.disable-swizzling": false + "--io.sentry.performance.disable-core-data-tracing": false + "--io.sentry.performance.disable-uiviewcontroller-tracing": false + "--io.sentry.other.disable-automatic-breadcrumbs": false + "--io.sentry.performance.disable-anr-tracking": false + "--io.sentry.performance.disable-auto-performance-tracing": false + "--io.sentry.performance.disable-ui-tracing": false + "--io.sentry.other.disable-filemanager-swizzling": false + + # events + "--io.sentry.events.reject-all": false # other - "--io.sentry.base64-attachment-data": false - "--io.sentry.disable-http-transport": false - "--disable-spotlight": false - "--reject-screenshots-in-before-capture-screenshot": false - "--reject-view-hierarchy-in-before-capture-view-hierarchy": false - "--reject-all-events": false - "--reject-all-spans": false + "--io.sentry.other.base64-attachment-data": false + "--io.sentry.other.disable-http-transport": false + "--io.sentry.other.disable-spotlight": false + "--io.sentry.other.reject-screenshots-in-before-capture-screenshot": false + "--io.sentry.other.reject-view-hierarchy-in-before-capture-view-hierarchy": false + "--io.sentry.other.reject-all-spans": false environmentVariables: - # session replay - - variable: "--io.sentry.sessionReplaySampleRate" - value: - isEnabled: false - - variable: "--io.sentry.sessionReplayOnErrorSampleRate" - value: - isEnabled: false - - variable: "--io.sentry.sessionReplayQuality" + # events + - variable: "--io.sentry.events.sampleRate" value: isEnabled: false - - variable: "--io.sentry.tracesSampleRate" + # session replay + - variable: "--io.sentry.session-replay.on-error-sample-rate" value: isEnabled: false - - variable: "--io.sentry.sessionTrackingIntervalMillis" + - variable: "--io.sentry.session-replay.session-sample-rate" value: isEnabled: false - - variable: "--io.sentry.profilesSampleRate" + - variable: "--io.sentry.session-replay.quality" value: isEnabled: false - - variable: "--io.sentry.tracesSamplerValue" + + # tracing + - variable: "--io.sentry.tracing.tracesSampleRate" value: isEnabled: false - - variable: "--io.sentry.profilesSamplerValue" + - variable: "--io.sentry.tracing.tracesSamplerValue" value: isEnabled: false - - variable: "--io.sentry.sdk-environment" + + # profiling + - variable: "--io.sentry.profiling.profilesSampleRate" value: isEnabled: false - - variable: "--io.sentry.dsn" + - variable: "--io.sentry.profiling.profilesSamplerValue" value: isEnabled: false - - variable: "--io.sentry.user.username" + - variable: "--io.sentry.profiling.profile-session-sample-rate" value: isEnabled: false - - variable: "--io.sentry.user.name" + + # performance + - variable: "--io.sentry.performance.sessionTrackingIntervalMillis" value: isEnabled: false - - variable: "--io.sentry.sdk-environment" + + # scope/user + - variable: "--io.sentry.scope.user.username" value: isEnabled: false - - variable: "--io.sentry.user.email" + - variable: "--io.sentry.scope.user.name" value: isEnabled: false - - variable: "--io.sentry.sessionTrackingIntervalMillis" + - variable: "--io.sentry.scope.user.email" value: isEnabled: false - - variable: "--io.sentry.user.name" + - variable: "--io.sentry.scope.user.id" value: isEnabled: false - - variable: "--io.sentry.user.id" + - variable: "--io.sentry.scope.sdk-environment" value: isEnabled: false - - variable: "--io.sentry.profile-session-sample-rate" + + # other + - variable: "--io.sentry.special.dsn" value: isEnabled: false diff --git a/Samples/iOS-Cocoapods-Swift6/Podfile b/Samples/iOS-Cocoapods-Swift6/Podfile index 7e00d841b7d..50f14a8b942 100644 --- a/Samples/iOS-Cocoapods-Swift6/Podfile +++ b/Samples/iOS-Cocoapods-Swift6/Podfile @@ -1,6 +1,12 @@ platform :ios, '11.0' use_frameworks! +install! 'cocoapods', :deterministic_uuids => false + target 'App' do pod 'Sentry', :path => "../../" end + +target 'TestKeyboardExtension' do + pod 'Sentry', :path => "../../" +end diff --git a/Samples/iOS-Cocoapods-Swift6/TestKeyboardExtension/Info.plist b/Samples/iOS-Cocoapods-Swift6/TestKeyboardExtension/Info.plist new file mode 100644 index 00000000000..41ed4a54e5a --- /dev/null +++ b/Samples/iOS-Cocoapods-Swift6/TestKeyboardExtension/Info.plist @@ -0,0 +1,24 @@ + + + + + NSExtension + + NSExtensionAttributes + + IsASCIICapable + + PrefersRightToLeft + + PrimaryLanguage + en-US + RequestsOpenAccess + + + NSExtensionPointIdentifier + com.apple.keyboard-service + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).KeyboardViewController + + + diff --git a/Samples/iOS-Cocoapods-Swift6/TestKeyboardExtension/KeyboardViewController.swift b/Samples/iOS-Cocoapods-Swift6/TestKeyboardExtension/KeyboardViewController.swift new file mode 100644 index 00000000000..dde8a500406 --- /dev/null +++ b/Samples/iOS-Cocoapods-Swift6/TestKeyboardExtension/KeyboardViewController.swift @@ -0,0 +1,6 @@ +import Sentry +import UIKit + +class KeyboardViewController: UIInputViewController { + +} diff --git a/Samples/iOS-Cocoapods-Swift6/fastlane/Fastfile b/Samples/iOS-Cocoapods-Swift6/fastlane/Fastfile index 87cd0885b47..7438090b4f3 100644 --- a/Samples/iOS-Cocoapods-Swift6/fastlane/Fastfile +++ b/Samples/iOS-Cocoapods-Swift6/fastlane/Fastfile @@ -8,14 +8,16 @@ platform :ios do run_tests( workspace: "iOS-Cocoapods-Swift6.xcworkspace", scheme: "App", - build_for_testing: true + build_for_testing: true, + destination: "platform=iOS Simulator,OS=18.4,name=iPhone 16 Pro" ) run_tests( workspace: "iOS-Cocoapods-Swift6.xcworkspace", scheme: "App", test_without_building: true, result_bundle: true, - result_bundle_path: "fastlane/test_results/results.xcresult" + result_bundle_path: "fastlane/test_results/results.xcresult", + destination: "platform=iOS Simulator,OS=18.4,name=iPhone 16 Pro" ) end end diff --git a/Samples/iOS-Cocoapods-Swift6/iOS-Cocoapods-Swift6.xcodeproj/project.pbxproj b/Samples/iOS-Cocoapods-Swift6/iOS-Cocoapods-Swift6.xcodeproj/project.pbxproj index b89b8f02e19..6ee59d67569 100644 --- a/Samples/iOS-Cocoapods-Swift6/iOS-Cocoapods-Swift6.xcodeproj/project.pbxproj +++ b/Samples/iOS-Cocoapods-Swift6/iOS-Cocoapods-Swift6.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 35A91A8917822D8EDADFB39C /* Pods_TestKeyboardExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7CA106457CC640CDCEDB05E5 /* Pods_TestKeyboardExtension.framework */; }; D4DC1E862D6F0FD400F562AA /* iOS-Cocoapods-Swift6_Base.xctestplan in Resources */ = {isa = PBXBuildFile; fileRef = D4DC1E852D6F0FD400F562AA /* iOS-Cocoapods-Swift6_Base.xctestplan */; }; D4DC1E952D6F0FDE00F562AA /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DC1E8B2D6F0FDE00F562AA /* AppDelegate.swift */; }; D4DC1E962D6F0FDE00F562AA /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DC1E922D6F0FDE00F562AA /* SceneDelegate.swift */; }; @@ -15,6 +16,8 @@ D4DC1E9A2D6F0FDE00F562AA /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D4DC1E8F2D6F0FDE00F562AA /* LaunchScreen.storyboard */; }; D4DC1E9B2D6F0FDE00F562AA /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D4DC1E912D6F0FDE00F562AA /* Main.storyboard */; }; D4DC1EA02D6F0FE600F562AA /* UITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4DC1E9D2D6F0FE600F562AA /* UITestsLaunchTests.swift */; }; + DBACAD1377BADFBE666689BB /* Pods_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE940F582C1CDCD69035F1A /* Pods_App.framework */; }; + FAB9CE512E42386700753B01 /* TestKeyboardExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = FAB9CE4A2E42386700753B01 /* TestKeyboardExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -25,12 +28,37 @@ remoteGlobalIDString = D46156842D63555100D7C33D; remoteInfo = "iOS-Cocoapods-Swift6"; }; + FAB9CE4F2E42386700753B01 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D461567D2D63555100D7C33D /* Project object */; + proxyType = 1; + remoteGlobalIDString = FAB9CE492E42386700753B01; + remoteInfo = TestKeyboardExtension; + }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + FAB9CE522E42386700753B01 /* Embed Foundation Extensions */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 13; + files = ( + FAB9CE512E42386700753B01 /* TestKeyboardExtension.appex in Embed Foundation Extensions */, + ); + name = "Embed Foundation Extensions"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ + 2A52AF4703478424D955547A /* Pods-TestKeyboardExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestKeyboardExtension.release.xcconfig"; path = "Target Support Files/Pods-TestKeyboardExtension/Pods-TestKeyboardExtension.release.xcconfig"; sourceTree = ""; }; + 34602AAC804A33BFC7E28047 /* Pods-App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.release.xcconfig"; path = "Target Support Files/Pods-App/Pods-App.release.xcconfig"; sourceTree = ""; }; + 48B372DF76C04889B67D6FD7 /* Pods-TestKeyboardExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TestKeyboardExtension.debug.xcconfig"; path = "Target Support Files/Pods-TestKeyboardExtension/Pods-TestKeyboardExtension.debug.xcconfig"; sourceTree = ""; }; + 7CA106457CC640CDCEDB05E5 /* Pods_TestKeyboardExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TestKeyboardExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D46156852D63555100D7C33D /* App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = App.app; sourceTree = BUILT_PRODUCTS_DIR; }; D4DC1E7A2D6F0FAD00F562AA /* UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - D4DC1E852D6F0FD400F562AA /* iOS-Cocoapods-Swift6_Base.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; name = "iOS-Cocoapods-Swift6_Base.xctestplan"; path = "../../../Plans/iOS-Cocoapods-Swift6_Base.xctestplan"; sourceTree = ""; }; + D4DC1E852D6F0FD400F562AA /* iOS-Cocoapods-Swift6_Base.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = "iOS-Cocoapods-Swift6_Base.xctestplan"; sourceTree = ""; }; D4DC1E8B2D6F0FDE00F562AA /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; D4DC1E8C2D6F0FDE00F562AA /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; D4DC1E8D2D6F0FDE00F562AA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -39,13 +67,38 @@ D4DC1E922D6F0FDE00F562AA /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; D4DC1E932D6F0FDE00F562AA /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; D4DC1E9D2D6F0FE600F562AA /* UITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITestsLaunchTests.swift; sourceTree = ""; }; + DAE940F582C1CDCD69035F1A /* Pods_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + E2E7A5213988B44BC60AB2CC /* Pods-App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App.debug.xcconfig"; path = "Target Support Files/Pods-App/Pods-App.debug.xcconfig"; sourceTree = ""; }; + FAB9CE4A2E42386700753B01 /* TestKeyboardExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = TestKeyboardExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ +/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ + FAB9CE552E42386700753B01 /* Exceptions for "TestKeyboardExtension" folder in "TestKeyboardExtension" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Info.plist, + ); + target = FAB9CE492E42386700753B01 /* TestKeyboardExtension */; + }; +/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ + +/* Begin PBXFileSystemSynchronizedRootGroup section */ + FAB9CE4B2E42386700753B01 /* TestKeyboardExtension */ = { + isa = PBXFileSystemSynchronizedRootGroup; + exceptions = ( + FAB9CE552E42386700753B01 /* Exceptions for "TestKeyboardExtension" folder in "TestKeyboardExtension" target */, + ); + path = TestKeyboardExtension; + sourceTree = ""; + }; +/* End PBXFileSystemSynchronizedRootGroup section */ + /* Begin PBXFrameworksBuildPhase section */ D46156822D63555100D7C33D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + DBACAD1377BADFBE666689BB /* Pods_App.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -56,12 +109,33 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + FAB9CE472E42386700753B01 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 35A91A8917822D8EDADFB39C /* Pods_TestKeyboardExtension.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 2E02642F16E55901174FEC92 /* Frameworks */ = { + isa = PBXGroup; + children = ( + DAE940F582C1CDCD69035F1A /* Pods_App.framework */, + 7CA106457CC640CDCEDB05E5 /* Pods_TestKeyboardExtension.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; 93ED8309140E9077914DDEAC /* Pods */ = { isa = PBXGroup; children = ( + E2E7A5213988B44BC60AB2CC /* Pods-App.debug.xcconfig */, + 34602AAC804A33BFC7E28047 /* Pods-App.release.xcconfig */, + 48B372DF76C04889B67D6FD7 /* Pods-TestKeyboardExtension.debug.xcconfig */, + 2A52AF4703478424D955547A /* Pods-TestKeyboardExtension.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -72,8 +146,10 @@ D4DC1E942D6F0FDE00F562AA /* Sources */, D4DC1E9E2D6F0FE600F562AA /* UITests */, D4DC1EA12D6F0FEB00F562AA /* Test Plans */, + FAB9CE4B2E42386700753B01 /* TestKeyboardExtension */, D46156862D63555100D7C33D /* Products */, 93ED8309140E9077914DDEAC /* Pods */, + 2E02642F16E55901174FEC92 /* Frameworks */, ); sourceTree = ""; }; @@ -82,45 +158,14 @@ children = ( D46156852D63555100D7C33D /* App.app */, D4DC1E7A2D6F0FAD00F562AA /* UITests.xctest */, + FAB9CE4A2E42386700753B01 /* TestKeyboardExtension.appex */, ); name = Products; sourceTree = ""; }; - D4DC1E872D6F0FDE00F562AA /* Headers */ = { - isa = PBXGroup; - children = ( - ); - path = Headers; - sourceTree = ""; - }; - D4DC1E882D6F0FDE00F562AA /* Local Podspecs */ = { - isa = PBXGroup; - children = ( - ); - path = "Local Podspecs"; - sourceTree = ""; - }; - D4DC1E892D6F0FDE00F562AA /* Target Support Files */ = { - isa = PBXGroup; - children = ( - ); - path = "Target Support Files"; - sourceTree = ""; - }; - D4DC1E8A2D6F0FDE00F562AA /* Pods */ = { - isa = PBXGroup; - children = ( - D4DC1E872D6F0FDE00F562AA /* Headers */, - D4DC1E882D6F0FDE00F562AA /* Local Podspecs */, - D4DC1E892D6F0FDE00F562AA /* Target Support Files */, - ); - path = Pods; - sourceTree = ""; - }; D4DC1E942D6F0FDE00F562AA /* Sources */ = { isa = PBXGroup; children = ( - D4DC1E8A2D6F0FDE00F562AA /* Pods */, D4DC1E8B2D6F0FDE00F562AA /* AppDelegate.swift */, D4DC1E8C2D6F0FDE00F562AA /* Assets.xcassets */, D4DC1E8D2D6F0FDE00F562AA /* Info.plist */, @@ -140,12 +185,13 @@ path = UITests; sourceTree = ""; }; - D4DC1EA12D6F0FEB00F562AA /* Test Plans */ = { + D4DC1EA12D6F0FEB00F562AA /* Plans */ = { isa = PBXGroup; children = ( D4DC1E852D6F0FD400F562AA /* iOS-Cocoapods-Swift6_Base.xctestplan */, ); - path = "Test Plans"; + name = Plans; + path = ../../Plans; sourceTree = ""; }; /* End PBXGroup section */ @@ -155,13 +201,17 @@ isa = PBXNativeTarget; buildConfigurationList = D46156982D63555300D7C33D /* Build configuration list for PBXNativeTarget "App" */; buildPhases = ( + 3C951FA009E8FB6CE0ED2C94 /* [CP] Check Pods Manifest.lock */, D46156812D63555100D7C33D /* Sources */, D46156822D63555100D7C33D /* Frameworks */, D46156832D63555100D7C33D /* Resources */, + FAB9CE522E42386700753B01 /* Embed Foundation Extensions */, + 4754901B3302F22D6954BA9C /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( + FAB9CE502E42386700753B01 /* PBXTargetDependency */, ); name = App; productName = "iOS-Cocoapods"; @@ -186,6 +236,27 @@ productReference = D4DC1E7A2D6F0FAD00F562AA /* UITests.xctest */; productType = "com.apple.product-type.bundle.ui-testing"; }; + FAB9CE492E42386700753B01 /* TestKeyboardExtension */ = { + isa = PBXNativeTarget; + buildConfigurationList = FAB9CE562E42386700753B01 /* Build configuration list for PBXNativeTarget "TestKeyboardExtension" */; + buildPhases = ( + 4E86FC47A5B804B333D366B0 /* [CP] Check Pods Manifest.lock */, + FAB9CE462E42386700753B01 /* Sources */, + FAB9CE472E42386700753B01 /* Frameworks */, + FAB9CE482E42386700753B01 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + fileSystemSynchronizedGroups = ( + FAB9CE4B2E42386700753B01 /* TestKeyboardExtension */, + ); + name = TestKeyboardExtension; + productName = TestKeyboardExtension; + productReference = FAB9CE4A2E42386700753B01 /* TestKeyboardExtension.appex */; + productType = "com.apple.product-type.app-extension"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -193,7 +264,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1620; + LastSwiftUpdateCheck = 1640; LastUpgradeCheck = 1620; TargetAttributes = { D46156842D63555100D7C33D = { @@ -203,6 +274,9 @@ CreatedOnToolsVersion = 16.2; TestTargetID = D46156842D63555100D7C33D; }; + FAB9CE492E42386700753B01 = { + CreatedOnToolsVersion = 16.4; + }; }; }; buildConfigurationList = D46156802D63555100D7C33D /* Build configuration list for PBXProject "iOS-Cocoapods-Swift6" */; @@ -221,6 +295,7 @@ targets = ( D46156842D63555100D7C33D /* App */, D4DC1E792D6F0FAD00F562AA /* UITests */, + FAB9CE492E42386700753B01 /* TestKeyboardExtension */, ); }; /* End PBXProject section */ @@ -244,8 +319,79 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + FAB9CE482E42386700753B01 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 3C951FA009E8FB6CE0ED2C94 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-App-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 4754901B3302F22D6954BA9C /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-App/Pods-App-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-App/Pods-App-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-App/Pods-App-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 4E86FC47A5B804B333D366B0 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-TestKeyboardExtension-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ D46156812D63555100D7C33D /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -265,6 +411,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + FAB9CE462E42386700753B01 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ @@ -273,6 +426,11 @@ target = D46156842D63555100D7C33D /* App */; targetProxy = D4DC1E802D6F0FAD00F562AA /* PBXContainerItemProxy */; }; + FAB9CE502E42386700753B01 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = FAB9CE492E42386700753B01 /* TestKeyboardExtension */; + targetProxy = FAB9CE4F2E42386700753B01 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -297,6 +455,7 @@ /* Begin XCBuildConfiguration section */ D46156992D63555300D7C33D /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = E2E7A5213988B44BC60AB2CC /* Pods-App.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -325,6 +484,7 @@ }; D461569A2D63555300D7C33D /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 34602AAC804A33BFC7E28047 /* Pods-App.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; @@ -504,6 +664,58 @@ }; name = Release; }; + FAB9CE532E42386700753B01 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 48B372DF76C04889B67D6FD7 /* Pods-TestKeyboardExtension.debug.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = TestKeyboardExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = TestKeyboardExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 18.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.getsentry.iOS-Cocoapods.TestKeyboardExtension"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + FAB9CE542E42386700753B01 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 2A52AF4703478424D955547A /* Pods-TestKeyboardExtension.release.xcconfig */; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = TestKeyboardExtension/Info.plist; + INFOPLIST_KEY_CFBundleDisplayName = TestKeyboardExtension; + INFOPLIST_KEY_NSHumanReadableCopyright = ""; + IPHONEOS_DEPLOYMENT_TARGET = 18.4; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@executable_path/../../Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "com.getsentry.iOS-Cocoapods.TestKeyboardExtension"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -534,6 +746,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + FAB9CE562E42386700753B01 /* Build configuration list for PBXNativeTarget "TestKeyboardExtension" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FAB9CE532E42386700753B01 /* Debug */, + FAB9CE542E42386700753B01 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = D461567D2D63555100D7C33D /* Project object */; diff --git a/Samples/iOS-ObjectiveC/iOS-ObjectiveC-UITests.xcconfig b/Samples/iOS-ObjectiveC/iOS-ObjectiveC-UITests.xcconfig index 519f272c590..0a68949b025 100644 --- a/Samples/iOS-ObjectiveC/iOS-ObjectiveC-UITests.xcconfig +++ b/Samples/iOS-ObjectiveC/iOS-ObjectiveC-UITests.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.iOS-ObjectiveC-UITests diff --git a/Samples/iOS-ObjectiveC/iOS-ObjectiveC.xcconfig b/Samples/iOS-ObjectiveC/iOS-ObjectiveC.xcconfig index 46cab762452..98086d5db87 100644 --- a/Samples/iOS-ObjectiveC/iOS-ObjectiveC.xcconfig +++ b/Samples/iOS-ObjectiveC/iOS-ObjectiveC.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.iOS-ObjectiveC INFOPLIST_FILE = iOS-ObjectiveC/Info.plist diff --git a/Samples/iOS-ObjectiveC/iOS-ObjectiveC.yml b/Samples/iOS-ObjectiveC/iOS-ObjectiveC.yml index 0c398a74283..e24248b77ea 100644 --- a/Samples/iOS-ObjectiveC/iOS-ObjectiveC.yml +++ b/Samples/iOS-ObjectiveC/iOS-ObjectiveC.yml @@ -5,6 +5,7 @@ createIntermediateGroups: true generateEmptyDirectories: true configs: Debug: debug + DebugV9: debug Test: debug TestCI: debug Release: release @@ -37,6 +38,7 @@ targets: - target: SentrySampleShared/SentrySampleShared configFiles: Debug: iOS-ObjectiveC.xcconfig + DebugV9: iOS-ObjectiveC.xcconfig Release: iOS-ObjectiveC.xcconfig Test: iOS-ObjectiveC.xcconfig TestCI: iOS-ObjectiveC.xcconfig diff --git a/Samples/iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m b/Samples/iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m index e0967bd74aa..f035a516811 100644 --- a/Samples/iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m +++ b/Samples/iOS-ObjectiveC/iOS-ObjectiveC/AppDelegate.m @@ -36,35 +36,48 @@ - (BOOL)application:(UIApplication *)application options.tracesSampleRate = @([env[@"--io.sentry.tracesSampleRate"] doubleValue]); } - if (![args containsObject:@"--io.sentry.disable-ui-profiling"]) { + if (![args containsObject:@"--io.sentry.profiling.disable-ui-profiling"]) { options.configureProfiling = ^(SentryProfileOptions *_Nonnull profiling) { - profiling.lifecycle = [args containsObject:@"--io.sentry.profile-lifecycle-manual"] + profiling.lifecycle = + [args containsObject:@"--io.sentry.profiling.profile-lifecycle-manual"] ? SentryProfileLifecycleManual : SentryProfileLifecycleTrace; profiling.sessionSampleRate = 1.f; - if (env[@"--io.sentry.profile-session-sample-rate"] != nil) { + if (env[@"--io.sentry.profiling.profile-session-sample-rate"] != nil) { profiling.sessionSampleRate = - [env[@"--io.sentry.profile-session-sample-rate"] floatValue]; + [env[@"--io.sentry.profiling.profile-session-sample-rate"] floatValue]; } }; } - if (env[@"--io.sentry.profilesSampleRate"] != nil) { - options.profilesSampleRate = @([env[@"--io.sentry.profilesSampleRate"] floatValue]); +#if !SDK_V9 + if (env[@"--io.sentry.profiling.profilesSampleRate"] != nil) { +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" + options.profilesSampleRate = + @([env[@"--io.sentry.profiling.profilesSampleRate"] floatValue]); +# pragma clang diagnostic pop } if (env[@"--io.sentry.profilesSamplerValue"] != nil) { +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" options.profilesSampler = ^NSNumber *_Nullable(SentrySamplingContext *_Nonnull samplingContext) { return @([env[@"--io.sentry.profilesSamplerValue"] floatValue]); }; +# pragma clang diagnostic pop } - if (![args containsObject:@"--io.sentry.disable-app-start-profiling"]) { + if (![args containsObject:@"--io.sentry.profiling.disable-app-start-profiling"]) { +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" options.enableAppLaunchProfiling = YES; +# pragma clang diagnostic pop } +#endif // !SDK_V9 SentryHttpStatusCodeRange *httpStatusCodeRange = [[SentryHttpStatusCodeRange alloc] initWithMin:400 max:599]; diff --git a/Samples/iOS-ObjectiveC/iOS-ObjectiveC/ViewController.m b/Samples/iOS-ObjectiveC/iOS-ObjectiveC/ViewController.m index 5af8997106d..c1c9058c7d6 100644 --- a/Samples/iOS-ObjectiveC/iOS-ObjectiveC/ViewController.m +++ b/Samples/iOS-ObjectiveC/iOS-ObjectiveC/ViewController.m @@ -72,11 +72,21 @@ - (IBAction)captureUserFeedback:(id)sender captureError:error withScopeBlock:^(SentryScope *_Nonnull scope) { [scope setLevel:kSentryLevelFatal]; }]; +#if SDK_V9 + NSLog(@"SDK V9 does not support user feedback."); +#else +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" SentryUserFeedback *userFeedback = [[SentryUserFeedback alloc] initWithEventId:eventId]; +# pragma clang diagnostic pop userFeedback.comments = @"It broke on iOS-ObjectiveC. I don't know why, but this happens."; userFeedback.email = @"john@me.com"; userFeedback.name = @"John Me"; +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" [SentrySDK captureUserFeedback:userFeedback]; +# pragma clang diagnostic pop +#endif // SDK_V9 } - (IBAction)captureUserFeedbackV2:(id)sender diff --git a/Samples/iOS-Swift/iOS-Benchmarking.xcconfig b/Samples/iOS-Swift/iOS-Benchmarking.xcconfig index 2d668da69a2..bb032efaa35 100644 --- a/Samples/iOS-Swift/iOS-Benchmarking.xcconfig +++ b/Samples/iOS-Swift/iOS-Benchmarking.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.iOS-Benchmarking INFOPLIST_FILE = iOS-Benchmarking/Info.plist diff --git a/Samples/iOS-Swift/iOS-Benchmarking/SentrySDKPerformanceBenchmarkTests.m b/Samples/iOS-Swift/iOS-Benchmarking/SentrySDKPerformanceBenchmarkTests.m index 1ccdd6fc02a..b81cb65fc39 100644 --- a/Samples/iOS-Swift/iOS-Benchmarking/SentrySDKPerformanceBenchmarkTests.m +++ b/Samples/iOS-Swift/iOS-Benchmarking/SentrySDKPerformanceBenchmarkTests.m @@ -24,12 +24,12 @@ - (void)testProfilerCPUUsage XCUIApplication *app = [[XCUIApplication alloc] init]; app.launchArguments = [app.launchArguments arrayByAddingObjectsFromArray:@[ - @"--io.sentry.test.benchmarking", @"--io.sentry.disable-app-start-profiling" + @"--io.sentry.test.benchmarking", @"--io.sentry.profiling.disable-app-start-profiling" ]]; NSMutableDictionary *mutableEnvironment = app.launchEnvironment.mutableCopy; - mutableEnvironment[@"--io.sentry.profilesSampleRate"] = @"1"; + mutableEnvironment[@"--io.sentry.profiling.profilesSampleRate"] = @"1"; app.launchEnvironment = mutableEnvironment; [app launch]; diff --git a/Samples/iOS-Swift/iOS-Swift-ShareExtension.xcconfig b/Samples/iOS-Swift/iOS-Swift-ShareExtension.xcconfig new file mode 100644 index 00000000000..7e99e1147b0 --- /dev/null +++ b/Samples/iOS-Swift/iOS-Swift-ShareExtension.xcconfig @@ -0,0 +1,16 @@ +#include "../Shared/Config/_Common.xcconfig" + +PRODUCT_BUNDLE_IDENTIFIER = io.sentry.sample.iOS-Swift.ShareExtension +INFOPLIST_FILE = iOS-Swift-ShareExtension/Info.plist + +PROVISIONING_PROFILE_SPECIFIER_Debug = match Development io.sentry.sample.iOS-Swift.ShareExtension +PROVISIONING_PROFILE_SPECIFIER_DebugV9 = match Development io.sentry.sample.iOS-Swift.ShareExtension +PROVISIONING_PROFILE_SPECIFIER_Test = match Development io.sentry.sample.iOS-Swift.ShareExtension +PROVISIONING_PROFILE_SPECIFIER_TestCI = match Development io.sentry.sample.iOS-Swift.ShareExtension +PROVISIONING_PROFILE_SPECIFIER_Release = match AppStore io.sentry.sample.iOS-Swift.ShareExtension +PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*] = $(PROVISIONING_PROFILE_SPECIFIER_$(CONFIGURATION)) +PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*] = + +CODE_SIGN_STYLE = Manual + +SUPPORTED_PLATFORMS = iphoneos iphonesimulator diff --git a/Samples/iOS-Swift/iOS-Swift-ShareExtension/Base.lproj/MainInterface.storyboard b/Samples/iOS-Swift/iOS-Swift-ShareExtension/Base.lproj/MainInterface.storyboard new file mode 100644 index 00000000000..286a50894d8 --- /dev/null +++ b/Samples/iOS-Swift/iOS-Swift-ShareExtension/Base.lproj/MainInterface.storyboard @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Samples/iOS-Swift/iOS-Swift-ShareExtension/Info.plist b/Samples/iOS-Swift/iOS-Swift-ShareExtension/Info.plist new file mode 100644 index 00000000000..2bb96edc1c6 --- /dev/null +++ b/Samples/iOS-Swift/iOS-Swift-ShareExtension/Info.plist @@ -0,0 +1,51 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + $(PRODUCT_NAME) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + GIT_BRANCH + <branch> + GIT_COMMIT_HASH + <sha> + GIT_STATUS_CLEAN + <status> + NSExtension + + NSExtensionAttributes + + NSExtensionActivationRule + + NSExtensionActivationSupportsText + + NSExtensionActivationSupportsWebURLWithMaxCount + 1 + NSExtensionActivationSupportsImageWithMaxCount + 1 + NSExtensionActivationSupportsFileWithMaxCount + 1 + + + NSExtensionMainStoryboard + MainInterface + NSExtensionPointIdentifier + com.apple.share-services + + + diff --git a/Samples/iOS-Swift/iOS-Swift-ShareExtension/ShareViewController.swift b/Samples/iOS-Swift/iOS-Swift-ShareExtension/ShareViewController.swift new file mode 100644 index 00000000000..cd3dd15885a --- /dev/null +++ b/Samples/iOS-Swift/iOS-Swift-ShareExtension/ShareViewController.swift @@ -0,0 +1,35 @@ +import Sentry +import SentrySampleShared +import Social +import UIKit + +class ShareViewController: SLComposeServiceViewController { + + required init?(coder: NSCoder) { + super.init(coder: coder) + setupSentry() + } + + override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { + super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) + setupSentry() + } + + private func setupSentry() { + SentrySDKWrapper.shared.startSentry() + } + + override func isContentValid() -> Bool { + return true + } + + override func didSelectPost() { + SentrySDK.capture(message: "iOS-Swift-ShareExtension: didSelectPost called") + + self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil) + } + + override func configurationItems() -> [Any]! { + return [] + } +} diff --git a/Samples/iOS-Swift/iOS-Swift-UITests.xcconfig b/Samples/iOS-Swift/iOS-Swift-UITests.xcconfig index a9f6f257acb..808d0d6170a 100644 --- a/Samples/iOS-Swift/iOS-Swift-UITests.xcconfig +++ b/Samples/iOS-Swift/iOS-Swift-UITests.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.iOS-Swift-UITests diff --git a/Samples/iOS-Swift/iOS-Swift-UITests/BaseUITest.swift b/Samples/iOS-Swift/iOS-Swift-UITests/BaseUITest.swift index 457fe33ba8c..86ba8338ded 100644 --- a/Samples/iOS-Swift/iOS-Swift-UITests/BaseUITest.swift +++ b/Samples/iOS-Swift/iOS-Swift-UITests/BaseUITest.swift @@ -1,9 +1,10 @@ +import SentrySampleShared import SentrySampleUITestShared import XCTest class BaseUITest: XCTestCase { internal lazy var app: XCUIApplication = newAppSession() - + //swiftlint:disable implicit_getter var automaticallyLaunchAndTerminateApp: Bool { get { true } } //swiftlint:enable implicit_getter @@ -12,15 +13,15 @@ class BaseUITest: XCTestCase { super.setUp() continueAfterFailure = false XCUIDevice.shared.orientation = .portrait - app.launchEnvironment["--io.sentry.sdk-environment"] = "ui-tests" + app.launchEnvironment["--io.sentry.scope.sdk-environment"] = "ui-tests" app.launchArguments.append(contentsOf: [ - "--io.sentry.wipe-data" + SentrySDKOverrides.Special.wipeDataOnLaunch.rawValue ]) if automaticallyLaunchAndTerminateApp { launchApp() } } - + override func tearDown() { if automaticallyLaunchAndTerminateApp { app.terminate() @@ -33,7 +34,7 @@ extension BaseUITest { func newAppSession() -> XCUIApplication { let app = XCUIApplication() app.launchEnvironment["--io.sentry.ui-test.test-name"] = name - app.launchArguments.append("--disable-spotlight") + app.launchArguments.append(SentrySDKOverrides.Other.disableSpotlight.rawValue) return app } @@ -67,5 +68,4 @@ extension BaseUITest { func waitForExistenceOfMainScreen() { app.waitForExistence("Home Screen doesn't exist.") } - } diff --git a/Samples/iOS-Swift/iOS-Swift-UITests/ProfilingUITests.swift b/Samples/iOS-Swift/iOS-Swift-UITests/ProfilingUITests.swift index 8d5dd68f9f3..ceb500324e8 100644 --- a/Samples/iOS-Swift/iOS-Swift-UITests/ProfilingUITests.swift +++ b/Samples/iOS-Swift/iOS-Swift-UITests/ProfilingUITests.swift @@ -1,4 +1,5 @@ @testable import Sentry +import SentrySampleShared import XCTest //swiftlint:disable function_body_length todo @@ -44,14 +45,14 @@ class ProfilingUITests: BaseUITest { func testProfilingGPUInfo() throws { if #available(iOS 16, *) { app.launchArguments.append(contentsOf: [ - "--io.sentry.wipe-data", + SentrySDKOverrides.Special.wipeDataOnLaunch.rawValue, // we're only interested in the manual transaction, the automatic stuff messes up how we try to retrieve the target profile info - "--disable-swizzling", + SentrySDKOverrides.Other.disableSwizzling.rawValue, - "--io.sentry.disable-app-start-profiling" + SentrySDKOverrides.Profiling.disableAppStartProfiling.rawValue ]) - app.launchEnvironment["--io.sentry.profilesSampleRate"] = "1.0" + app.launchEnvironment[SentrySDKOverrides.Profiling.sampleRate.rawValue] = "1.0" launchApp() goToTransactions() @@ -144,36 +145,38 @@ extension ProfilingUITests { fileprivate func setAppLaunchParameters(_ profileType: ProfilingUITests.ProfilingType, _ lifecycle: SentryProfileOptions.SentryProfileLifecycle?, _ shouldProfileNextLaunch: Bool) { app.launchArguments.append(contentsOf: [ // these help avoid other profiles that'd be taken automatically, that interfere with the checking we do for the assertions later in the tests - "--disable-swizzling", - "--disable-auto-performance-tracing", - "--disable-uiviewcontroller-tracing", - + SentrySDKOverrides.Other.disableSwizzling.rawValue, + SentrySDKOverrides.Performance.disablePerformanceTracing.rawValue, + SentrySDKOverrides.Performance.disableUIVCTracing.rawValue, + SentrySDKOverrides.Performance.disableTimeToFullDisplayTracing.rawValue, + // sets a marker function to run in a load command that the launch profile should detect - "--io.sentry.slow-load-method", + SentrySDKOverrides.Profiling.slowLoadMethod.rawValue, // override full chunk completion before stoppage introduced in https://github.com/getsentry/sentry-cocoa/pull/4214 - "--io.sentry.continuous-profiler-immediate-stop" + SentrySDKOverrides.Profiling.immediateStop.rawValue ]) switch profileType { case .ui: - app.launchEnvironment["--io.sentry.profile-session-sample-rate"] = "1" + app.launchEnvironment[SentrySDKOverrides.Profiling.sessionSampleRate.rawValue] = "1" switch lifecycle { case .none: fatalError("Misconfigured test case. Must provide a lifecycle for UI profiling.") case .trace: break case .manual: - app.launchArguments.append("--io.sentry.profile-lifecycle-manual") + app.launchArguments.append(SentrySDKOverrides.Profiling.manualLifecycle.rawValue) } case .continuous: - app.launchArguments.append("--io.sentry.disable-ui-profiling") + app.launchArguments.append(SentrySDKOverrides.Profiling.disableUIProfiling.rawValue) case .trace: - app.launchEnvironment["--io.sentry.profilesSampleRate"] = "1" + app.launchArguments.append(SentrySDKOverrides.Profiling.disableUIProfiling.rawValue) + app.launchEnvironment[SentrySDKOverrides.Profiling.sampleRate.rawValue] = "1" } if !shouldProfileNextLaunch { - app.launchArguments.append("--io.sentry.disable-app-start-profiling") + app.launchArguments.append(SentrySDKOverrides.Profiling.disableAppStartProfiling.rawValue) } } diff --git a/Samples/iOS-Swift/iOS-Swift-UITests/SessionReplayUITests.swift b/Samples/iOS-Swift/iOS-Swift-UITests/SessionReplayUITests.swift new file mode 100644 index 00000000000..d23c5aef642 --- /dev/null +++ b/Samples/iOS-Swift/iOS-Swift-UITests/SessionReplayUITests.swift @@ -0,0 +1,33 @@ +import XCTest + +class SessionReplayUITests: BaseUITest { + + func testCameraUI_shouldNotCrashOnIOS26() throws { + guard UIImagePickerController.isSourceTypeAvailable(.camera) else { + throw XCTSkip("Camera UI is not available on this device.") + } + // -- Arrange -- + // During the beta phase of iOS 26.0 we noticed crashes when traversing the view hierarchy + // of the camera UI. This test is used to verify that no regression occurs. + // See https://github.com/getsentry/sentry-cocoa/issues/5647 + app.buttons["Extra"].tap() + + // -- Act -- + app.buttons["Show Camera UI"].tap() + + // We need to verify the camera UI is shown by checking for the existence of a UI element. + // This can be any element that is part of the camera UI and can be found reliably. + // The "PhotoCapture" button is a good candidate as it is always present when the + // camera UI is shown. + let cameraUIElement = app.buttons["PhotoCapture"] + XCTAssertTrue(cameraUIElement.waitForExistence(timeout: 5)) + + // After the Camera UI is shown, we keep it open for 10 seconds to trigger at least one full + // video segment captured (segments are 5 seconds long). + delay(seconds: 10) + + // -- Assert -- + // We know the test succeeded if we reach this point without the app crashing. + XCTAssertTrue(cameraUIElement.waitForExistence(timeout: 5)) + } +} diff --git a/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift b/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift index e99fd11959c..38cad195d56 100644 --- a/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift +++ b/Samples/iOS-Swift/iOS-Swift-UITests/UserFeedbackUITests.swift @@ -1,5 +1,6 @@ //swiftlint:disable file_length +import SentrySampleShared import XCTest class UserFeedbackUITests: BaseUITest { @@ -15,14 +16,14 @@ class UserFeedbackUITests: BaseUITest { super.setUp() app.launchArguments.append(contentsOf: [ - "--io.sentry.feedback.no-animations", - "--io.sentry.wipe-data", + SentrySDKOverrides.Feedback.noAnimations.rawValue, + SentrySDKOverrides.Special.wipeDataOnLaunch.rawValue, // since the goal of these tests is only to exercise the UI of the widget and form, disable other SDK features to avoid any confounding factors that might fail or crash a test case - "--io.sentry.disable-everything", + SentrySDKOverrides.Special.disableEverything.rawValue, // write base64-encoded data into the envelope file for attachments instead of raw bytes, specifically for images. this way the entire envelope contents can be more easily passed as a string through the text field in the app to this process for validation. - "--io.sentry.base64-attachment-data" + SentrySDKOverrides.Other.base64AttachmentData.rawValue ]) continueAfterFailure = true } @@ -32,7 +33,7 @@ extension UserFeedbackUITests { // MARK: Tests ensuring correct appearance func testUIElementsWithDefaults() { - launchApp(args: ["--io.sentry.feedback.all-defaults"]) + launchApp(args: [SentrySDKOverrides.Feedback.allDefaults.rawValue]) // widget button text XCTAssert(app.otherElements["Report a Bug"].exists) @@ -88,10 +89,10 @@ extension UserFeedbackUITests { func testPrefilledUserInformation() throws { launchApp(args: [ - "--io.sentry.feedback.all-defaults" + SentrySDKOverrides.Feedback.allDefaults.rawValue ], env: [ - "--io.sentry.user.name": "ui test user", - "--io.sentry.user.email": "ui-testing@sentry.io" + SentrySDKOverrides.Other.userFullName.rawValue: "ui test user", + SentrySDKOverrides.Other.userEmail.rawValue: "ui-testing@sentry.io" ]) widgetButton.tap() @@ -101,10 +102,10 @@ extension UserFeedbackUITests { func testNoPrefilledUserInformation() throws { launchApp(args: [ - "--io.sentry.feedback.dont-use-sentry-user" + SentrySDKOverrides.Feedback.noUserInjection.rawValue ], env: [ - "--io.sentry.user.name": "ui test user", - "--io.sentry.user.email": "ui-testing@sentry.io" + SentrySDKOverrides.Other.userFullName.rawValue: "ui test user", + SentrySDKOverrides.Other.userEmail.rawValue: "ui-testing@sentry.io" ]) widgetButton.tap() @@ -117,7 +118,9 @@ extension UserFeedbackUITests { // MARK: Tests validating happy path / successful submission func testSubmitFullyFilledCustomForm() throws { - launchApp(args: ["--io.sentry.feedback.dont-use-sentry-user"]) + launchApp(args: [ + SentrySDKOverrides.Feedback.noUserInjection.rawValue + ]) try retrieveAppUnderTestApplicationSupportDirectory() try assertHookMarkersNotExist() @@ -155,9 +158,9 @@ extension UserFeedbackUITests { let testName = "Andrew" let testContactEmail = "andrew.mcknight@sentry.io" - launchApp(args: ["--io.sentry.feedback.all-defaults"], env: [ - "--io.sentry.user.name": testName, - "--io.sentry.user.email": testContactEmail + launchApp(args: [SentrySDKOverrides.Feedback.allDefaults.rawValue], env: [ + SentrySDKOverrides.Other.userFullName.rawValue: testName, + SentrySDKOverrides.Other.userEmail.rawValue: testContactEmail ]) try retrieveAppUnderTestApplicationSupportDirectory() @@ -202,8 +205,8 @@ extension UserFeedbackUITests { func testSubmitCustomButton() throws { launchApp(args: [ - "--io.sentry.feedback.use-custom-feedback-button", - "--io.sentry.feedback.dont-use-sentry-user" + SentrySDKOverrides.Feedback.useCustomFeedbackButton.rawValue, + SentrySDKOverrides.Feedback.noUserInjection.rawValue ]) try retrieveAppUnderTestApplicationSupportDirectory() @@ -243,9 +246,9 @@ extension UserFeedbackUITests { let testName = "Andrew" let testContactEmail = "andrew.mcknight@sentry.io" - launchApp(args: ["--io.sentry.feedback.all-defaults"], env: [ - "--io.sentry.user.name": testName, - "--io.sentry.user.email": testContactEmail + launchApp(args: [SentrySDKOverrides.Feedback.allDefaults.rawValue], env: [ + SentrySDKOverrides.Other.userFullName.rawValue: testName, + SentrySDKOverrides.Other.userEmail.rawValue: testContactEmail ]) try retrieveAppUnderTestApplicationSupportDirectory() @@ -272,9 +275,9 @@ extension UserFeedbackUITests { let testName = "Andrew" let testContactEmail = "andrew.mcknight@sentry.io" - launchApp(args: ["--io.sentry.feedback.all-defaults"], env: [ - "--io.sentry.user.name": testName, - "--io.sentry.user.email": testContactEmail + launchApp(args: [SentrySDKOverrides.Feedback.allDefaults.rawValue], env: [ + SentrySDKOverrides.Other.userFullName.rawValue: testName, + SentrySDKOverrides.Other.userEmail.rawValue: testContactEmail ]) try retrieveAppUnderTestApplicationSupportDirectory() @@ -309,9 +312,9 @@ extension UserFeedbackUITests { let testName = "Andrew" let testContactEmail = "andrew.mcknight@sentry.io" - launchApp(args: ["--io.sentry.feedback.all-defaults"], env: [ - "--io.sentry.user.name": testName, - "--io.sentry.user.email": testContactEmail + launchApp(args: [SentrySDKOverrides.Feedback.allDefaults.rawValue], env: [ + SentrySDKOverrides.Other.userFullName.rawValue: testName, + SentrySDKOverrides.Other.userEmail.rawValue: testContactEmail ]) try retrieveAppUnderTestApplicationSupportDirectory() @@ -341,7 +344,9 @@ extension UserFeedbackUITests { // MARK: Tests validating screenshot functionality func testAddingScreenshots() throws { - launchApp(args: ["--io.sentry.feedback.inject-screenshot"]) + launchApp(args: [ + SentrySDKOverrides.Feedback.injectScreenshot.rawValue + ]) XCTAssert(removeScreenshotButton.isHittable) let testMessage = "UITest user feedback" @@ -353,7 +358,9 @@ extension UserFeedbackUITests { } func testAddingAndRemovingScreenshots() throws { - launchApp(args: ["--io.sentry.feedback.inject-screenshot"]) + launchApp(args: [ + SentrySDKOverrides.Feedback.injectScreenshot.rawValue + ]) XCTAssert(removeScreenshotButton.isHittable) removeScreenshotButton.tap() XCTAssertFalse(removeScreenshotButton.isHittable) @@ -369,7 +376,7 @@ extension UserFeedbackUITests { // MARK: Tests validating error cases func testSubmitWithNoFieldsFilledDefault() throws { - launchApp(args: ["--io.sentry.feedback.all-defaults"]) + launchApp(args: [SentrySDKOverrides.Feedback.allDefaults.rawValue]) try retrieveAppUnderTestApplicationSupportDirectory() try assertHookMarkersNotExist() @@ -389,7 +396,10 @@ extension UserFeedbackUITests { } func testSubmitWithNoFieldsFilledEmailAndMessageRequired() throws { - launchApp(args: ["--io.sentry.feedback.require-email", "--io.sentry.feedback.dont-use-sentry-user"]) + launchApp(args: [ + SentrySDKOverrides.Feedback.requireEmail.rawValue, + SentrySDKOverrides.Feedback.noUserInjection.rawValue + ]) try retrieveAppUnderTestApplicationSupportDirectory() try assertHookMarkersNotExist() @@ -414,9 +424,9 @@ extension UserFeedbackUITests { func testSubmitWithNoFieldsFilledAllRequired() throws { launchApp(args: [ - "--io.sentry.feedback.require-email", - "--io.sentry.feedback.require-name", - "--io.sentry.feedback.dont-use-sentry-user" + SentrySDKOverrides.Feedback.requireEmail.rawValue, + SentrySDKOverrides.Feedback.requireName.rawValue, + SentrySDKOverrides.Feedback.noUserInjection.rawValue ]) try retrieveAppUnderTestApplicationSupportDirectory() @@ -440,7 +450,7 @@ extension UserFeedbackUITests { } func testSubmitOnlyWithOptionalFieldsFilled() throws { - launchApp(args: ["--io.sentry.feedback.all-defaults"]) + launchApp(args: [SentrySDKOverrides.Feedback.allDefaults.rawValue]) try retrieveAppUnderTestApplicationSupportDirectory() try assertHookMarkersNotExist() @@ -462,9 +472,9 @@ extension UserFeedbackUITests { let testName = "Andrew" let testContactEmail = "andrew.mcknight@sentry.io" - launchApp(args: ["--io.sentry.feedback.all-defaults"], env: [ - "--io.sentry.user.name": testName, - "--io.sentry.user.email": testContactEmail + launchApp(args: [SentrySDKOverrides.Feedback.allDefaults.rawValue], env: [ + SentrySDKOverrides.Other.userFullName.rawValue: testName, + SentrySDKOverrides.Other.userEmail.rawValue: testContactEmail ]) try retrieveAppUnderTestApplicationSupportDirectory() @@ -492,7 +502,9 @@ extension UserFeedbackUITests { // MARK: Alternative widget control func testFormShowsAndDismissesProperlyWithCustomButton() { - launchApp(args: ["--io.sentry.feedback.use-custom-feedback-button"]) + launchApp(args: [ + SentrySDKOverrides.Feedback.useCustomFeedbackButton.rawValue + ]) customButton.tap() cancelButton.tap() @@ -502,7 +514,9 @@ extension UserFeedbackUITests { } func testNoAutomaticallyInjectedWidgetWithCustomButton() { - launchApp(args: ["--io.sentry.feedback.use-custom-feedback-button"]) + launchApp(args: [ + SentrySDKOverrides.Feedback.useCustomFeedbackButton.rawValue + ]) XCTAssertFalse(widgetButton.isHittable) XCTAssert(customButton.isHittable) @@ -516,7 +530,9 @@ extension UserFeedbackUITests { } func testManuallyDisplayingWidget() { - launchApp(args: ["--io.sentry.feedback.no-auto-inject-widget"]) + launchApp(args: [ + SentrySDKOverrides.Feedback.disableAutoInject.rawValue + ]) XCTAssertFalse(widgetButton.isHittable) extrasAreaTabBarButton.tap() app.buttons["io.sentry.ui-test.button.show-widget"].tap() diff --git a/Samples/iOS-Swift/iOS-Swift-UITests/ViewLifecycleUITests.swift b/Samples/iOS-Swift/iOS-Swift-UITests/ViewLifecycleUITests.swift index c3ad471ebf1..a6946e77148 100644 --- a/Samples/iOS-Swift/iOS-Swift-UITests/ViewLifecycleUITests.swift +++ b/Samples/iOS-Swift/iOS-Swift-UITests/ViewLifecycleUITests.swift @@ -1,3 +1,4 @@ +import SentrySampleShared import XCTest // This is an UI test for a scenario that was previously crashing the SDK (see https://github.com/getsentry/sentry-cocoa/issues/5087 for details). @@ -9,9 +10,9 @@ class ViewLifecycleUITests: BaseUITest { override func setUp() { super.setUp() launchApp(args: [ - "--disable-time-to-full-display-tracing", - "--disable-performance-v2", - "--disable-app-hang-tracking-v2" + SentrySDKOverrides.Performance.disableTimeToFullDisplayTracing.rawValue, + SentrySDKOverrides.Performance.disablePerformanceV2.rawValue, + SentrySDKOverrides.Performance.disableAppHangTrackingV2.rawValue ]) } diff --git a/Samples/iOS-Swift/iOS-Swift-UITests/XCTest+Delay.swift b/Samples/iOS-Swift/iOS-Swift-UITests/XCTest+Delay.swift new file mode 100644 index 00000000000..0286eca63dd --- /dev/null +++ b/Samples/iOS-Swift/iOS-Swift-UITests/XCTest+Delay.swift @@ -0,0 +1,11 @@ +import XCTest + +public extension XCTestCase { + func delay(seconds: TimeInterval) { + let exp = expectation(description: "Waiting for \(seconds) seconds") + DispatchQueue.main.asyncAfter(deadline: .now() + seconds) { + exp.fulfill() + } + wait(for: [exp], timeout: seconds + 1) + } +} diff --git a/Samples/iOS-Swift/iOS-Swift.xcconfig b/Samples/iOS-Swift/iOS-Swift.xcconfig index 5b5a7bac2f8..a09ba3428d0 100644 --- a/Samples/iOS-Swift/iOS-Swift.xcconfig +++ b/Samples/iOS-Swift/iOS-Swift.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.sample.iOS-Swift INFOPLIST_FILE = iOS-Swift/Info.plist diff --git a/Samples/iOS-Swift/iOS-Swift.yml b/Samples/iOS-Swift/iOS-Swift.yml index 0f7eac2c869..1da8d04075f 100644 --- a/Samples/iOS-Swift/iOS-Swift.yml +++ b/Samples/iOS-Swift/iOS-Swift.yml @@ -5,6 +5,7 @@ createIntermediateGroups: true generateEmptyDirectories: true configs: Debug: debug + DebugV9: debug Test: debug TestCI: debug Release: release @@ -31,8 +32,10 @@ targets: - target: Sentry/Sentry - target: iOS-SwiftClip - target: SentrySampleShared/SentrySampleShared + - target: iOS-Swift-ShareExtension configFiles: Debug: iOS-Swift.xcconfig + DebugV9: iOS-Swift.xcconfig Release: iOS-Swift.xcconfig Test: iOS-Swift.xcconfig TestCI: iOS-Swift.xcconfig @@ -55,6 +58,7 @@ targets: - target: SentrySampleShared/SentrySampleShared configFiles: Debug: iOS-SwiftClip.xcconfig + DebugV9: iOS-SwiftClip.xcconfig Release: iOS-SwiftClip.xcconfig Test: iOS-SwiftClip.xcconfig TestCI: iOS-SwiftClip.xcconfig @@ -73,8 +77,10 @@ targets: - iOS-Swift-UITests dependencies: - target: SentrySampleShared/SentrySampleUITestShared + - target: SentrySampleShared/SentrySampleShared configFiles: Debug: iOS-Swift-UITests.xcconfig + DebugV9: iOS-Swift-UITests.xcconfig Release: iOS-Swift-UITests.xcconfig Test: iOS-Swift-UITests.xcconfig TestCI: iOS-Swift-UITests.xcconfig @@ -88,9 +94,24 @@ targets: - target: SentrySampleShared/SentrySampleUITestShared configFiles: Debug: iOS-Benchmarking.xcconfig + DebugV9: iOS-Benchmarking.xcconfig Release: iOS-Benchmarking.xcconfig Test: iOS-Benchmarking.xcconfig TestCI: iOS-Benchmarking.xcconfig + iOS-Swift-ShareExtension: + type: app-extension + platform: auto + sources: + - iOS-Swift-ShareExtension + dependencies: + - target: Sentry/Sentry + - target: SentrySampleShared/SentrySampleShared + configFiles: + Debug: iOS-Swift-ShareExtension.xcconfig + DebugV9: iOS-Swift-ShareExtension.xcconfig + Release: iOS-Swift-ShareExtension.xcconfig + Test: iOS-Swift-ShareExtension.xcconfig + TestCI: iOS-Swift-ShareExtension.xcconfig schemes: iOS-Swift: templates: diff --git a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift index 349b4d4eef5..e377481492c 100644 --- a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift +++ b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift @@ -18,7 +18,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { print("[iOS-Swift] [debug] launch arguments: \(args)") print("[iOS-Swift] [debug] launch environment: \(env)") - if args.contains("--io.sentry.wipe-data") { + if args.contains(SentrySDKOverrides.Special.wipeDataOnLaunch.rawValue) { removeAppData() } diff --git a/Samples/iOS-Swift/iOS-Swift/Base.lproj/Main.storyboard b/Samples/iOS-Swift/iOS-Swift/Base.lproj/Main.storyboard index 544ec78d77b..2d6df1ada95 100644 --- a/Samples/iOS-Swift/iOS-Swift/Base.lproj/Main.storyboard +++ b/Samples/iOS-Swift/iOS-Swift/Base.lproj/Main.storyboard @@ -2,7 +2,6 @@ - @@ -198,17 +197,17 @@ - + - + + + - + + + + + + + + + - + diff --git a/Samples/iOS-Swift/iOS-Swift/ExtraViewController.swift b/Samples/iOS-Swift/iOS-Swift/ExtraViewController.swift index 7584b659bb0..0cb01f49329 100644 --- a/Samples/iOS-Swift/iOS-Swift/ExtraViewController.swift +++ b/Samples/iOS-Swift/iOS-Swift/ExtraViewController.swift @@ -18,6 +18,7 @@ class ExtraViewController: UIViewController { @IBOutlet weak var dataMarshalingErrorLabel: UILabel! private let dispatchQueue = DispatchQueue(label: "ExtraViewControllers", attributes: .concurrent) + private var batteryConsumer: BatteryConsumer? override func viewDidLoad() { super.viewDidLoad() @@ -51,6 +52,27 @@ class ExtraViewController: UIViewController { SentrySDK.reportFullyDisplayed() } + + @IBAction func highEnergyCPU(_ sender: UIButton) { + highlightButton(sender) + if #available(iOS 15.0, *) { + batteryConsumer = BatteryConsumer(qos: .userInitiated) + batteryConsumer?.start() + } + } + + @IBAction func lowEnergyCPU(_ sender: UIButton) { + highlightButton(sender) + if #available(iOS 15.0, *) { + batteryConsumer = BatteryConsumer(qos: .background) + batteryConsumer?.start() + } + } + + @IBAction func stopUsingEnergy(_ sender: UIButton) { + highlightButton(sender) + batteryConsumer?.stop() + } @IBAction func anrDeadlock(_ sender: UIButton) { highlightButton(sender) @@ -185,11 +207,15 @@ class ExtraViewController: UIViewController { scope.setLevel(.fatal) } + #if SDK_V9 + print("SDK V9 does not support user feedback.") + #else let userFeedback = UserFeedback(eventId: eventId) userFeedback.comments = "It broke on iOS-Swift. I don't know why, but this happens." userFeedback.email = "john@me.com" userFeedback.name = "John Me" SentrySDK.capture(userFeedback: userFeedback) + #endif // SDK_V9 } @IBAction func permissions(_ sender: UIButton) { @@ -386,6 +412,21 @@ class ExtraViewController: UIViewController { showToast(in: self, type: .warning, message: "Feedback widget only available in iOS 13 or later.") } } + + @IBAction func showCameraUIAction(_ sender: Any) { + // We need to check if the camera is available, otherwise simulators running on a Mac Mini (device without any + // built-in camera) would crash with this error: + // + // *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Source type 1 not available' + guard UIImagePickerController.isSourceTypeAvailable(.camera) else { + preconditionFailure("Can not display the camera UI because the source type is not available.") + } + let imagePicker = UIImagePickerController() + imagePicker.sourceType = .camera + imagePicker.allowsEditing = false + imagePicker.cameraCaptureMode = .photo + self.present(imagePicker, animated: true, completion: nil) + } } @available(iOS 13.0, *) diff --git a/Samples/iOS-Swift/iOS-Swift/Info.plist b/Samples/iOS-Swift/iOS-Swift/Info.plist index 5330d565b45..438de9757e8 100644 --- a/Samples/iOS-Swift/iOS-Swift/Info.plist +++ b/Samples/iOS-Swift/iOS-Swift/Info.plist @@ -28,6 +28,8 @@ LSRequiresIPhoneOS + NSCameraUsageDescription + Testing camera permissions NSFaceIDUsageDescription $(PRODUCT_NAME) Authentication with TouchId or FaceID for testing purposes of the Sentry Cocoa SDK. NSLocationAlwaysAndWhenInUseUsageDescription diff --git a/Samples/iOS-Swift/iOS-Swift/Profiling/NSObject+SentryAppSetup.m b/Samples/iOS-Swift/iOS-Swift/Profiling/NSObject+SentryAppSetup.m index e4ffb419d9e..8edb0413d0c 100644 --- a/Samples/iOS-Swift/iOS-Swift/Profiling/NSObject+SentryAppSetup.m +++ b/Samples/iOS-Swift/iOS-Swift/Profiling/NSObject+SentryAppSetup.m @@ -4,7 +4,8 @@ @implementation NSObject (SentryAppSetup) + (void)load { NSLog(@"[iOS-Swift] Starting app launch work"); - if ([NSProcessInfo.processInfo.arguments containsObject:@"--io.sentry.slow-load-method"]) { + if ([NSProcessInfo.processInfo.arguments + containsObject:@"--io.sentry.profiling.slow-load-method"]) { [self sentry_slowLoadWork]; } NSLog(@"[iOS-Swift] Finishing app launch work"); diff --git a/Samples/iOS-Swift/iOS-Swift/Profiling/ProfilingViewController.swift b/Samples/iOS-Swift/iOS-Swift/Profiling/ProfilingViewController.swift index 188dedfb80b..42605e27076 100644 --- a/Samples/iOS-Swift/iOS-Swift/Profiling/ProfilingViewController.swift +++ b/Samples/iOS-Swift/iOS-Swift/Profiling/ProfilingViewController.swift @@ -59,8 +59,10 @@ class ProfilingViewController: UIViewController, UITextFieldDelegate { } @IBAction func sampleRateEdited(_ sender: UITextField) { + #if !SDK_V9 var sampleRate = SentrySDKOverrides.Profiling.sampleRate sampleRate.floatValue = getSampleRateOverride(field: sender) + #endif // !SDK_V9 } @IBAction func tracesSampleRateEdited(_ sender: UITextField) { @@ -76,8 +78,10 @@ class ProfilingViewController: UIViewController, UITextFieldDelegate { @IBAction func defineProfilesSampleRateToggled(_ sender: UISwitch) { sampleRateField.isEnabled = sender.isOn + #if !SDK_V9 var sampleRate = SentrySDKOverrides.Profiling.sampleRate sampleRate.floatValue = getSampleRateOverride(field: sampleRateField) + #endif // !SDK_V9 } @IBAction func defineTracesSampleRateToggled(_ sender: UISwitch) { @@ -163,8 +167,9 @@ private extension ProfilingViewController { } func optionsConfiguration() { - guard let options = SentrySDK.currentHub().getClient()?.options else { return } + guard let options = SentrySDKInternal.currentHub().getClient()?.options else { return } + #if !SDK_V9 if let sampleRate = options.profilesSampleRate { sampleRateField.text = String(format: "%.2f", sampleRate.floatValue) sampleRateField.isEnabled = true @@ -174,6 +179,7 @@ private extension ProfilingViewController { sampleRateField.text = "nil" profilesSampleRateSwitch.isOn = false } + #endif // !SDK_V9 if let sampleRate = options.tracesSampleRate { tracesSampleRateField.text = String(format: "%.2f", sampleRate.floatValue) @@ -191,7 +197,11 @@ private extension ProfilingViewController { profileAppStartsSwitch.isOn = v2Options.profileAppStarts } else { traceLifecycleSwitch.isOn = false + #if SDK_V9 + profileAppStartsSwitch.isOn = false + #else profileAppStartsSwitch.isOn = options.enableAppLaunchProfiling + #endif // !SDK_V9 } } diff --git a/Samples/iOS-Swift/iOS-Swift/ProjectProposal.pdf b/Samples/iOS-Swift/iOS-Swift/ProjectProposal.pdf new file mode 100644 index 00000000000..f865bd15afc Binary files /dev/null and b/Samples/iOS-Swift/iOS-Swift/ProjectProposal.pdf differ diff --git a/Samples/iOS-Swift/iOS-Swift/Sample.mp4 b/Samples/iOS-Swift/iOS-Swift/Sample.mp4 new file mode 100644 index 00000000000..56525e6b300 Binary files /dev/null and b/Samples/iOS-Swift/iOS-Swift/Sample.mp4 differ diff --git a/Samples/iOS-Swift/iOS-Swift/Tools/EnergyConsumer.swift b/Samples/iOS-Swift/iOS-Swift/Tools/EnergyConsumer.swift new file mode 100644 index 00000000000..02421bd0ff4 --- /dev/null +++ b/Samples/iOS-Swift/iOS-Swift/Tools/EnergyConsumer.swift @@ -0,0 +1,58 @@ +import simd +final class BatteryConsumer { + + init(qos: DispatchQoS) { + queue = DispatchQueue( + label: "com.sentry.sample.BatteryConsumer", + qos: qos, + attributes: .concurrent) + } + + private let queue: DispatchQueue + private var workItem: DispatchWorkItem? + private let lock = NSLock() + private var running = false + + @available(iOS 15.0, *) + func start() { + lock.lock() + defer { lock.unlock() } + guard !running else { return } + running = true + + let item = DispatchWorkItem { [weak self] in + + var accumulator = simd_double4(0, 0, 0, 0) + + while self?.isRunning ?? false { + // Do a batch of meaningless but FP-heavy math. + for i in 1...16_384 { + let v = simd_double4(Double(i), Double(i) + 1, + Double(i) + 2, Double(i) + 3) + accumulator += sin(v) * cos(v) + } + + // Touch memory so the optimizer can’t remove the loop. + // This makes the loop both CPU- and memory-intensive. + if accumulator.x.isInfinite { print(accumulator) } + } + } + + workItem = item + queue.async(execute: item) + } + + func stop() { + lock.lock() + running = false + lock.unlock() + workItem?.cancel() + workItem = nil + } + + private var isRunning: Bool { + lock.lock() + defer { lock.unlock() } + return running + } +} diff --git a/Samples/iOS-Swift/iOS-Swift/Tools/SentryExposure.h b/Samples/iOS-Swift/iOS-Swift/Tools/SentryExposure.h index ee873d0f89b..c0b2bd45a9b 100644 --- a/Samples/iOS-Swift/iOS-Swift/Tools/SentryExposure.h +++ b/Samples/iOS-Swift/iOS-Swift/Tools/SentryExposure.h @@ -1,9 +1,32 @@ #import +#import #import +@class SentryHub; + +NS_ASSUME_NONNULL_BEGIN + @interface SentryBreadcrumbTracker : NSObject -+ (NSDictionary *)extractDataFromView:(UIView *)view - withAccessibilityIdentifier:(BOOL)includeIdentifier; ++ (nullable NSDictionary *)extractDataFromView:(UIView *)view + withAccessibilityIdentifier:(BOOL)includeIdentifier; + +@end + +@interface SentrySDKInternal : NSObject + ++ (nullable NSArray *)relevantViewControllersNames; + ++ (SentryHub *)currentHub; + +@end + +#if SDK_V9 +@interface SentryScope () + +- (NSDictionary *)serialize; @end +#endif + +NS_ASSUME_NONNULL_END diff --git a/Samples/iOS-Swift/iOS-Swift/Tools/TopViewControllerInspector.swift b/Samples/iOS-Swift/iOS-Swift/Tools/TopViewControllerInspector.swift index 1c7267729fc..0711b28a973 100644 --- a/Samples/iOS-Swift/iOS-Swift/Tools/TopViewControllerInspector.swift +++ b/Samples/iOS-Swift/iOS-Swift/Tools/TopViewControllerInspector.swift @@ -51,7 +51,7 @@ class TopViewControllerInspector: UIView { @objc private func getTopVC() { - let names = SentrySDK.relevantViewControllersNames() + let names = SentrySDKInternal.relevantViewControllersNames() lbl.text = names?.joined(separator: ", ") } @@ -62,7 +62,7 @@ class TopViewControllerInspector: UIView { override func layoutSubviews() { let screenBounds = UIScreen.main.bounds - btn.frame = CGRect(x: screenBounds.width - 160, y: screenBounds.height - 160, width: 140, height: 44) + btn.frame = CGRect(x: screenBounds.width - 160, y: screenBounds.height - 200, width: 140, height: 44) lbl.frame = CGRect(x: 20, y: btn.frame.origin.y, width: screenBounds.width - 200, height: 44) } diff --git a/Samples/iOS-Swift/iOS-Swift/Tools/iOS-Swift-Bridging-Header.h b/Samples/iOS-Swift/iOS-Swift/Tools/iOS-Swift-Bridging-Header.h index 17416e71c00..fd526d911f6 100644 --- a/Samples/iOS-Swift/iOS-Swift/Tools/iOS-Swift-Bridging-Header.h +++ b/Samples/iOS-Swift/iOS-Swift/Tools/iOS-Swift-Bridging-Header.h @@ -3,4 +3,3 @@ #import "SentryExposure.h" #import #import -#import diff --git a/Samples/iOS-Swift/iOS-Swift/ViewControllers/CoreDataViewController.swift b/Samples/iOS-Swift/iOS-Swift/ViewControllers/CoreDataViewController.swift index 033bafddd2e..3733a5cc1ec 100644 --- a/Samples/iOS-Swift/iOS-Swift/ViewControllers/CoreDataViewController.swift +++ b/Samples/iOS-Swift/iOS-Swift/ViewControllers/CoreDataViewController.swift @@ -59,7 +59,7 @@ class CoreDataViewController: UITableViewController { return obj } - func saveContext () { + func saveContext() { // iOS 9.0 and below - however you were previously handling it if managedObjectContext.hasChanges { do { diff --git a/Samples/iOS-Swift/iOS-Swift/ViewControllers/SentryPDFViewController.swift b/Samples/iOS-Swift/iOS-Swift/ViewControllers/SentryPDFViewController.swift new file mode 100644 index 00000000000..b1c697568d4 --- /dev/null +++ b/Samples/iOS-Swift/iOS-Swift/ViewControllers/SentryPDFViewController.swift @@ -0,0 +1,24 @@ +import PDFKit + +class SentryPDFViewController: UIViewController { + override func viewDidLoad() { + super.viewDidLoad() + + let pdfView = PDFView() + view.addSubview(pdfView) + + pdfView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + pdfView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + pdfView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), + pdfView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), + pdfView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) + ]) + + guard let fileUrl = Bundle.main.url(forResource: "ProjectProposal", withExtension: "pdf"), + let document = PDFDocument(url: fileUrl) else { + preconditionFailure("Failed to load PDF document from bundle.") + } + pdfView.document = document + } +} diff --git a/Samples/iOS-Swift/iOS-Swift/ViewControllers/SentryVideoViewController.swift b/Samples/iOS-Swift/iOS-Swift/ViewControllers/SentryVideoViewController.swift new file mode 100644 index 00000000000..f42321a7d91 --- /dev/null +++ b/Samples/iOS-Swift/iOS-Swift/ViewControllers/SentryVideoViewController.swift @@ -0,0 +1,63 @@ +import AVKit +import UIKit + +/// Video view controller for displaying video using the ``AVKit`` framework. +/// +/// See the expo-video video view for reference: +/// https://github.com/expo/expo/blob/sdk-53/packages/expo-video/ios/VideoView.swift +class SentryVideoViewController: UIViewController { + lazy var playerViewController = AVPlayerViewController() + + weak var player: AVPlayer? { + didSet { + playerViewController.player = player + } + } + + override func viewDidLoad() { + super.viewDidLoad() + + setupPlayerUI() + setupPlayer() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + // Start playing the video when the view appears. + player?.play() + } + + func setupPlayerUI() { + // Use a distinct color to clearly indicate when the video content not being displayed. + playerViewController.view.backgroundColor = .systemOrange + + // Disable updates to the Now Playing Info Center, to increase isolation of app to global system state. + playerViewController.updatesNowPlayingInfoCenter = false + + // Reference for the correct life cycle calls: + // https://developer.apple.com/documentation/uikit/creating-a-custom-container-view-controller#Add-a-child-view-controller-programmatically-to-your-content + addChild(playerViewController) + view.addSubview(playerViewController.view) + + playerViewController.view.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + playerViewController.view.topAnchor.constraint(greaterThanOrEqualTo: view.safeAreaLayoutGuide.topAnchor), + playerViewController.view.centerYAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor), + + playerViewController.view.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), + playerViewController.view.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) + ]) + + playerViewController.didMove(toParent: self) + } + + func setupPlayer() { + guard let videoUrl = Bundle.main.url(forResource: "Sample", withExtension: "mp4") else { + preconditionFailure("Sample video not found in main bundle") + } + let player = AVPlayer(url: videoUrl) + player.isMuted = true + self.player = player + } +} diff --git a/Samples/iOS-Swift/iOS-SwiftClip.xcconfig b/Samples/iOS-Swift/iOS-SwiftClip.xcconfig index 774b7e95b53..37b9d85976b 100644 --- a/Samples/iOS-Swift/iOS-SwiftClip.xcconfig +++ b/Samples/iOS-Swift/iOS-SwiftClip.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.sample.iOS-Swift.Clip INFOPLIST_FILE = iOS-SwiftClip/Info.plist diff --git a/Samples/iOS-Swift6/iOS-Swift6-UITests.xcconfig b/Samples/iOS-Swift6/iOS-Swift6-UITests.xcconfig index f8ccfbc5983..3399f6d4112 100644 --- a/Samples/iOS-Swift6/iOS-Swift6-UITests.xcconfig +++ b/Samples/iOS-Swift6/iOS-Swift6-UITests.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.sample.iOS-Swift6-UITests diff --git a/Samples/iOS-Swift6/iOS-Swift6.xcconfig b/Samples/iOS-Swift6/iOS-Swift6.xcconfig index 43f7421043c..82e75936575 100644 --- a/Samples/iOS-Swift6/iOS-Swift6.xcconfig +++ b/Samples/iOS-Swift6/iOS-Swift6.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.sample.iOS-Swift6 INFOPLIST_FILE = iOS-Swift6/Info.plist diff --git a/Samples/iOS-SwiftUI/iOS-SwiftUI-UITests.xcconfig b/Samples/iOS-SwiftUI/iOS-SwiftUI-UITests.xcconfig index f264e53fb73..944465534eb 100644 --- a/Samples/iOS-SwiftUI/iOS-SwiftUI-UITests.xcconfig +++ b/Samples/iOS-SwiftUI/iOS-SwiftUI-UITests.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.iOS-Swift-UITests SUPPORTED_PLATFORMS = iphoneos iphonesimulator diff --git a/Samples/iOS-SwiftUI/iOS-SwiftUI-UITests/FeedbackUITests.swift b/Samples/iOS-SwiftUI/iOS-SwiftUI-UITests/FeedbackUITests.swift index b16c47db0bd..495d4df62ef 100644 --- a/Samples/iOS-SwiftUI/iOS-SwiftUI-UITests/FeedbackUITests.swift +++ b/Samples/iOS-SwiftUI/iOS-SwiftUI-UITests/FeedbackUITests.swift @@ -1,10 +1,12 @@ +import SentrySampleShared import XCTest final class FeedbackUITests: XCTestCase { func testWidgetDisplayInSwiftUIApp() throws { let app = XCUIApplication() app.launchArguments.append(contentsOf: [ - "--io.sentry.feedback.all-defaults" + SentrySDKOverrides.Feedback.allDefaults.rawValue, + SentrySDKOverrides.Profiling.disableAppStartProfiling.rawValue ]) app.launch() diff --git a/Samples/iOS-SwiftUI/iOS-SwiftUI-UITests/LaunchUITests.swift b/Samples/iOS-SwiftUI/iOS-SwiftUI-UITests/LaunchUITests.swift index 19bc2af73e0..af23971f58b 100644 --- a/Samples/iOS-SwiftUI/iOS-SwiftUI-UITests/LaunchUITests.swift +++ b/Samples/iOS-SwiftUI/iOS-SwiftUI-UITests/LaunchUITests.swift @@ -1,3 +1,4 @@ +import SentrySampleShared import SentrySampleUITestShared import XCTest @@ -11,16 +12,16 @@ class LaunchUITests: XCTestCase { func testTransactionSpan() { let app = newAppSession() app.safelyLaunch() - + let transactionName = app.staticTexts["TRANSACTION_NAME"] let transactionId = app.staticTexts["TRANSACTION_ID"] - if !transactionName.waitForExistence(timeout: 1) { + if !transactionName.waitForExistence(timeout: 5) { XCTFail("Span operation label not found") } - + let childParentId = app.staticTexts["CHILD_PARENT_SPANID"] let childName = app.staticTexts["CHILD_NAME"] - + XCTAssertEqual(childName.label, "Child Span") XCTAssertEqual(transactionName.label, "Content View Body") XCTAssertEqual(childParentId.label, transactionId.label) @@ -39,34 +40,44 @@ class LaunchUITests: XCTestCase { formScreenNavigationBar/*@START_MENU_TOKEN@*/.buttons["Test"]/*[[".otherElements[\"Test\"].buttons[\"Test\"]",".buttons[\"Test\"]"],[[[-1,1],[-1,0]]],[0]]@END_MENU_TOKEN@*/.tap() XCTAssertEqual(app.staticTexts["SPAN_ID"].label, "NO SPAN") } - + func testTTID_TTFD() { let app = newAppSession() app.safelyLaunch() app.buttons["Show TTD"].tap() - + XCTAssertEqual(app.staticTexts["TTDInfo"].label, "TTID and TTFD found") } - - func newAppSession() -> XCUIApplication { - let app = XCUIApplication() - app.launchEnvironment["--io.sentry.ui-test.test-name"] = name - app.launchArguments.append("--disable-spotlight") - return app - } + + func newAppSession() -> XCUIApplication { + let app = XCUIApplication() + app.launchEnvironment["--io.sentry.ui-test.test-name"] = name + app.launchArguments.append(contentsOf: [ + SentrySDKOverrides.Other.disableSpotlight.rawValue, + SentrySDKOverrides.Special.wipeDataOnLaunch.rawValue + ]) + return app + } } extension XCUIApplication { - public func safelyLaunch() { - // Calling activate() and then launch() effectively launches the app twice, interfering with - // local debugging. Only call activate if there isn't a debugger attached, which is a decent - // proxy for whether this is running in CI. - if !isDebugging() { - // App prewarming can sometimes cause simulators to get stuck in UI tests, activating them - // before launching clears any prewarming state. - activate() + public func safelyLaunch() { + // Calling activate() and then launch() effectively launches the app twice, interfering with + // local debugging. Only call activate if there isn't a debugger attached, which is a decent + // proxy for whether this is running in CI. + if !isDebugging() { + // activate() appears to drop launch args and environment variables, so save them beforehand and reset them before subsequent calls to launch() + let launchArguments = self.launchArguments + let launchEnvironment = self.launchEnvironment + + // App prewarming can sometimes cause simulators to get stuck in UI tests, activating them + // before launching clears any prewarming state. + activate() + + self.launchArguments = launchArguments + self.launchEnvironment = launchEnvironment + } + + launch() } - - launch() - } } diff --git a/Samples/iOS-SwiftUI/iOS-SwiftUI.xcconfig b/Samples/iOS-SwiftUI/iOS-SwiftUI.xcconfig index 52c34bdabfa..6ffb7fd7289 100644 --- a/Samples/iOS-SwiftUI/iOS-SwiftUI.xcconfig +++ b/Samples/iOS-SwiftUI/iOS-SwiftUI.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.iOS-SwiftUI INFOPLIST_FILE = iOS-SwiftUI/Info.plist diff --git a/Samples/iOS-SwiftUI/iOS-SwiftUI.yml b/Samples/iOS-SwiftUI/iOS-SwiftUI.yml index c6b9d74e77d..cc986e2d42d 100644 --- a/Samples/iOS-SwiftUI/iOS-SwiftUI.yml +++ b/Samples/iOS-SwiftUI/iOS-SwiftUI.yml @@ -5,6 +5,7 @@ createIntermediateGroups: true generateEmptyDirectories: true configs: Debug: debug + DebugV9: debug Test: debug TestCI: debug Release: release @@ -26,6 +27,7 @@ targets: sources: - iOS-SwiftUI - ../Shared/SampleAssets.xcassets + - ../../Sources/Sentry/Public/SentrySerializable.h - ../../Sources/Sentry/include/SentryTracer.h - ../../Sources/Sentry/include/SentryPerformanceTracker.h - ../../Sources/Sentry/Public/SentryProfilingConditionals.h @@ -35,6 +37,7 @@ targets: - target: SentrySampleShared/SentrySampleShared configFiles: Debug: iOS-SwiftUI.xcconfig + DebugV9: iOS-SwiftUI.xcconfig Release: iOS-SwiftUI.xcconfig Test: iOS-SwiftUI.xcconfig TestCI: iOS-SwiftUI.xcconfig @@ -51,6 +54,7 @@ targets: platform: auto dependencies: - target: SentrySampleShared/SentrySampleUITestShared + - target: SentrySampleShared/SentrySampleShared sources: - iOS-SwiftUI-UITests configFiles: diff --git a/Samples/iOS-SwiftUI/iOS-SwiftUI/ContentView.swift b/Samples/iOS-SwiftUI/iOS-SwiftUI/ContentView.swift index 9a50ff1ea3b..3fe0e9feae6 100644 --- a/Samples/iOS-SwiftUI/iOS-SwiftUI/ContentView.swift +++ b/Samples/iOS-SwiftUI/iOS-SwiftUI/ContentView.swift @@ -35,11 +35,15 @@ struct ContentView: View { scope.setLevel(.fatal) } +#if SDK_V9 + print("SDK V9 does not support user feedback.") +#else let userFeedback = UserFeedback(eventId: eventId) userFeedback.comments = "It broke on tvOS-Swift. I don't know why, but this happens." userFeedback.email = "john@me.com" userFeedback.name = "John Me" SentrySDK.capture(userFeedback: userFeedback) + #endif // SDK_V9 } var captureErrorAction: () -> Void = { diff --git a/Samples/iOS-SwiftUI/iOS-SwiftUI/SwiftUIApp.swift b/Samples/iOS-SwiftUI/iOS-SwiftUI/SwiftUIApp.swift index 7bbb4b9bc7c..87435d6e183 100644 --- a/Samples/iOS-SwiftUI/iOS-SwiftUI/SwiftUIApp.swift +++ b/Samples/iOS-SwiftUI/iOS-SwiftUI/SwiftUIApp.swift @@ -34,6 +34,10 @@ class MySceneDelegate: NSObject, UIWindowSceneDelegate, ObservableObject { var initializedSentry = false func sceneDidBecomeActive(_ scene: UIScene) { guard !initializedSentry else { return } + guard UIApplication.shared.connectedScenes.first as? UIWindowScene != nil else { + preconditionFailure("The test app should always have a UIWindowScene at this point") + } + SampleAppDebugMenu.shared.display() SentrySDK.feedback.showWidget() initializedSentry = true diff --git a/Samples/iOS13-Swift-UITests.xcconfig b/Samples/iOS13-Swift-UITests.xcconfig deleted file mode 100644 index 47f6200ac6a..00000000000 --- a/Samples/iOS13-Swift-UITests.xcconfig +++ /dev/null @@ -1,28 +0,0 @@ -#include "Shared/Config/Architectures.xcconfig" -#include "Shared/Config/BuildOptions.xcconfig" -#include "Shared/Config/Deployment.xcconfig" -#include "Shared/Config/Linking.xcconfig" -#include "Shared/Config/Localization.xcconfig" -#include "Shared/Config/Packaging.xcconfig" -#include "Shared/Config/SearchPaths.xcconfig" -#include "Shared/Config/Signing.xcconfig" -#include "Shared/Config/Versioning.xcconfig" -#include "Shared/Config/CodeGeneration.xcconfig" -#include "Shared/Config/ClangLanguage.xcconfig" -#include "Shared/Config/ClangCppLanguage.xcconfig" -#include "Shared/Config/ClangModules.xcconfig" -#include "Shared/Config/ClangObjCLanguage.xcconfig" -#include "Shared/Config/ClangPreprocessing.xcconfig" -#include "Shared/Config/ClangWarnings.xcconfig" -#include "Shared/Config/ClangWarningsCpp.xcconfig" -#include "Shared/Config/ClangWarningsObjC.xcconfig" -#include "Shared/Config/AssetCatalog.xcconfig" -#include "Shared/Config/ClangAnalyzer.xcconfig" -#include "Shared/Config/Swift.xcconfig" -#include "Shared/Config/Metal.xcconfig" - -PRODUCT_BUNDLE_IDENTIFIER = io.sentry.sample.iOS13-Swift-UITests - -SUPPORTED_PLATFORMS = iphoneos iphonesimulator - -TEST_TARGET_NAME = iOS13-Swift diff --git a/Samples/iOS13-Swift.xcconfig b/Samples/iOS13-Swift.xcconfig deleted file mode 100644 index eb2c28e31f3..00000000000 --- a/Samples/iOS13-Swift.xcconfig +++ /dev/null @@ -1,26 +0,0 @@ -#include "Shared/Config/Architectures.xcconfig" -#include "Shared/Config/BuildOptions.xcconfig" -#include "Shared/Config/Deployment.xcconfig" -#include "Shared/Config/Linking.xcconfig" -#include "Shared/Config/Localization.xcconfig" -#include "Shared/Config/Packaging.xcconfig" -#include "Shared/Config/SearchPaths.xcconfig" -#include "Shared/Config/Signing.xcconfig" -#include "Shared/Config/Versioning.xcconfig" -#include "Shared/Config/CodeGeneration.xcconfig" -#include "Shared/Config/ClangLanguage.xcconfig" -#include "Shared/Config/ClangCppLanguage.xcconfig" -#include "Shared/Config/ClangModules.xcconfig" -#include "Shared/Config/ClangObjCLanguage.xcconfig" -#include "Shared/Config/ClangPreprocessing.xcconfig" -#include "Shared/Config/ClangWarnings.xcconfig" -#include "Shared/Config/ClangWarningsCpp.xcconfig" -#include "Shared/Config/ClangWarningsObjC.xcconfig" -#include "Shared/Config/AssetCatalog.xcconfig" -#include "Shared/Config/ClangAnalyzer.xcconfig" -#include "Shared/Config/Swift.xcconfig" -#include "Shared/Config/Metal.xcconfig" - -PRODUCT_BUNDLE_IDENTIFIER = io.sentry.sample.iOS13-Swift -INFOPLIST_FILE = iOS-Swift/iOS13-Swift/Info.plist -SUPPORTED_PLATFORMS = iphoneos iphonesimulator diff --git a/Samples/iOS13-Swift/iOS13-Swift-UITests.xcconfig b/Samples/iOS13-Swift/iOS13-Swift-UITests.xcconfig index 84b9f429da0..2889f1535c0 100644 --- a/Samples/iOS13-Swift/iOS13-Swift-UITests.xcconfig +++ b/Samples/iOS13-Swift/iOS13-Swift-UITests.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.sample.iOS13-Swift-UITests diff --git a/Samples/iOS13-Swift/iOS13-Swift.xcconfig b/Samples/iOS13-Swift/iOS13-Swift.xcconfig index c5bd04e4089..81450e2f75d 100644 --- a/Samples/iOS13-Swift/iOS13-Swift.xcconfig +++ b/Samples/iOS13-Swift/iOS13-Swift.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.sample.iOS13-Swift INFOPLIST_FILE = iOS-Swift/iOS13-Swift/Info.plist diff --git a/Samples/iOS15-SwiftUI/iOS15-SwiftUI.xcconfig b/Samples/iOS15-SwiftUI/iOS15-SwiftUI.xcconfig index 5121ff10d72..2ca224c3518 100644 --- a/Samples/iOS15-SwiftUI/iOS15-SwiftUI.xcconfig +++ b/Samples/iOS15-SwiftUI/iOS15-SwiftUI.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.iOS15-SwiftUI INFOPLIST_FILE = iOS15-SwiftUI/Info.plist diff --git a/Samples/macOS-Swift/Shared/NSObject+SentryAppSetup.m b/Samples/macOS-Swift/Shared/NSObject+SentryAppSetup.m index e4ffb419d9e..8edb0413d0c 100644 --- a/Samples/macOS-Swift/Shared/NSObject+SentryAppSetup.m +++ b/Samples/macOS-Swift/Shared/NSObject+SentryAppSetup.m @@ -4,7 +4,8 @@ @implementation NSObject (SentryAppSetup) + (void)load { NSLog(@"[iOS-Swift] Starting app launch work"); - if ([NSProcessInfo.processInfo.arguments containsObject:@"--io.sentry.slow-load-method"]) { + if ([NSProcessInfo.processInfo.arguments + containsObject:@"--io.sentry.profiling.slow-load-method"]) { [self sentry_slowLoadWork]; } NSLog(@"[iOS-Swift] Finishing app launch work"); diff --git a/Samples/macOS-Swift/Shared/ViewController.swift b/Samples/macOS-Swift/Shared/ViewController.swift index a8dd08f79f1..57fcc3c78a0 100644 --- a/Samples/macOS-Swift/Shared/ViewController.swift +++ b/Samples/macOS-Swift/Shared/ViewController.swift @@ -44,11 +44,15 @@ class ViewController: NSViewController { scope.setLevel(.fatal) } +#if SDK_V9 + print("SDK V9 does not support user feedback.") +#else let userFeedback = UserFeedback(eventId: eventId) userFeedback.comments = "It broke on macOS-Swift. I don't know why, but this happens." userFeedback.email = "john@me.com" userFeedback.name = "John Me" SentrySDK.capture(userFeedback: userFeedback) + #endif // SDK_V9 } @IBAction func raiseNSException(_ sender: Any) { diff --git a/Samples/macOS-Swift/Shared/macOS-Swift.xcconfig b/Samples/macOS-Swift/Shared/macOS-Swift.xcconfig deleted file mode 100644 index 5bde52a641c..00000000000 --- a/Samples/macOS-Swift/Shared/macOS-Swift.xcconfig +++ /dev/null @@ -1,30 +0,0 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" - -PRODUCT_BUNDLE_IDENTIFIER = io.sentry.macOS-Swift -INFOPLIST_FILE = Shared/Info.plist -SWIFT_OBJC_BRIDGING_HEADER = Shared/macOS-Swift-Bridging-Header.h - -SUPPORTED_PLATFORMS = macosx - -MACOSX_DEPLOYMENT_TARGET = 10.15 diff --git a/Samples/macOS-Swift/macOS-Swift-Other.xcconfig b/Samples/macOS-Swift/macOS-Swift-Other.xcconfig index a5a71a3bee1..ac1faa92d58 100644 --- a/Samples/macOS-Swift/macOS-Swift-Other.xcconfig +++ b/Samples/macOS-Swift/macOS-Swift-Other.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.macOS-Swift-Other INFOPLIST_FILE = Shared/Info.plist diff --git a/Samples/macOS-Swift/macOS-Swift-Sandboxed-Other.xcconfig b/Samples/macOS-Swift/macOS-Swift-Sandboxed-Other.xcconfig index e81074d4f43..4670084db26 100644 --- a/Samples/macOS-Swift/macOS-Swift-Sandboxed-Other.xcconfig +++ b/Samples/macOS-Swift/macOS-Swift-Sandboxed-Other.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.macOS-Swift-Sandboxed-Other INFOPLIST_FILE = Shared/Info.plist diff --git a/Samples/macOS-Swift/macOS-Swift-Sandboxed.xcconfig b/Samples/macOS-Swift/macOS-Swift-Sandboxed.xcconfig index 327744dd8be..3694506fd51 100644 --- a/Samples/macOS-Swift/macOS-Swift-Sandboxed.xcconfig +++ b/Samples/macOS-Swift/macOS-Swift-Sandboxed.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.macOS-Swift-Sandboxed INFOPLIST_FILE = Shared/Info.plist diff --git a/Samples/macOS-Swift/macOS-Swift-UITests.xcconfig b/Samples/macOS-Swift/macOS-Swift-UITests.xcconfig index d7bd19228ac..997ac04a61e 100644 --- a/Samples/macOS-Swift/macOS-Swift-UITests.xcconfig +++ b/Samples/macOS-Swift/macOS-Swift-UITests.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.iOS-Swift-UITests diff --git a/Samples/macOS-Swift/macOS-Swift-UITests/MacOSSwiftUITests.swift b/Samples/macOS-Swift/macOS-Swift-UITests/MacOSSwiftUITests.swift index 73dc75e743c..78d8b38ae85 100644 --- a/Samples/macOS-Swift/macOS-Swift-UITests/MacOSSwiftUITests.swift +++ b/Samples/macOS-Swift/macOS-Swift-UITests/MacOSSwiftUITests.swift @@ -1,3 +1,4 @@ +import SentrySampleShared import XCTest final class MacOSSwiftUITests: XCTestCase { @@ -25,14 +26,14 @@ private extension MacOSSwiftUITests { let app = XCUIApplication(bundleIdentifier: appBundleID) if wipeData { - app.launchArguments.append("--io.sentry.wipe-data") + app.launchArguments.append(SentrySDKOverrides.Special.wipeDataOnLaunch.rawValue) } try launchAndConfigureSubsequentLaunches(app: app, shouldProfileThisLaunch: false, shouldProfileNextLaunch: shouldProfileLaunches, shouldBeSandboxed: isSandboxed) app.terminate() if wipeData { - app.launchArguments.removeAll { $0 == "--io.sentry.wipe-data" } + app.launchArguments.removeAll { $0 == SentrySDKOverrides.Special.wipeDataOnLaunch.rawValue } } // second launch to profile a launch if configured @@ -57,21 +58,21 @@ private extension MacOSSwiftUITests { ) throws { app.launchArguments.append(contentsOf: [ // these help avoid other profiles that'd be taken automatically, that interfere with the checking we do for the assertions later in the tests - "--disable-swizzling", - "--disable-auto-performance-tracing", - "--disable-uiviewcontroller-tracing", + SentrySDKOverrides.Other.disableSwizzling.rawValue, + SentrySDKOverrides.Performance.disablePerformanceTracing.rawValue, + SentrySDKOverrides.Performance.disableUIVCTracing.rawValue, // sets a marker function to run in a load command that the launch profile should detect - "--io.sentry.slow-load-method", + SentrySDKOverrides.Profiling.slowLoadMethod.rawValue, // override full chunk completion before stoppage introduced in https://github.com/getsentry/sentry-cocoa/pull/4214 - "--io.sentry.continuous-profiler-immediate-stop" + SentrySDKOverrides.Profiling.immediateStop.rawValue ]) app.launchEnvironment["--io.sentry.ui-test.test-name"] = name - if shouldProfileNextLaunch { - app.launchArguments.append("--io.sentry.enable-profile-app-starts") + if !shouldProfileNextLaunch { + app.launchArguments.append(SentrySDKOverrides.Profiling.disableAppStartProfiling.rawValue) } app.launch() diff --git a/Samples/macOS-Swift/macOS-Swift.xcconfig b/Samples/macOS-Swift/macOS-Swift.xcconfig index 5b23c0e995e..9ea5b5e0fcf 100644 --- a/Samples/macOS-Swift/macOS-Swift.xcconfig +++ b/Samples/macOS-Swift/macOS-Swift.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.macOS-Swift INFOPLIST_FILE = Shared/Info.plist diff --git a/Samples/macOS-Swift/macOS-Swift.yml b/Samples/macOS-Swift/macOS-Swift.yml index eee2e8b4123..1eae1433839 100644 --- a/Samples/macOS-Swift/macOS-Swift.yml +++ b/Samples/macOS-Swift/macOS-Swift.yml @@ -5,6 +5,7 @@ createIntermediateGroups: true generateEmptyDirectories: true configs: Debug: debug + DebugV9: debug Test: debug TestCI: debug Release: release @@ -16,6 +17,7 @@ projectReferences: fileGroups: - ../Shared/Config - macOS-Swift.yml + - ../../Plans/macOS-Swift_Base.xctestplan options: bundleIdPrefix: io.sentry targets: @@ -31,6 +33,7 @@ targets: - target: SentrySampleShared/SentrySampleShared configFiles: Debug: macOS-Swift.xcconfig + DebugV9: macOS-Swift.xcconfig Release: macOS-Swift.xcconfig Test: macOS-Swift.xcconfig TestCI: macOS-Swift.xcconfig @@ -52,6 +55,7 @@ targets: - target: macOS-Swift-Other - target: macOS-Swift-Sandboxed - target: macOS-Swift-Sandboxed-Other + - target: SentrySampleShared/SentrySampleShared configFiles: Debug: macOS-Swift-UITests.xcconfig Release: macOS-Swift-UITests.xcconfig diff --git a/Samples/macOS-SwiftUI/macOS-SwiftUI.xcconfig b/Samples/macOS-SwiftUI/macOS-SwiftUI.xcconfig index 67310e94dea..78613ed1b69 100644 --- a/Samples/macOS-SwiftUI/macOS-SwiftUI.xcconfig +++ b/Samples/macOS-SwiftUI/macOS-SwiftUI.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.macOS-SwiftUI INFOPLIST_FILE = macOS-SwiftUI/Info.plist diff --git a/Samples/tvOS-Swift/tvOS-SBSwift-UITests.xcconfig b/Samples/tvOS-Swift/tvOS-SBSwift-UITests.xcconfig index 85b330608fe..3f3b0ca9eee 100644 --- a/Samples/tvOS-Swift/tvOS-SBSwift-UITests.xcconfig +++ b/Samples/tvOS-Swift/tvOS-SBSwift-UITests.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.tvOS-SBSwift-UITests INFOPLIST_FILE = tvOS-SBSwift-UITests/Info.plist diff --git a/Samples/tvOS-Swift/tvOS-SBSwift.xcconfig b/Samples/tvOS-Swift/tvOS-SBSwift.xcconfig index a0af0e43371..6f17a7f7ed4 100644 --- a/Samples/tvOS-Swift/tvOS-SBSwift.xcconfig +++ b/Samples/tvOS-Swift/tvOS-SBSwift.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.tvOS-SBSwift INFOPLIST_FILE = tvOS-SBSwift/Info.plist diff --git a/Samples/tvOS-Swift/tvOS-Swift-UITests.xcconfig b/Samples/tvOS-Swift/tvOS-Swift-UITests.xcconfig index 7b63df29e3a..ae1801037ce 100644 --- a/Samples/tvOS-Swift/tvOS-Swift-UITests.xcconfig +++ b/Samples/tvOS-Swift/tvOS-Swift-UITests.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.tvOS-Swift-UITests INFOPLIST_FILE = tvOS-Swift-UITests/Info.plist diff --git a/Samples/tvOS-Swift/tvOS-Swift.xcconfig b/Samples/tvOS-Swift/tvOS-Swift.xcconfig index 6c8dc449391..e60a9129a55 100644 --- a/Samples/tvOS-Swift/tvOS-Swift.xcconfig +++ b/Samples/tvOS-Swift/tvOS-Swift.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.tvOS-Swift INFOPLIST_FILE = tvOS-Swift/Info.plist diff --git a/Samples/tvOS-Swift/tvOS-Swift.yml b/Samples/tvOS-Swift/tvOS-Swift.yml index 6f7238afe05..5b6ef4f1687 100644 --- a/Samples/tvOS-Swift/tvOS-Swift.yml +++ b/Samples/tvOS-Swift/tvOS-Swift.yml @@ -5,6 +5,7 @@ createIntermediateGroups: true generateEmptyDirectories: true configs: Debug: debug + DebugV9: debug Test: debug TestCI: debug Release: release @@ -17,6 +18,7 @@ fileGroups: - ../Shared/Config - tvOS-Swift.yml - ../../Plans/tvOS-Swift_Base.xctestplan + - ../../Plans/tvOS-SBSwift_Base.xctestplan options: bundleIdPrefix: io.sentry targets: @@ -32,6 +34,7 @@ targets: - target: SentrySampleShared/SentrySampleShared configFiles: Debug: tvOS-Swift.xcconfig + DebugV9: tvOS-Swift.xcconfig Release: tvOS-Swift.xcconfig Test: tvOS-Swift.xcconfig TestCI: tvOS-Swift.xcconfig diff --git a/Samples/tvOS-Swift/tvOS-Swift/ContentView.swift b/Samples/tvOS-Swift/tvOS-Swift/ContentView.swift index 532491accee..b231434e601 100644 --- a/Samples/tvOS-Swift/tvOS-Swift/ContentView.swift +++ b/Samples/tvOS-Swift/tvOS-Swift/ContentView.swift @@ -34,11 +34,15 @@ struct ContentView: View { scope.setLevel(.fatal) } +#if SDK_V9 + print("SDK V9 does not support user feedback.") +#else let userFeedback = UserFeedback(eventId: eventId) userFeedback.comments = "It broke on tvOS-Swift. I don't know why, but this happens." userFeedback.email = "john@me.com" userFeedback.name = "John Me" SentrySDK.capture(userFeedback: userFeedback) + #endif // SDK_V9 } var captureErrorAction: () -> Void = { diff --git a/Samples/visionOS-SPM/.gitignore b/Samples/visionOS-SPM/.gitignore new file mode 100644 index 00000000000..bb460e7be91 --- /dev/null +++ b/Samples/visionOS-SPM/.gitignore @@ -0,0 +1,7 @@ +.DS_Store +/.build +/Packages +/*.xcodeproj +xcuserdata/ +DerivedData/ +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata diff --git a/Samples/visionOS-SPM/Package.swift b/Samples/visionOS-SPM/Package.swift new file mode 100644 index 00000000000..35c5826ba85 --- /dev/null +++ b/Samples/visionOS-SPM/Package.swift @@ -0,0 +1,24 @@ +// swift-tools-version:5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "visionOS-SPM", + platforms: [.visionOS(.v1)], + products: [ + .executable(name: "visionOS-SPM", targets: ["visionOS-SPM"]) + ], + dependencies: [ + // branch is replaced in CI to the current sha + .package(name: "Sentry", path: "../../../sentry-cocoa") + ], + targets: [ + .executableTarget( + name: "visionOS-SPM", + dependencies: [.product(name: "Sentry", package: "Sentry")], + swiftSettings: [ + .unsafeFlags(["-warnings-as-errors"]) + ]) + ] +) diff --git a/Samples/visionOS-SPM/Sources/visionOS-SPM/ContentView.swift b/Samples/visionOS-SPM/Sources/visionOS-SPM/ContentView.swift new file mode 100644 index 00000000000..062da714328 --- /dev/null +++ b/Samples/visionOS-SPM/Sources/visionOS-SPM/ContentView.swift @@ -0,0 +1,10 @@ +import SwiftUI + +struct ContentView: View { + var body: some View { + VStack { + Text("Hello, world!") + } + .padding() + } +} diff --git a/Samples/visionOS-SPM/Sources/visionOS-SPM/main.swift b/Samples/visionOS-SPM/Sources/visionOS-SPM/main.swift new file mode 100644 index 00000000000..dbf4af692dd --- /dev/null +++ b/Samples/visionOS-SPM/Sources/visionOS-SPM/main.swift @@ -0,0 +1,19 @@ +import Foundation +import Sentry +import SwiftUI + +struct VisionOSApp: App { + + init() { + SentrySDK.start { options in + options.dsn = "https://a92d50327ac74b8b9aa4ea80eccfb267@o447951.ingest.sentry.io/5428557" + options.debug = true + } + } + + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/Samples/visionOS-Swift/visionOS-Swift.xcconfig b/Samples/visionOS-Swift/visionOS-Swift.xcconfig index 4e9dc5778cc..31b24cf54d8 100644 --- a/Samples/visionOS-Swift/visionOS-Swift.xcconfig +++ b/Samples/visionOS-Swift/visionOS-Swift.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.VisionOS-Swift INFOPLIST_FILE = visionOS-Swift/Info.plist diff --git a/Samples/visionOS-Swift/visionOS-Swift.yml b/Samples/visionOS-Swift/visionOS-Swift.yml index d6e64e1fdaa..de84fe19fda 100644 --- a/Samples/visionOS-Swift/visionOS-Swift.yml +++ b/Samples/visionOS-Swift/visionOS-Swift.yml @@ -5,6 +5,7 @@ createIntermediateGroups: true generateEmptyDirectories: true configs: Debug: debug + DebugV9: debug Test: debug TestCI: debug Release: release @@ -31,6 +32,7 @@ targets: - target: SentrySampleShared/SentrySampleShared configFiles: Debug: visionOS-Swift.xcconfig + DebugV9: visionOS-Swift.xcconfig Release: visionOS-Swift.xcconfig Test: visionOS-Swift.xcconfig TestCI: visionOS-Swift.xcconfig diff --git a/Samples/visionOS-Swift/visionOS-Swift/ContentView.swift b/Samples/visionOS-Swift/visionOS-Swift/ContentView.swift index df6ce1ed190..880ab38147f 100644 --- a/Samples/visionOS-Swift/visionOS-Swift/ContentView.swift +++ b/Samples/visionOS-Swift/visionOS-Swift/ContentView.swift @@ -23,11 +23,15 @@ struct ContentView: View { scope.setLevel(.fatal) } +#if SDK_V9 + print("SDK V9 does not support user feedback.") +#else let userFeedback = UserFeedback(eventId: eventId) userFeedback.comments = "It broke on visionOS-Swift. I don't know why, but this happens." userFeedback.email = "john@me.com" userFeedback.name = "John Me" SentrySDK.capture(userFeedback: userFeedback) +#endif // SDK_V9 } var captureErrorAction: () -> Void = { diff --git a/Samples/watchOS-Swift/.gitignore b/Samples/watchOS-Swift/.gitignore index 4dc6caa6cd3..a93e887bab1 100644 --- a/Samples/watchOS-Swift/.gitignore +++ b/Samples/watchOS-Swift/.gitignore @@ -1 +1 @@ -libs \ No newline at end of file +libs diff --git a/Samples/watchOS-Swift/watchOS-Swift-App.xcconfig b/Samples/watchOS-Swift/watchOS-Swift-App.xcconfig index 5fc08ec015c..3232ea78811 100644 --- a/Samples/watchOS-Swift/watchOS-Swift-App.xcconfig +++ b/Samples/watchOS-Swift/watchOS-Swift-App.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.watchOS-Swift.watchkitapp INFOPLIST_FILE = watchOS-Swift WatchKit App/Info.plist diff --git a/Samples/watchOS-Swift/watchOS-Swift-Extension.xcconfig b/Samples/watchOS-Swift/watchOS-Swift-Extension.xcconfig index b8e18275aa0..81b67a024b2 100644 --- a/Samples/watchOS-Swift/watchOS-Swift-Extension.xcconfig +++ b/Samples/watchOS-Swift/watchOS-Swift-Extension.xcconfig @@ -1,25 +1,4 @@ -#include "../Shared/Config/Architectures.xcconfig" -#include "../Shared/Config/BuildOptions.xcconfig" -#include "../Shared/Config/Deployment.xcconfig" -#include "../Shared/Config/Linking.xcconfig" -#include "../Shared/Config/Localization.xcconfig" -#include "../Shared/Config/Packaging.xcconfig" -#include "../Shared/Config/SearchPaths.xcconfig" -#include "../Shared/Config/Signing.xcconfig" -#include "../Shared/Config/Versioning.xcconfig" -#include "../Shared/Config/CodeGeneration.xcconfig" -#include "../Shared/Config/ClangLanguage.xcconfig" -#include "../Shared/Config/ClangCppLanguage.xcconfig" -#include "../Shared/Config/ClangModules.xcconfig" -#include "../Shared/Config/ClangObjCLanguage.xcconfig" -#include "../Shared/Config/ClangPreprocessing.xcconfig" -#include "../Shared/Config/ClangWarnings.xcconfig" -#include "../Shared/Config/ClangWarningsCpp.xcconfig" -#include "../Shared/Config/ClangWarningsObjC.xcconfig" -#include "../Shared/Config/AssetCatalog.xcconfig" -#include "../Shared/Config/ClangAnalyzer.xcconfig" -#include "../Shared/Config/Swift.xcconfig" -#include "../Shared/Config/Metal.xcconfig" +#include "../Shared/Config/_Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.watchOS-Swift.watchkitapp.watchkitextension INFOPLIST_FILE = watchOS-Swift WatchKit Extension/Info.plist diff --git a/Sentry.podspec b/Sentry.podspec index a01c7ea3574..9ec7a65e8c7 100644 --- a/Sentry.podspec +++ b/Sentry.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Sentry" - s.version = "8.53.2" + s.version = "8.56.0" s.summary = "Sentry client for cocoa" s.homepage = "https://github.com/getsentry/sentry-cocoa" s.license = "mit" @@ -19,6 +19,7 @@ Pod::Spec.new do |s| s.swift_versions = "5.5" s.pod_target_xcconfig = { 'GCC_ENABLE_CPP_EXCEPTIONS' => 'YES', + 'APPLICATION_EXTENSION_API_ONLY' => 'NO', 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++14', 'CLANG_CXX_LIBRARY' => 'libc++', 'SWIFT_INCLUDE_PATHS' => '${PODS_TARGET_SRCROOT}/Sources/Sentry/include', diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index a11a59ba91a..8e0019789a7 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -50,8 +50,6 @@ 0A9E917128DC7E7000FB4182 /* SentryInternalCDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A9E917028DC7E7000FB4182 /* SentryInternalCDefines.h */; }; 0AAE201E28ED9B9400D0CD80 /* SentryReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AAE201D28ED9B9400D0CD80 /* SentryReachability.m */; }; 0AAE202128ED9BCC00D0CD80 /* SentryReachability.h in Headers */ = {isa = PBXBuildFile; fileRef = 0AAE202028ED9BCC00D0CD80 /* SentryReachability.h */; }; - 0ADC33EC28D9BB780078D980 /* SentryUIDeviceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 0ADC33EB28D9BB780078D980 /* SentryUIDeviceWrapper.m */; }; - 0ADC33EE28D9BB890078D980 /* SentryUIDeviceWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0ADC33ED28D9BB890078D980 /* SentryUIDeviceWrapper.h */; }; 0ADC33F128D9BE940078D980 /* TestSentryUIDeviceWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ADC33EF28D9BE690078D980 /* TestSentryUIDeviceWrapper.swift */; }; 0AE455AD28F584D2006680E5 /* SentryReachabilityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0AE455AC28F584D2006680E5 /* SentryReachabilityTests.m */; }; 15360CCF2432777500112302 /* SentrySessionTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 15360CCE2432777400112302 /* SentrySessionTracker.m */; }; @@ -61,12 +59,10 @@ 15360CED2433A15500112302 /* SentryInstallation.m in Sources */ = {isa = PBXBuildFile; fileRef = 15360CEC2433A15500112302 /* SentryInstallation.m */; }; 15360CF02433A16D00112302 /* SentryInstallation.h in Headers */ = {isa = PBXBuildFile; fileRef = 15360CEF2433A16D00112302 /* SentryInstallation.h */; }; 15D0AC882459EE4D006541C2 /* SentryNSURLRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15D0AC872459EE4D006541C2 /* SentryNSURLRequestTests.swift */; }; - 15E0A8E1240C41CE00F044E3 /* SentryEnvelope.h in Headers */ = {isa = PBXBuildFile; fileRef = 15E0A8E0240C41CE00F044E3 /* SentryEnvelope.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 15E0A8E5240C457D00F044E3 /* SentryEnvelope.m in Sources */ = {isa = PBXBuildFile; fileRef = 15E0A8E4240C457D00F044E3 /* SentryEnvelope.m */; }; 15E0A8EA240F2C9000F044E3 /* SentrySerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 15E0A8E9240F2C8F00F044E3 /* SentrySerialization.h */; }; 15E0A8ED240F2CB000F044E3 /* SentrySerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 15E0A8EC240F2CB000F044E3 /* SentrySerialization.m */; }; 15E0A8F0240F638200F044E3 /* SentrySerializationNilTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 15E0A8EF240F638200F044E3 /* SentrySerializationNilTests.m */; }; - 15E0A8F22411A45A00F044E3 /* SentrySession.m in Sources */ = {isa = PBXBuildFile; fileRef = 15E0A8F12411A45A00F044E3 /* SentrySession.m */; }; + 15E0A8F22411A45A00F044E3 /* SentrySessionInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = 15E0A8F12411A45A00F044E3 /* SentrySessionInternal.m */; }; 33042A0D29DAF79A00C60085 /* SentryExtraContextProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 33042A0C29DAF79A00C60085 /* SentryExtraContextProvider.m */; }; 33042A1729DC2C4300C60085 /* SentryExtraContextProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33042A1629DC2C4300C60085 /* SentryExtraContextProviderTests.swift */; }; 33EB2A912C3412E4004FED3D /* SentryWithoutUIKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 33EB2A8F2C3411AE004FED3D /* SentryWithoutUIKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -87,6 +83,7 @@ 621F61F12BEA073A005E654F /* SentryEnabledFeaturesBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 621F61F02BEA073A005E654F /* SentryEnabledFeaturesBuilder.swift */; }; 62212B872D520CB00062C2FA /* SentryEventCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62212B862D520CB00062C2FA /* SentryEventCodable.swift */; }; 62277BBC2DA5183500EF06B7 /* SentryTracer+Test.m in Sources */ = {isa = PBXBuildFile; fileRef = 62277BBB2DA5183500EF06B7 /* SentryTracer+Test.m */; }; + 62278CA82E30B21A0022ABC6 /* SentryHttpTransportFlushIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62278CA72E30B21A0022ABC6 /* SentryHttpTransportFlushIntegrationTests.swift */; }; 622C08DB29E554B9002571D4 /* SentrySpanContext+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 622C08D929E554B9002571D4 /* SentrySpanContext+Private.h */; }; 62375FB92B47F9F000CC55F1 /* SentryDependencyContainerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62375FB82B47F9F000CC55F1 /* SentryDependencyContainerTests.swift */; }; 623C45B02A651D8200D9E88B /* SentryCoreDataTracker+Test.m in Sources */ = {isa = PBXBuildFile; fileRef = 623C45AF2A651D8200D9E88B /* SentryCoreDataTracker+Test.m */; }; @@ -362,15 +359,13 @@ 7B14089824878F950035403D /* SentryCrashStackEntryMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B14089724878F950035403D /* SentryCrashStackEntryMapper.m */; }; 7B14089A248791660035403D /* SentryCrashStackEntryMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B140899248791660035403D /* SentryCrashStackEntryMapperTests.swift */; }; 7B16FD022654F86B008177D3 /* SentrySysctlTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B16FD012654F86B008177D3 /* SentrySysctlTests.swift */; }; - 7B18DE4028D9F748004845C6 /* SentryNSNotificationCenterWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B18DE3F28D9F748004845C6 /* SentryNSNotificationCenterWrapper.h */; }; - 7B18DE4228D9F794004845C6 /* SentryNSNotificationCenterWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B18DE4128D9F794004845C6 /* SentryNSNotificationCenterWrapper.m */; }; - 7B18DE4A28DA0C8B004845C6 /* SentryNSNotificationCenterWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18DE4928DA0C8B004845C6 /* SentryNSNotificationCenterWrapperTests.swift */; }; + 7B18DE4028D9F748004845C6 /* SentryNotificationNames.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B18DE3F28D9F748004845C6 /* SentryNotificationNames.h */; }; 7B26BBFB24C0A66D00A79CCC /* SentrySdkInfoNilTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B26BBFA24C0A66D00A79CCC /* SentrySdkInfoNilTests.m */; }; 7B2A70D827D5F080008B0D15 /* SentryANRTrackerV1Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B2A70D727D5F07F008B0D15 /* SentryANRTrackerV1Tests.swift */; }; 7B2A70DB27D607CF008B0D15 /* SentryThreadWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B2A70DA27D607CF008B0D15 /* SentryThreadWrapper.h */; }; 7B2A70DD27D6083D008B0D15 /* SentryThreadWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B2A70DC27D6083D008B0D15 /* SentryThreadWrapper.m */; }; 7B2A70DF27D60904008B0D15 /* SentryTestThreadWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B2A70DE27D60904008B0D15 /* SentryTestThreadWrapper.swift */; }; - 7B2BB0032966F55900A1E102 /* SentryOptions+HybridSDKs.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B2BB0012966F55900A1E102 /* SentryOptions+HybridSDKs.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 7B2BB0032966F55900A1E102 /* SentryOptionsInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B2BB0012966F55900A1E102 /* SentryOptionsInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; 7B30B67C26527886006B2752 /* SentryDisplayLinkWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B30B67B26527886006B2752 /* SentryDisplayLinkWrapper.h */; }; 7B30B67E26527894006B2752 /* SentryDisplayLinkWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B30B67D26527894006B2752 /* SentryDisplayLinkWrapper.m */; }; 7B30B68026527C3C006B2752 /* SentryFramesTrackerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B30B67F26527C3C006B2752 /* SentryFramesTrackerTests.swift */; }; @@ -388,7 +383,7 @@ 7B4E23B6251A07BD00060D68 /* SentryDispatchQueueWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4E23B5251A07BD00060D68 /* SentryDispatchQueueWrapperTests.swift */; }; 7B4E23BE251A2BD500060D68 /* SentryCrashIntegrationSessionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B4E23BD251A2BD500060D68 /* SentryCrashIntegrationSessionHandler.h */; }; 7B4E23C2251A2C2B00060D68 /* SentryCrashIntegrationSessionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B4E23C1251A2C2B00060D68 /* SentryCrashIntegrationSessionHandler.m */; }; - 7B4E24FC251C97B500060D68 /* SentrySession.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B4E24FB251C97B400060D68 /* SentrySession.h */; }; + 7B4E24FC251C97B500060D68 /* SentrySessionInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B4E24FB251C97B400060D68 /* SentrySessionInternal.h */; }; 7B4E375525822C4500059C93 /* SentryAttachment.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B4E375425822C4500059C93 /* SentryAttachment.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7B4E375B2582313100059C93 /* SentryAttachmentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4E375A2582313100059C93 /* SentryAttachmentTests.swift */; }; 7B4E375F258231FC00059C93 /* SentryAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B4E375E258231FC00059C93 /* SentryAttachment.m */; }; @@ -403,7 +398,6 @@ 7B5AB65D27E48E5200F1D1BA /* TestThreadInspector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5AB65C27E48E5200F1D1BA /* TestThreadInspector.swift */; }; 7B5B94332657A816002E474B /* SentryAppStartTrackingIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5B94322657A816002E474B /* SentryAppStartTrackingIntegrationTests.swift */; }; 7B5B94352657AD21002E474B /* SentryFramesTrackingIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5B94342657AD21002E474B /* SentryFramesTrackingIntegrationTests.swift */; }; - 7B5CAF7127F5953400ED0DB6 /* SentryEnvelope+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B5CAF7027F5953400ED0DB6 /* SentryEnvelope+Private.h */; }; 7B5CAF7527F5A67C00ED0DB6 /* SentryNSURLRequestBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B5CAF7427F5A67C00ED0DB6 /* SentryNSURLRequestBuilder.h */; }; 7B5CAF7727F5A68C00ED0DB6 /* SentryNSURLRequestBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B5CAF7627F5A68C00ED0DB6 /* SentryNSURLRequestBuilder.m */; }; 7B5CAF7E27F5AD3500ED0DB6 /* TestNSURLRequestBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B5CAF7D27F5AD3500ED0DB6 /* TestNSURLRequestBuilder.m */; }; @@ -435,8 +429,6 @@ 7B72D23A28D074BC0014798A /* TestExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B72D23928D074BC0014798A /* TestExtensions.swift */; }; 7B77BE3527EC8445003C9020 /* SentryDiscardReasonMapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B77BE3427EC8445003C9020 /* SentryDiscardReasonMapper.h */; }; 7B77BE3727EC8460003C9020 /* SentryDiscardReasonMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B77BE3627EC8460003C9020 /* SentryDiscardReasonMapper.m */; }; - 7B7A30C624B48321005A4C6E /* SentryCrashWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B7A30C524B48321005A4C6E /* SentryCrashWrapper.h */; }; - 7B7A30C824B48389005A4C6E /* SentryCrashWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B7A30C724B48389005A4C6E /* SentryCrashWrapper.m */; }; 7B7A599526B692540060A676 /* SentryScreenFrames.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B7A599426B692540060A676 /* SentryScreenFrames.h */; settings = {ATTRIBUTES = (Private, ); }; }; 7B7A599726B692F00060A676 /* SentryScreenFrames.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B7A599626B692F00060A676 /* SentryScreenFrames.m */; }; 7B7D872C2486480B00D2ECFF /* SentryStacktraceBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B7D872B2486480B00D2ECFF /* SentryStacktraceBuilder.h */; }; @@ -458,8 +450,6 @@ 7B8713B426415BAA006D6004 /* SentryAppStartTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B8713B326415BAA006D6004 /* SentryAppStartTracker.m */; }; 7B87C916295ECFD700510C52 /* SentryMetricKitEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B87C915295ECFD700510C52 /* SentryMetricKitEventTests.swift */; }; 7B883F49253D714C00879E62 /* SentryCrashUUIDConversion.c in Sources */ = {isa = PBXBuildFile; fileRef = 7B883F48253D714C00879E62 /* SentryCrashUUIDConversion.c */; }; - 7B88F2FE24BC5A4C00ADF90A /* SentrySdkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B88F2FD24BC5A4C00ADF90A /* SentrySdkInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 7B88F30024BC5A7D00ADF90A /* SentrySdkInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B88F2FF24BC5A7D00ADF90A /* SentrySdkInfo.m */; }; 7B88F30224BC5C6D00ADF90A /* SentrySdkInfoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B88F30124BC5C6D00ADF90A /* SentrySdkInfoTests.swift */; }; 7B88F30424BC8E6500ADF90A /* SentrySerializationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B88F30324BC8E6500ADF90A /* SentrySerializationTests.swift */; }; 7B8CA85726DD4E6200DD872C /* SentryNetworkTrackerIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B8CA85626DD4E6200DD872C /* SentryNetworkTrackerIntegrationTests.swift */; }; @@ -474,8 +464,6 @@ 7B98D7CF25FB650F00C5A389 /* SentryWatchdogTerminationTrackingIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B98D7CE25FB650F00C5A389 /* SentryWatchdogTerminationTrackingIntegration.m */; }; 7B98D7D325FB65AE00C5A389 /* SentryWatchdogTerminationTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B98D7D225FB65AE00C5A389 /* SentryWatchdogTerminationTracker.m */; }; 7B98D7E025FB73B900C5A389 /* SentryWatchdogTerminationTrackerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B98D7DF25FB73B900C5A389 /* SentryWatchdogTerminationTrackerTests.swift */; }; - 7B98D7E425FB7A7200C5A389 /* SentryAppState.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B98D7E325FB7A7200C5A389 /* SentryAppState.h */; }; - 7B98D7E825FB7BCD00C5A389 /* SentryAppState.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B98D7E725FB7BCD00C5A389 /* SentryAppState.m */; }; 7B98D7EC25FB7C4900C5A389 /* SentryAppStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B98D7EB25FB7C4900C5A389 /* SentryAppStateTests.swift */; }; 7BA0C04628055F8E003E0326 /* SentryTransportAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BA0C04528055F8E003E0326 /* SentryTransportAdapter.h */; }; 7BA0C0482805600A003E0326 /* SentryTransportAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BA0C0472805600A003E0326 /* SentryTransportAdapter.m */; }; @@ -495,7 +483,7 @@ 7BA61CCC247D14E600C130A8 /* SentryThreadInspectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA61CCB247D14E600C130A8 /* SentryThreadInspectorTests.swift */; }; 7BA61CCF247EB59500C130A8 /* SentryCrashUUIDConversionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA61CCE247EB59500C130A8 /* SentryCrashUUIDConversionTests.swift */; }; 7BA61EA625F21E660008CAA2 /* SentrySDKLogTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA61EA525F21E660008CAA2 /* SentrySDKLogTests.swift */; }; - 7BA840A024A1EC6E00B718AA /* SentrySDKTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA8409F24A1EC6E00B718AA /* SentrySDKTests.swift */; }; + 7BA840A024A1EC6E00B718AA /* SentrySDKInternalTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA8409F24A1EC6E00B718AA /* SentrySDKInternalTests.swift */; }; 7BAF3DB5243C743E008A5414 /* SentryClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BAF3DB4243C743E008A5414 /* SentryClientTests.swift */; }; 7BAF3DB9243C9777008A5414 /* SentryTransport.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BAF3DB8243C9777008A5414 /* SentryTransport.h */; }; 7BAF3DCE243DCBFE008A5414 /* SentryTransportFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BAF3DCD243DCBFE008A5414 /* SentryTransportFactory.m */; }; @@ -505,8 +493,6 @@ 7BB42EF124F3B7B700D7B39A /* SentrySession+Equality.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BB42EF024F3B7B700D7B39A /* SentrySession+Equality.m */; }; 7BB6550D253EEB3900887E87 /* SentryUserFeedbackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB6550C253EEB3900887E87 /* SentryUserFeedbackTests.swift */; }; 7BB7E7C729267A28004BF96B /* EmptyIntegration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB7E7C629267A28004BF96B /* EmptyIntegration.swift */; }; - 7BBC826D25DFCFDE005F1ED8 /* SentryInAppLogic.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BBC826C25DFCFDE005F1ED8 /* SentryInAppLogic.h */; }; - 7BBC827125DFD039005F1ED8 /* SentryInAppLogic.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BBC827025DFD039005F1ED8 /* SentryInAppLogic.m */; }; 7BBC827925DFD7D7005F1ED8 /* SentryInAppLogicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBC827825DFD7D7005F1ED8 /* SentryInAppLogicTests.swift */; }; 7BBD1889244841EC00427C76 /* SentryHttpDateParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BBD1888244841EC00427C76 /* SentryHttpDateParser.h */; }; 7BBD188B244841FB00427C76 /* SentryHttpDateParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BBD188A244841FB00427C76 /* SentryHttpDateParser.m */; }; @@ -539,11 +525,8 @@ 7BC852332458802C005A70F0 /* SentryDataCategoryMapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BC852322458802C005A70F0 /* SentryDataCategoryMapper.h */; }; 7BC85235245880AE005A70F0 /* SentryDataCategoryMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BC85234245880AE005A70F0 /* SentryDataCategoryMapper.m */; }; 7BC8523724588115005A70F0 /* SentryDataCategory.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BC8523624588115005A70F0 /* SentryDataCategory.h */; }; - 7BC852392458830A005A70F0 /* SentryEnvelopeItemType.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BC852382458830A005A70F0 /* SentryEnvelopeItemType.h */; settings = {ATTRIBUTES = (Private, ); }; }; 7BC8523B2458849E005A70F0 /* SentryDataCategoryMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC8523A2458849E005A70F0 /* SentryDataCategoryMapperTests.swift */; }; - 7BC9A20028F41016001E7C4C /* SentryMeasurementValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BC9A1FF28F41016001E7C4C /* SentryMeasurementValue.h */; }; 7BC9A20228F41350001E7C4C /* SentryMeasurementUnit.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BC9A20128F41350001E7C4C /* SentryMeasurementUnit.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7BC9A20428F4166D001E7C4C /* SentryMeasurementValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BC9A20328F4166D001E7C4C /* SentryMeasurementValue.m */; }; 7BC9A20628F41781001E7C4C /* SentryMeasurementUnit.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BC9A20528F41781001E7C4C /* SentryMeasurementUnit.m */; }; 7BCFA71627D0BB50008C662C /* SentryANRTrackerV1.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BCFA71527D0BB50008C662C /* SentryANRTrackerV1.m */; }; 7BCFBD672681C95000BC27D8 /* SentryScopeObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BCFBD662681C95000BC27D8 /* SentryScopeObserver.h */; }; @@ -551,10 +534,6 @@ 7BCFBD6F2681D0EE00BC27D8 /* SentryCrashScopeObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BCFBD6E2681D0EE00BC27D8 /* SentryCrashScopeObserver.m */; }; 7BD337E424A356180050DB6E /* SentryCrashIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BD337E324A356180050DB6E /* SentryCrashIntegrationTests.swift */; }; 7BD4BD4127EB0F0D0071F4FF /* SentryDiscardReason.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BD4BD4027EB0F0C0071F4FF /* SentryDiscardReason.h */; }; - 7BD4BD4327EB29BA0071F4FF /* SentryClientReport.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BD4BD4227EB29BA0071F4FF /* SentryClientReport.h */; }; - 7BD4BD4527EB29F50071F4FF /* SentryClientReport.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BD4BD4427EB29F50071F4FF /* SentryClientReport.m */; }; - 7BD4BD4727EB2A3D0071F4FF /* SentryDiscardedEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BD4BD4627EB2A3D0071F4FF /* SentryDiscardedEvent.h */; }; - 7BD4BD4927EB2A5D0071F4FF /* SentryDiscardedEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BD4BD4827EB2A5D0071F4FF /* SentryDiscardedEvent.m */; }; 7BD4BD4B27EB2DC20071F4FF /* SentryDiscardedEventTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BD4BD4A27EB2DC20071F4FF /* SentryDiscardedEventTests.swift */; }; 7BD4BD4D27EB31820071F4FF /* SentryClientReportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BD4BD4C27EB31820071F4FF /* SentryClientReportTests.swift */; }; 7BD4E8E627FD84480086C410 /* TestFileManagerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BD4E8E527FD84480086C410 /* TestFileManagerDelegate.swift */; }; @@ -574,7 +553,6 @@ 7BDEAA022632A4580001EA25 /* SentryOptions+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BDEAA002632A4580001EA25 /* SentryOptions+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 7BE0DC29272A9E1C004FA8B7 /* SentryBreadcrumbTrackerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BE0DC28272A9E1C004FA8B7 /* SentryBreadcrumbTrackerTests.swift */; }; 7BE0DC2F272ABAF6004FA8B7 /* SentryAutoBreadcrumbTrackingIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BE0DC2E272ABAF6004FA8B7 /* SentryAutoBreadcrumbTrackingIntegrationTests.swift */; }; - 7BE1E32824F7AE08009D3AD0 /* SentrySession+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BE1E32624F7AE08009D3AD0 /* SentrySession+Private.h */; }; 7BE1E33224F7E3B6009D3AD0 /* SentryMigrateSessionInit.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BE1E33124F7E3B6009D3AD0 /* SentryMigrateSessionInit.h */; }; 7BE1E33424F7E3CB009D3AD0 /* SentryMigrateSessionInit.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BE1E33324F7E3CB009D3AD0 /* SentryMigrateSessionInit.m */; }; 7BE2C7F8257000A4003B66C7 /* SentryTestIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BE2C7F72570009F003B66C7 /* SentryTestIntegration.m */; }; @@ -590,7 +568,6 @@ 7BECF42226145C5D00D9826E /* SentryMechanismMeta.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BECF42126145C5D00D9826E /* SentryMechanismMeta.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7BECF42826145CD900D9826E /* SentryMechanismMeta.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BECF42726145CD900D9826E /* SentryMechanismMeta.m */; }; 7BECF432261463E600D9826E /* SentryMechanismMetaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BECF431261463E600D9826E /* SentryMechanismMetaTests.swift */; }; - 7BED3576266F7BFF00EAA70D /* TestSentryCrashWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BED3575266F7BFF00EAA70D /* TestSentryCrashWrapper.m */; }; 7BEF4957270C4B9D00F8F30E /* SentryUIViewControllerSwizzlingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BEF4956270C4B9D00F8F30E /* SentryUIViewControllerSwizzlingTests.swift */; }; 7BF536D124BDF3E7004FA6A2 /* SentryEnvelopeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BF536D024BDF3E7004FA6A2 /* SentryEnvelopeTests.swift */; }; 7BF536D424BEF255004FA6A2 /* SentryAssertions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BF536D324BEF255004FA6A2 /* SentryAssertions.swift */; }; @@ -602,9 +579,6 @@ 7BF9EF762722B34700B5BBEF /* SentrySubClassFinder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BF9EF752722B34700B5BBEF /* SentrySubClassFinder.h */; }; 7BF9EF782722B35D00B5BBEF /* SentrySubClassFinder.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BF9EF772722B35D00B5BBEF /* SentrySubClassFinder.m */; }; 7BF9EF7A2722B58900B5BBEF /* SentrySubClassFinderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BF9EF792722B58900B5BBEF /* SentrySubClassFinderTests.swift */; }; - 7BF9EF7C2722B90E00B5BBEF /* SentryDefaultObjCRuntimeWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BF9EF7B2722B90E00B5BBEF /* SentryDefaultObjCRuntimeWrapper.h */; }; - 7BF9EF7E2722B91F00B5BBEF /* SentryDefaultObjCRuntimeWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BF9EF7D2722B91F00B5BBEF /* SentryDefaultObjCRuntimeWrapper.m */; }; - 7BF9EF842722D07B00B5BBEF /* SentryObjCRuntimeWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BF9EF832722D07B00B5BBEF /* SentryObjCRuntimeWrapper.h */; }; 7BF9EF862722D10600B5BBEF /* SentryTestObjCRuntimeWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BF9EF852722D10600B5BBEF /* SentryTestObjCRuntimeWrapper.h */; }; 7BF9EF882722D13000B5BBEF /* SentryTestObjCRuntimeWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BF9EF872722D13000B5BBEF /* SentryTestObjCRuntimeWrapper.m */; }; 7BF9EF8B2722D58700B5BBEF /* SentryInitializeForGettingSubclassesNotCalled.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BF9EF8A2722D58700B5BBEF /* SentryInitializeForGettingSubclassesNotCalled.m */; }; @@ -618,8 +592,6 @@ 7D0637032382B34300B30749 /* SentryScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D0637022382B34300B30749 /* SentryScope.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7D082B8323C628790029866B /* SentryMeta.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D082B8023C628780029866B /* SentryMeta.m */; }; 7D0FCFB22379B915004DD83A /* SentryHub.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D0FCFB02379B915004DD83A /* SentryHub.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7D427C62237B1D200046BAC8 /* SentrySDK.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D427C5F237B1D200046BAC8 /* SentrySDK.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7D5C441A237C2E1F00DAB0A3 /* SentrySDK.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D5C4418237C2E1F00DAB0A3 /* SentrySDK.m */; }; 7D5C441C237C2E1F00DAB0A3 /* SentryHub.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D5C4419237C2E1F00DAB0A3 /* SentryHub.m */; }; 7D65260E237F649E00113EA2 /* SentryScope.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D65260B237F649E00113EA2 /* SentryScope.m */; }; 7D7F0A5F23DF3D2C00A4629C /* SentryGlobalEventProcessor.h in Headers */ = {isa = PBXBuildFile; fileRef = 7D7F0A5E23DF3D2C00A4629C /* SentryGlobalEventProcessor.h */; }; @@ -667,12 +639,8 @@ 843FB3232D0CD04D00558F18 /* SentryUserAccess.m in Sources */ = {isa = PBXBuildFile; fileRef = 843FB3222D0CD04D00558F18 /* SentryUserAccess.m */; }; 843FB3242D0CD04D00558F18 /* SentryUserAccess.h in Headers */ = {isa = PBXBuildFile; fileRef = 843FB3212D0CD04D00558F18 /* SentryUserAccess.h */; }; 843FB3432D156B9900558F18 /* SentryFeedbackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 843FB3412D156B9900558F18 /* SentryFeedbackTests.swift */; }; - 844EDC6F294143B900C86F34 /* SentryNSProcessInfoWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 844EDC6D294143B900C86F34 /* SentryNSProcessInfoWrapper.h */; }; - 844EDC70294143B900C86F34 /* SentryNSProcessInfoWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 844EDC6E294143B900C86F34 /* SentryNSProcessInfoWrapper.mm */; }; 844EDC76294144DB00C86F34 /* SentrySystemWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 844EDC74294144DB00C86F34 /* SentrySystemWrapper.h */; }; 844EDC77294144DB00C86F34 /* SentrySystemWrapper.mm in Sources */ = {isa = PBXBuildFile; fileRef = 844EDC75294144DB00C86F34 /* SentrySystemWrapper.mm */; }; - 844EDCE52947DC3100C86F34 /* SentryNSTimerFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 844EDCE32947DC3100C86F34 /* SentryNSTimerFactory.h */; }; - 844EDCE62947DC3100C86F34 /* SentryNSTimerFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 844EDCE42947DC3100C86F34 /* SentryNSTimerFactory.m */; }; 844EDD6C2949387000C86F34 /* SentryMetricProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 844EDD6B2949387000C86F34 /* SentryMetricProfiler.h */; }; 8453421228BE855D00C22EEC /* SentrySampleDecision.m in Sources */ = {isa = PBXBuildFile; fileRef = 8453421128BE855D00C22EEC /* SentrySampleDecision.m */; }; 8453421628BE8A9500C22EEC /* SentrySpanStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 8453421528BE8A9500C22EEC /* SentrySpanStatus.m */; }; @@ -702,6 +670,9 @@ 84A8891C28DBD28900C51DFD /* SentryDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 84A8891A28DBD28900C51DFD /* SentryDevice.h */; }; 84A8891D28DBD28900C51DFD /* SentryDevice.m in Sources */ = {isa = PBXBuildFile; fileRef = 84A8891B28DBD28900C51DFD /* SentryDevice.m */; }; 84A8892128DBD8D600C51DFD /* SentryDeviceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 84A8892028DBD8D600C51DFD /* SentryDeviceTests.m */; }; + 84A898542E163072009A551E /* SentryProfileConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 84A898532E163072009A551E /* SentryProfileConfiguration.m */; }; + 84A898552E163072009A551E /* SentryProfileConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 84A898522E163072009A551E /* SentryProfileConfiguration.h */; }; + 84A898CE2E1DBDD1009A551E /* SentryAppStartProfilingConfigurationChangeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A898CD2E1DBDD1009A551E /* SentryAppStartProfilingConfigurationChangeTests.swift */; }; 84A903712D39F66F00690CE4 /* SentryUserFeedbackFormViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84A903702D39F66F00690CE4 /* SentryUserFeedbackFormViewModel.swift */; }; 84AC61D229F7541E009EEF61 /* SentryDispatchSourceWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 84AC61D029F7541E009EEF61 /* SentryDispatchSourceWrapper.h */; }; 84AC61D329F7541E009EEF61 /* SentryDispatchSourceWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 84AC61D129F7541E009EEF61 /* SentryDispatchSourceWrapper.m */; }; @@ -736,16 +707,14 @@ 84E13B842CBF1D91003B52EC /* SentryUserFeedbackWidgetButtonMegaphoneIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E13B832CBF1D91003B52EC /* SentryUserFeedbackWidgetButtonMegaphoneIconView.swift */; }; 84EB21942BF01C6C00EDDA28 /* TestNSNotificationCenterWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18DE4328D9F8F6004845C6 /* TestNSNotificationCenterWrapper.swift */; }; 84EB21962BF01CEA00EDDA28 /* SentryCrashInstallationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84EB21952BF01CEA00EDDA28 /* SentryCrashInstallationTests.swift */; }; - 84F2A1CE2E06001300A94524 /* SentryApplaunchProfilingMalformedConfigFileTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84F2A1CD2E06001300A94524 /* SentryApplaunchProfilingMalformedConfigFileTests.swift */; }; + 84F2A1CE2E06001300A94524 /* (null) in Sources */ = {isa = PBXBuildFile; }; 84F994E62A6894B500EC0190 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84F994E52A6894B500EC0190 /* CoreData.framework */; }; 84F994E82A6894BD00EC0190 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84F994E72A6894BD00EC0190 /* SystemConfiguration.framework */; platformFilters = (ios, maccatalyst, macos, tvos, ); }; - 861265F92404EC1500C4AFDE /* NSArray+SentrySanitize.h in Headers */ = {isa = PBXBuildFile; fileRef = 861265F72404EC1500C4AFDE /* NSArray+SentrySanitize.h */; }; - 861265FA2404EC1500C4AFDE /* NSArray+SentrySanitize.m in Sources */ = {isa = PBXBuildFile; fileRef = 861265F82404EC1500C4AFDE /* NSArray+SentrySanitize.m */; }; + 861265F92404EC1500C4AFDE /* SentryArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 861265F72404EC1500C4AFDE /* SentryArray.h */; }; + 861265FA2404EC1500C4AFDE /* SentryArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 861265F82404EC1500C4AFDE /* SentryArray.m */; }; 8E0551E026A7A63C00400526 /* TestProtocolClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E0551DF26A7A63C00400526 /* TestProtocolClient.swift */; }; 8E133FA225E72DEF00ABD0BF /* SentrySamplingContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E133FA025E72DEF00ABD0BF /* SentrySamplingContext.m */; }; 8E133FA625E72EB400ABD0BF /* SentrySamplingContext.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E133FA525E72EB400ABD0BF /* SentrySamplingContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 8E25C95325F836D000DC215B /* SentryRandom.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E25C95125F836D000DC215B /* SentryRandom.m */; }; - 8E25C95725F836EE00DC215B /* SentryRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E25C95625F836EE00DC215B /* SentryRandom.h */; }; 8E4A037825F6F52100000D77 /* SentrySampleDecision.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E4A037725F6F52100000D77 /* SentrySampleDecision.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8E4E7C6D25DAAAFE006AB9E2 /* SentryTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E4E7C6B25DAAAFE006AB9E2 /* SentryTransaction.h */; }; 8E4E7C6E25DAAAFE006AB9E2 /* SentrySpan.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E4E7C6C25DAAAFE006AB9E2 /* SentrySpan.h */; }; @@ -788,17 +757,25 @@ 8F0D6AA22B04115A00D048B1 /* SentryInstallation+Test.h in Sources */ = {isa = PBXBuildFile; fileRef = 8F0D6AA12B040A0100D048B1 /* SentryInstallation+Test.h */; }; 8F73BC312B02B87E00C3CEF4 /* SentryInstallationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F73BC302B02B87E00C3CEF4 /* SentryInstallationTests.swift */; }; 92136D672C9D7660002A9FB8 /* SentryNSURLRequestBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92136D662C9D765D002A9FB8 /* SentryNSURLRequestBuilderTests.swift */; }; + 92235CAC2E15369900865983 /* SentryLogBatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92235CAB2E15369900865983 /* SentryLogBatcher.swift */; }; + 92235CAE2E15549C00865983 /* SentryLogger.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92235CAD2E15549C00865983 /* SentryLogger.swift */; }; + 92235CB02E155B2600865983 /* SentryLoggerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92235CAF2E155B2600865983 /* SentryLoggerTests.swift */; }; 925824C22CB5897700C9B20B /* SentrySessionReplayIntegration-Hybrid.h in Headers */ = {isa = PBXBuildFile; fileRef = D80382BE2C09C6FD0090E048 /* SentrySessionReplayIntegration-Hybrid.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 9264E1EB2E2E385E00B077CF /* SentryLogMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9264E1EA2E2E385B00B077CF /* SentryLogMessage.swift */; }; + 9264E1ED2E2E397C00B077CF /* SentryLogMessageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9264E1EC2E2E397400B077CF /* SentryLogMessageTests.swift */; }; 92672BB629C9A2A9006B021C /* SentryBreadcrumb+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 92672BB529C9A2A9006B021C /* SentryBreadcrumb+Private.h */; settings = {ATTRIBUTES = (Private, ); }; }; 927A5CC42DD7626B00B82404 /* SentryEnvelopeItemHeaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 927A5CC32DD7626400B82404 /* SentryEnvelopeItemHeaderTests.swift */; }; + 928207C42E251B8F009285A4 /* SentryScope+PrivateSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = 928207C32E251B8F009285A4 /* SentryScope+PrivateSwift.h */; }; 9286059529A5096600F96038 /* SentryGeo.h in Headers */ = {isa = PBXBuildFile; fileRef = 9286059429A5096600F96038 /* SentryGeo.h */; settings = {ATTRIBUTES = (Public, ); }; }; 9286059729A5098900F96038 /* SentryGeo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9286059629A5098900F96038 /* SentryGeo.m */; }; 9286059929A50BAB00F96038 /* SentryGeoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9286059829A50BAA00F96038 /* SentryGeoTests.swift */; }; + 928BED2B2E16977A00B4D398 /* SentryLogBatcherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 928BED2A2E16977A00B4D398 /* SentryLogBatcherTests.swift */; }; 92B6BDA92E05B8F600D538B3 /* SentryLogLevelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92B6BDA82E05B8F000D538B3 /* SentryLogLevelTests.swift */; }; 92B6BDAD2E05B9FB00D538B3 /* SentryLogTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92B6BDAC2E05B9F700D538B3 /* SentryLogTests.swift */; }; 92D957732E05A44600E20E66 /* SentryAsyncLog.m in Sources */ = {isa = PBXBuildFile; fileRef = 92D957722E05A44600E20E66 /* SentryAsyncLog.m */; }; 92D957772E05A4F300E20E66 /* SentryAsyncLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 92D957762E05A4F300E20E66 /* SentryAsyncLog.h */; }; 92E5F3D62CDBB3BF00B7AD98 /* SentrySampling.h in Headers */ = {isa = PBXBuildFile; fileRef = 8E8C57A525EEFC42001CEEFA /* SentrySampling.h */; }; + 92EC54CE2E1EB54B00A10AC2 /* SentryClient+Logs.h in Headers */ = {isa = PBXBuildFile; fileRef = 92EC54CD2E1EB54B00A10AC2 /* SentryClient+Logs.h */; }; 92ECD7202E05A7DF0063EC10 /* SentryLogC.h in Headers */ = {isa = PBXBuildFile; fileRef = D8AE48B12C5786AA0092A2A6 /* SentryLogC.h */; settings = {ATTRIBUTES = (Private, ); }; }; 92ECD73C2E05ACE00063EC10 /* SentryLog.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92ECD73B2E05ACDE0063EC10 /* SentryLog.swift */; }; 92ECD73E2E05AD320063EC10 /* SentryLogLevel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92ECD73D2E05AD2B0063EC10 /* SentryLogLevel.swift */; }; @@ -815,9 +792,6 @@ A8F17B2E2901765900990B25 /* SentryRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F17B2D2901765900990B25 /* SentryRequest.m */; }; A8F17B342902870300990B25 /* SentryHttpStatusCodeRange.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F17B332902870300990B25 /* SentryHttpStatusCodeRange.m */; }; D4009EB22D771BC20007AF30 /* SentryFileIOTrackerSwiftHelpersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4009EB12D771BB90007AF30 /* SentryFileIOTrackerSwiftHelpersTests.swift */; }; - D40604472DD2471600C40DC0 /* SentryNSApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = D40604462DD2471600C40DC0 /* SentryNSApplication.m */; }; - D40604492DD2472600C40DC0 /* SentryNSApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = D40604482DD2472600C40DC0 /* SentryNSApplication.h */; }; - D406044B2DD2483D00C40DC0 /* SentryApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = D406044A2DD2483D00C40DC0 /* SentryApplication.h */; }; D41415A72DEEE532003B14D5 /* SentryRedactViewHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D41415A62DEEE532003B14D5 /* SentryRedactViewHelper.swift */; }; D4291A692DD61A3F00772088 /* SentryDispatchQueueProviderProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D4291A672DD61A3F00772088 /* SentryDispatchQueueProviderProtocol.h */; }; D4291A6D2DD62ACE00772088 /* SentryDispatchFactoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4291A6C2DD62AC800772088 /* SentryDispatchFactoryTests.m */; }; @@ -848,6 +822,9 @@ D456B4322D706BDF007068CB /* SentrySpanOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = D456B4312D706BDD007068CB /* SentrySpanOperation.h */; }; D456B4362D706BF2007068CB /* SentryTraceOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = D456B4352D706BEE007068CB /* SentryTraceOrigin.h */; }; D456B4382D706BFE007068CB /* SentrySpanDataKey.h in Headers */ = {isa = PBXBuildFile; fileRef = D456B4372D706BFB007068CB /* SentrySpanDataKey.h */; }; + D45B4AF52E019E1A00C31DFB /* TestSentryViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45B4AF42E019E1500C31DFB /* TestSentryViewRenderer.swift */; }; + D45B4AF72E01A10100C31DFB /* TestSentryViewPhotographer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45B4AF62E01A0FA00C31DFB /* TestSentryViewPhotographer.swift */; }; + D45CE9752E5F454E00BFEDB2 /* SentryScreenshotSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45CE9742E5F454300BFEDB2 /* SentryScreenshotSource.swift */; }; D45E2D772E003EBF0072A6B7 /* TestRedactOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D45E2D762E003EBF0072A6B7 /* TestRedactOptions.swift */; }; D467125E2DCCFF2500D4074A /* SentryReplayOptionsObjcTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D467125D2DCCFF2500D4074A /* SentryReplayOptionsObjcTests.m */; }; D46712622DCD059900D4074A /* SentryRedactDefaultOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D46712612DCD059500D4074A /* SentryRedactDefaultOptionsTests.swift */; }; @@ -860,6 +837,7 @@ D48724E22D354D16005DE483 /* SentryTraceOriginTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D48724E12D354D16005DE483 /* SentryTraceOriginTests.swift */; }; D48E8B8B2D3E79610032E35E /* SentryTraceOrigin.swift in Sources */ = {isa = PBXBuildFile; fileRef = D48E8B8A2D3E79610032E35E /* SentryTraceOrigin.swift */; }; D48E8B9D2D3E82AC0032E35E /* SentrySpanOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D48E8B9C2D3E82AC0032E35E /* SentrySpanOperation.swift */; }; + D490648A2DFAE1F600555785 /* SentryScreenshotOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49064892DFAE1F600555785 /* SentryScreenshotOptions.swift */; }; D49480D32DC23E9300A3B6E9 /* SentryReplayTypeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49480D22DC23E8E00A3B6E9 /* SentryReplayTypeTests.swift */; }; D49480D72DC23FE300A3B6E9 /* SentrySessionReplayDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D49480D62DC23FE200A3B6E9 /* SentrySessionReplayDelegate.swift */; }; D4AF00212D2E92FD00F5F3D7 /* SentryNSFileManagerSwizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = D4AF00202D2E92FD00F5F3D7 /* SentryNSFileManagerSwizzling.m */; }; @@ -867,15 +845,21 @@ D4AF00252D2E93C400F5F3D7 /* SentryNSFileManagerSwizzlingTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4AF00242D2E93C400F5F3D7 /* SentryNSFileManagerSwizzlingTests.m */; }; D4B0DC7F2DA9257A00DE61B6 /* SentryRenderVideoResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4B0DC7E2DA9257200DE61B6 /* SentryRenderVideoResult.swift */; }; D4C5F59A2D4249E6002A9BF6 /* DataSentryTracingIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4C5F5992D4249E0002A9BF6 /* DataSentryTracingIntegrationTests.swift */; }; + D4CA34832E378C9900E92A61 /* SentryArrayTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CA34822E378C9000E92A61 /* SentryArrayTests.swift */; }; D4CBA2472DE06D0200581618 /* libSentryTestUtils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8431F00A29B284F200D8DC56 /* libSentryTestUtils.a */; }; D4CBA2532DE06D1600581618 /* TestConstantTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CBA2512DE06D1600581618 /* TestConstantTests.swift */; }; D4CD2A802DE9F91900DA9F59 /* SentryRedactRegion.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CD2A7C2DE9F91900DA9F59 /* SentryRedactRegion.swift */; }; D4CD2A812DE9F91900DA9F59 /* SentryRedactRegionType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CD2A7D2DE9F91900DA9F59 /* SentryRedactRegionType.swift */; }; + D4D12E7A2DFC608800DC45C4 /* SentryScreenshotOptionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4D12E792DFC607F00DC45C4 /* SentryScreenshotOptionsTests.swift */; }; + D4DEE6592E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4DEE6582E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m */; }; D4E3F35D2D4A864600F79E2B /* SentryNSDictionarySanitizeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D42E48582D48FC8F00D251BC /* SentryNSDictionarySanitizeTests.swift */; }; D4E3F35E2D4A877300F79E2B /* SentryNSDictionarySanitize+Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = D41909942D490006002B83D0 /* SentryNSDictionarySanitize+Tests.m */; }; + D4ECA4012E3CBEDE00C757EA /* SentryDummyPublicEmptyClass.m in Sources */ = {isa = PBXBuildFile; fileRef = D4ECA4002E3CBEDE00C757EA /* SentryDummyPublicEmptyClass.m */; }; + D4ECA4022E3CBEDE00C757EA /* SentryDummyPrivateEmptyClass.m in Sources */ = {isa = PBXBuildFile; fileRef = D4ECA3FF2E3CBEDE00C757EA /* SentryDummyPrivateEmptyClass.m */; }; D4EDF9842D0B2A210071E7B3 /* Data+SentryTracing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4EDF9832D0B2A1D0071E7B3 /* Data+SentryTracing.swift */; }; D4EE12D22DE9AC3800385BAF /* TestNSNotificationCenterWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4EE12D12DE9AC3300385BAF /* TestNSNotificationCenterWrapperTests.swift */; }; D4F2B5352D0C69D500649E42 /* SentryCrashCTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F2B5342D0C69D100649E42 /* SentryCrashCTests.swift */; }; + D4F7BD822E4373BF004A2D77 /* SentryLevelMapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4F7BD7C2E4373BB004A2D77 /* SentryLevelMapperTests.swift */; }; D4FC68172DD632E7001B74FF /* SentryDispatchSourceProviderProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = D4FC68162DD632E7001B74FF /* SentryDispatchSourceProviderProtocol.h */; }; D4FC681A2DD63465001B74FF /* SentryDispatchQueueWrapperTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4FC68192DD63465001B74FF /* SentryDispatchQueueWrapperTests.m */; }; D8019910286B089000C277F0 /* SentryCrashReportSinkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D801990F286B089000C277F0 /* SentryCrashReportSinkTests.swift */; }; @@ -897,7 +881,7 @@ D8199DC029376EE80074249E /* SentrySwiftUI.h in Headers */ = {isa = PBXBuildFile; fileRef = D8199DB529376ECC0074249E /* SentrySwiftUI.h */; }; D8199DC129376EEC0074249E /* SentryTracedView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8199DB629376ECC0074249E /* SentryTracedView.swift */; }; D81A346C291AECC7005A27A9 /* PrivateSentrySDKOnly.h in Headers */ = {isa = PBXBuildFile; fileRef = D81A346B291AECC7005A27A9 /* PrivateSentrySDKOnly.h */; settings = {ATTRIBUTES = (Private, ); }; }; - D81FDF12280EA1060045E0E4 /* SentryScreenShotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D81FDF10280EA0080045E0E4 /* SentryScreenShotTests.swift */; }; + D81FDF12280EA1060045E0E4 /* SentryScreenshotSourceTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D81FDF10280EA0080045E0E4 /* SentryScreenshotSourceTests.swift */; }; D820CDB72BB1895F00BA339D /* SentrySessionReplayIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = D820CDB62BB1895F00BA339D /* SentrySessionReplayIntegration.m */; }; D820CDB82BB1895F00BA339D /* SentrySessionReplayIntegration.h in Headers */ = {isa = PBXBuildFile; fileRef = D820CDB52BB1895F00BA339D /* SentrySessionReplayIntegration.h */; settings = {ATTRIBUTES = (Private, ); }; }; D82859432C3E753C009A28AA /* SentrySessionReplaySyncC.c in Sources */ = {isa = PBXBuildFile; fileRef = D82859422C3E753C009A28AA /* SentrySessionReplaySyncC.c */; }; @@ -931,9 +915,6 @@ D855AD62286ED6A4002573E1 /* SentryCrashTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D855AD61286ED6A4002573E1 /* SentryCrashTests.m */; }; D855B3E827D652AF00BCED76 /* SentryCoreDataTrackingIntegrationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D855B3E727D652AF00BCED76 /* SentryCoreDataTrackingIntegrationTest.swift */; }; D855B3EA27D652C700BCED76 /* TestCoreDataStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = D855B3E927D652C700BCED76 /* TestCoreDataStack.swift */; }; - D85852BA27EDDC5900C6D8AE /* SentryUIApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = D85852B827EDDC5900C6D8AE /* SentryUIApplication.m */; }; - D858FA662A29EAB3002A3503 /* SentryBinaryImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D858FA642A29EAB3002A3503 /* SentryBinaryImageCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; - D858FA672A29EAB3002A3503 /* SentryBinaryImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D858FA652A29EAB3002A3503 /* SentryBinaryImageCache.m */; }; D859696B27BECD8F0036A46E /* SentryCoreDataTrackingIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = D859696927BECD8F0036A46E /* SentryCoreDataTrackingIntegration.m */; }; D859696F27BECDA20036A46E /* SentryCoreDataTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = D859696D27BECDA20036A46E /* SentryCoreDataTracker.m */; }; D859697327BECDD20036A46E /* SentryCoreDataSwizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = D859697127BECDD20036A46E /* SentryCoreDataSwizzling.m */; }; @@ -985,7 +966,7 @@ D8B088B729C9E3FF00213258 /* SentryTracerConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = D8B088B529C9E3FF00213258 /* SentryTracerConfiguration.m */; }; D8B665BC2B95F73200BD0E7B /* SentryPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = D8B665BA2B95F54200BD0E7B /* SentryPrivate.h */; }; D8B76B062808066D000A58C4 /* SentryScreenshotIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8B76B042808060E000A58C4 /* SentryScreenshotIntegrationTests.swift */; }; - D8B76B0828081461000A58C4 /* TestSentryScreenShot.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8B76B0728081461000A58C4 /* TestSentryScreenShot.swift */; }; + D8B76B0828081461000A58C4 /* TestSentryScreenshotProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8B76B0728081461000A58C4 /* TestSentryScreenshotProvider.swift */; }; D8BBD32728FD9FC00011F850 /* SentrySwift.h in Headers */ = {isa = PBXBuildFile; fileRef = D8BBD32628FD9FBF0011F850 /* SentrySwift.h */; settings = {ATTRIBUTES = (Private, ); }; }; D8BC28C82BFF5EBB0054DA4D /* SentryTouchTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8BC28C72BFF5EBB0054DA4D /* SentryTouchTracker.swift */; }; D8BC28CC2BFF78220054DA4D /* SentryRRWebTouchEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8BC28CB2BFF78220054DA4D /* SentryRRWebTouchEvent.swift */; }; @@ -996,7 +977,6 @@ D8BFE37929A76666002E73F3 /* SentryTimeToDisplayTrackerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8BFE37729A76519002E73F3 /* SentryTimeToDisplayTrackerTest.swift */; }; D8C66A362A77B1F70015696A /* SentryPropagationContext.h in Headers */ = {isa = PBXBuildFile; fileRef = D8C66A342A77B1F70015696A /* SentryPropagationContext.h */; }; D8C66A372A77B1F70015696A /* SentryPropagationContext.m in Sources */ = {isa = PBXBuildFile; fileRef = D8C66A352A77B1F70015696A /* SentryPropagationContext.m */; }; - D8C67E9B28000E24007E326E /* SentryUIApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = D8C67E9928000E23007E326E /* SentryUIApplication.h */; }; D8CAC02E2BA0663E00E38F34 /* SentryReplayOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8CAC02A2BA0663E00E38F34 /* SentryReplayOptions.swift */; }; D8CAC02F2BA0663E00E38F34 /* SentryVideoInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8CAC02B2BA0663E00E38F34 /* SentryVideoInfo.swift */; }; D8CB74152947246600A5F964 /* SentryEnvelopeAttachmentHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = D8CB74142947246600A5F964 /* SentryEnvelopeAttachmentHeader.h */; }; @@ -1005,7 +985,6 @@ D8CB741B2947286500A5F964 /* SentryEnvelopeItemHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = D8CB741A2947286500A5F964 /* SentryEnvelopeItemHeader.m */; }; D8CB742B294B1DD000A5F964 /* SentryUIApplicationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8CB742A294B1DD000A5F964 /* SentryUIApplicationTests.swift */; }; D8CB742E294B294B00A5F964 /* MockUIScene.m in Sources */ = {isa = PBXBuildFile; fileRef = D8CB742D294B294B00A5F964 /* MockUIScene.m */; }; - D8CCFC632A1520C900DE232E /* SentryBinaryImageCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D8CCFC622A1520C900DE232E /* SentryBinaryImageCacheTests.m */; }; D8CD158F2D39405900EFF8AB /* TestFramesTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841325DE2BFED0510029228F /* TestFramesTracker.swift */; }; D8CE69BC277E39C700C6EC5C /* SentryFileIOTrackingIntegrationObjCTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D8CE69BB277E39C700C6EC5C /* SentryFileIOTrackingIntegrationObjCTests.m */; }; D8DBE0CA2C0E093000FAB1FD /* SentryTouchTrackerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8DBE0C92C0E093000FAB1FD /* SentryTouchTrackerTests.swift */; }; @@ -1023,28 +1002,60 @@ F41362112E1C55AF00B84443 /* SentryScopePersistentStore+Tags.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41362102E1C55AF00B84443 /* SentryScopePersistentStore+Tags.swift */; }; F41362132E1C566100B84443 /* SentryScopePersistentStore+User.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41362122E1C566100B84443 /* SentryScopePersistentStore+User.swift */; }; F41362152E1C568400B84443 /* SentryScopePersistentStore+Context.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41362142E1C568400B84443 /* SentryScopePersistentStore+Context.swift */; }; + F443DB272E09BE8C009A9045 /* LoadValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F443DB262E09BE8C009A9045 /* LoadValidatorTests.swift */; }; F44858132E03579D0013E63B /* SentryCrashDynamicLinker+Test.h in Headers */ = {isa = PBXBuildFile; fileRef = F44858122E0357940013E63B /* SentryCrashDynamicLinker+Test.h */; }; + F451FAA62E0B304E0050ACF2 /* LoadValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F451FAA52E0B304E0050ACF2 /* LoadValidator.swift */; }; F452437E2DE60B71003E8F50 /* SentryUseNSExceptionCallstackWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = F452437D2DE60B71003E8F50 /* SentryUseNSExceptionCallstackWrapper.m */; }; F45243882DE65968003E8F50 /* ExceptionCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = F45243872DE65968003E8F50 /* ExceptionCatcher.m */; }; - F45243892DE65968003E8F50 /* ExceptionCatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = F45243872DE65968003E8F50 /* ExceptionCatcher.m */; }; F452438A2DE65968003E8F50 /* ExceptionCatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = F45243862DE65968003E8F50 /* ExceptionCatcher.h */; }; F452438C2DE65BC0003E8F50 /* SentryUseNSExceptionCallstackWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = F452438B2DE65BC0003E8F50 /* SentryUseNSExceptionCallstackWrapper.h */; }; F458D1132E180BB00028273E /* SentryFileManagerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = F458D1122E180BB00028273E /* SentryFileManagerProtocol.swift */; }; F458D1152E1869AD0028273E /* SentryScopePersistentStore+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = F458D1142E1869AD0028273E /* SentryScopePersistentStore+String.swift */; }; - F46DA6C32E1DBCA000DF6E3B /* SentryScopePersistentStore+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46DA6C22E1DBCA000DF6E3B /* SentryScopePersistentStore+Helper.swift */; }; F458D1172E186DF20028273E /* SentryScopePersistentStore+Fingerprint.swift in Sources */ = {isa = PBXBuildFile; fileRef = F458D1162E186DF20028273E /* SentryScopePersistentStore+Fingerprint.swift */; }; F458D1192E186E000028273E /* SentryScopePersistentStore+Extras.swift in Sources */ = {isa = PBXBuildFile; fileRef = F458D1182E186E000028273E /* SentryScopePersistentStore+Extras.swift */; }; + F46DA6C32E1DBCA000DF6E3B /* SentryScopePersistentStore+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46DA6C22E1DBCA000DF6E3B /* SentryScopePersistentStore+Helper.swift */; }; + F46E0BA82E6A19F900DAA75C /* SentryCrashWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46E0BA72E6A19F900DAA75C /* SentryCrashWrapperTests.swift */; }; + F48E2E0A2E6637840073CB22 /* TestSentryCrashWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48E2E092E6637840073CB22 /* TestSentryCrashWrapper.swift */; }; + F48F74F32E5F9959009D4E7D /* SentryCrashBinaryImageCacheTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F48F74F22E5F9959009D4E7D /* SentryCrashBinaryImageCacheTests.m */; }; + F48F75712E5FA630009D4E7D /* SentryBinaryImageCacheCallbacks.m in Sources */ = {isa = PBXBuildFile; fileRef = F48F75702E5FA630009D4E7D /* SentryBinaryImageCacheCallbacks.m */; }; + F48F75732E5FA649009D4E7D /* SentryBinaryImageCacheCallbacks.h in Headers */ = {isa = PBXBuildFile; fileRef = F48F75722E5FA649009D4E7D /* SentryBinaryImageCacheCallbacks.h */; }; + F48F767C2E60B555009D4E7D /* SentryNSTimerFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = F48F767B2E60B555009D4E7D /* SentryNSTimerFactory.swift */; }; + F49236EB2E5E4B2F00663673 /* SentryBinaryImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49236EA2E5E4B2F00663673 /* SentryBinaryImageCache.swift */; }; F49D41982DEA27AF00D9244E /* SentryUseNSExceptionCallstackWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49D41972DEA27AF00D9244E /* SentryUseNSExceptionCallstackWrapperTests.swift */; }; F49D419A2DEA2FB000D9244E /* SentryCrashExceptionApplicationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49D41992DEA2FB000D9244E /* SentryCrashExceptionApplicationTests.swift */; }; F49D419C2DEA30C300D9244E /* SentryCrashExceptionApplicationHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = F49D419B2DEA30B800D9244E /* SentryCrashExceptionApplicationHelper.h */; }; F49D419E2DEA3D0600D9244E /* SentryCrashExceptionApplicationHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = F49D419D2DEA3D0300D9244E /* SentryCrashExceptionApplicationHelper.m */; }; + F4A930232E65FDBF006DA6EF /* SentryMobileProvisionParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A930222E65FDAF006DA6EF /* SentryMobileProvisionParser.swift */; }; + F4A930252E661856006DA6EF /* SentryMobileProvisionParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A930242E661856006DA6EF /* SentryMobileProvisionParserTests.swift */; }; F4AACD612E01ACE800DDDD1E /* SentryCrashDynamicLinkerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4AACD602E01ACE800DDDD1E /* SentryCrashDynamicLinkerTests.m */; }; + F4DC35562E1FFD620077CE89 /* SentryVideoFrameProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DC35552E1FFD610077CE89 /* SentryVideoFrameProcessor.swift */; }; + F4DC35582E1FFE1F0077CE89 /* SentryVideoFrameProcessorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DC35572E1FFE1B0077CE89 /* SentryVideoFrameProcessorTests.swift */; }; + F4DCC9DD2E4AA9D0008ECE45 /* SentrySDKSettingsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DCC9DC2E4AA9D0008ECE45 /* SentrySDKSettingsTests.swift */; }; + F4DCC9E52E4AACE0008ECE45 /* SentrySDKSettings+Equality.m in Sources */ = {isa = PBXBuildFile; fileRef = F4DCC9E42E4AACE0008ECE45 /* SentrySDKSettings+Equality.m */; }; F4E3DCCB2E1579240093CB80 /* SentryScopePersistentStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E3DCCA2E1579240093CB80 /* SentryScopePersistentStore.swift */; }; + F4FE9DBD2E621F100014FED5 /* SentryRandom.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FE9DBC2E621F100014FED5 /* SentryRandom.swift */; }; + F4FE9DFD2E622CD70014FED5 /* SentryDefaultObjCRuntimeWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FE9DFB2E622CD70014FED5 /* SentryDefaultObjCRuntimeWrapper.swift */; }; + F4FE9DFE2E622CD70014FED5 /* SentryObjCRuntimeWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FE9DFC2E622CD70014FED5 /* SentryObjCRuntimeWrapper.swift */; }; + F4FE9E082E6248E40014FED5 /* SentryCrashWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FE9E072E6248E40014FED5 /* SentryCrashWrapper.swift */; }; + FA01BCB22E69352A00968DFA /* SentryDiscardedEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA01BCB12E69352A00968DFA /* SentryDiscardedEvent.swift */; }; FA034AC82DD3DB4900FE3107 /* SentryIntegrationProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = FA034AC72DD3DB4900FE3107 /* SentryIntegrationProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; - FA3734822E0EEA670091EF24 /* SentryScreenshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA3734812E0EEA670091EF24 /* SentryScreenshot.swift */; }; + FA1841832E4B457F005DEDC7 /* SentryApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA18417D2E4B457B005DEDC7 /* SentryApplication.swift */; }; + FA21A2EF2E60E9CB00E7EADB /* EnvelopeComparison.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA21A2E92E60E9C700E7EADB /* EnvelopeComparison.swift */; }; + FA21F0B42E4A2A80008B4E5A /* SentryAppState.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA4C32972DF7513F001D7B01 /* SentryAppState.swift */; }; + FA34C1A32E692A5000BC52AA /* SentryEnvelopeItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA34C1A22E692A5000BC52AA /* SentryEnvelopeItem.swift */; }; FA3734842E0F086C0091EF24 /* SentryDependencyContainerSwiftHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = FA3734832E0F07A20091EF24 /* SentryDependencyContainerSwiftHelper.h */; }; FA3734862E0F09320091EF24 /* SentryDependencyContainerSwiftHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3734852E0F092F0091EF24 /* SentryDependencyContainerSwiftHelper.m */; }; + FA3854362E267DA60045A563 /* SentryUser+Serialize.h in Headers */ = {isa = PBXBuildFile; fileRef = FA3854352E267DA20045A563 /* SentryUser+Serialize.h */; }; + FA3A42722E1C5F9B00A08C39 /* SentryNSNotificationCenterWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA3A42712E1C5F9B00A08C39 /* SentryNSNotificationCenterWrapper.swift */; }; + FA3AEE782E68E2830092283E /* SentryEnvelopeHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA3AEE772E68E2830092283E /* SentryEnvelopeHeader.swift */; }; + FA458CC32E691A730061B13D /* SentryProcessInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA458CBD2E691A6E0061B13D /* SentryProcessInfo.swift */; }; FA4C32972DF7513F001D7B00 /* SentryExperimentalOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA4C32962DF7513F001D7B00 /* SentryExperimentalOptions.swift */; }; + FA6555142E30181B009917BC /* SentrySDKInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = FA6555132E30181B009917BC /* SentrySDKInternal.h */; }; + FA6555162E30182B009917BC /* SentrySDKInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = FA6555152E30182B009917BC /* SentrySDKInternal.m */; }; + FA65551A2E3018A3009917BC /* SentrySDKTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA6555192E30189E009917BC /* SentrySDKTests.swift */; }; + FA66143A2E4B593900657755 /* SentryApplicationExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA6614392E4B593000657755 /* SentryApplicationExtensions.swift */; }; + FA6614FC2E4B8E1A00657755 /* TestSentryUIApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA6614FB2E4B8E1500657755 /* TestSentryUIApplication.swift */; }; + FA6615052E4BA4D700657755 /* ThreadSafeApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA6615042E4BA4D200657755 /* ThreadSafeApplication.swift */; }; FA67DCC12DDBD4C800896B02 /* SentrySDKLog+Configure.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCC02DDBD4C800896B02 /* SentrySDKLog+Configure.swift */; }; FA67DCF52DDBD4EA00896B02 /* SentryCurrentDateProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCCA2DDBD4EA00896B02 /* SentryCurrentDateProvider.swift */; }; FA67DCF62DDBD4EA00896B02 /* SentryViewRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCE52DDBD4EA00896B02 /* SentryViewRenderer.swift */; }; @@ -1083,17 +1094,38 @@ FA67DD182DDBD4EA00896B02 /* UIImageHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCED2DDBD4EA00896B02 /* UIImageHelper.swift */; }; FA67DD192DDBD4EA00896B02 /* SwizzleClassNameExclude.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA67DCD52DDBD4EA00896B02 /* SwizzleClassNameExclude.swift */; }; FA6FC0A32E0B5ACE00ED2669 /* SentrySdkPackage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA6FC0A22E0B5AC800ED2669 /* SentrySdkPackage.swift */; }; + FA6FC0AA2E0B6B1100ED2669 /* SentrySdkInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA6FC0A92E0B6B0E00ED2669 /* SentrySdkInfo.swift */; }; FA7206DF2E0B37850072FDD4 /* SentryProfileCollector.h in Headers */ = {isa = PBXBuildFile; fileRef = FA7206DE2E0B37780072FDD4 /* SentryProfileCollector.h */; }; FA7206E12E0B37C80072FDD4 /* SentryProfileCollector.mm in Sources */ = {isa = PBXBuildFile; fileRef = FA7206E02E0B37C60072FDD4 /* SentryProfileCollector.mm */; }; FA8A36182DEAA1EB0058D883 /* SentryThread+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = FA8A36172DEAA1EB0058D883 /* SentryThread+Private.h */; }; FA8E58F12E0AD4270049F69D /* SentryDispatchQueueWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA8E58F02E0AD4220049F69D /* SentryDispatchQueueWrapper.swift */; }; FA90FAA82E06614E008CAAE8 /* SentryExtraPackages.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA90FAA72E06614B008CAAE8 /* SentryExtraPackages.swift */; }; FA90FAFD2E070A3B008CAAE8 /* SentryURLRequestFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA90FAFC2E070A3B008CAAE8 /* SentryURLRequestFactory.swift */; }; + FA94E6912E6B92C100576666 /* SentryClientReport.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA94E68B2E6B92BE00576666 /* SentryClientReport.swift */; }; + FA94E6B22E6D265800576666 /* SentryEnvelope.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA94E6B12E6D265500576666 /* SentryEnvelope.swift */; }; + FA94E71C2E6F26C500576666 /* SentrySerialization+ReplayRecording.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA94E71B2E6F26BF00576666 /* SentrySerialization+ReplayRecording.swift */; }; + FA94E7242E6F339400576666 /* SentryEnvelopeItemType.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA94E7232E6F32FA00576666 /* SentryEnvelopeItemType.swift */; }; + FAAB29F12E3D252300ACD577 /* SentrySession.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB29F02E3D252000ACD577 /* SentrySession.swift */; }; + FAAB2EE02E4BE97500FE8B7E /* TestSentryNSApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB2EDF2E4BE96F00FE8B7E /* TestSentryNSApplication.swift */; }; + FAAB2F972E4D345800FE8B7E /* SentryUIDeviceWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB2F962E4D344F00FE8B7E /* SentryUIDeviceWrapper.swift */; }; + FAAB30F32E4E8F2C00FE8B7E /* SentryInAppLogic.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB30F22E4E8F2C00FE8B7E /* SentryInAppLogic.swift */; }; FAB359982E05D7E90083D5E3 /* SentryEventSwiftHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = FAB359972E05D7E90083D5E3 /* SentryEventSwiftHelper.h */; }; FAB3599A2E05D8080083D5E3 /* SentryEventSwiftHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = FAB359992E05D8080083D5E3 /* SentryEventSwiftHelper.m */; }; + FAB7BBA92E2577A6007301E1 /* SentryModels+Serializable.h in Headers */ = {isa = PBXBuildFile; fileRef = FAB7BBA82E2577A2007301E1 /* SentryModels+Serializable.h */; }; + FABB48B32E59310D0071397E /* SentryMeasurementValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = FABB48B12E59310D0071397E /* SentryMeasurementValue.swift */; }; + FABE8E152E307A5E0040809A /* SentrySDK.swift in Sources */ = {isa = PBXBuildFile; fileRef = FABE8E142E307A5C0040809A /* SentrySDK.swift */; }; + FABE8E172E307A7F0040809A /* Dependencies.swift in Sources */ = {isa = PBXBuildFile; fileRef = FABE8E162E307A7C0040809A /* Dependencies.swift */; }; FAC62B652E15A4100003909D /* SentrySDKThreadTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC62B642E15A40C0003909D /* SentrySDKThreadTests.swift */; }; + FAC735232E25AA81006C5A64 /* SentryProfilingSwiftHelpersTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FAC735222E25AA7A006C5A64 /* SentryProfilingSwiftHelpersTests.m */; }; + FACEED132E3179A10007B4AC /* SentyOptionsInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = FACEED122E3179A10007B4AC /* SentyOptionsInternal.m */; }; + FAE2DAB82E1F317900262307 /* SentryProfilingSwiftHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = FAE2DAB72E1F317900262307 /* SentryProfilingSwiftHelpers.m */; }; + FAE2DABA2E1F318900262307 /* SentryProfilingSwiftHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE2DAB92E1F318900262307 /* SentryProfilingSwiftHelpers.h */; }; + FAE80C242E4695B40010A595 /* SentryEvent+Serialize.h in Headers */ = {isa = PBXBuildFile; fileRef = FAE80C232E4695AE0010A595 /* SentryEvent+Serialize.h */; }; FAEC270E2DF3526000878871 /* SentryUserFeedback.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAEC270D2DF3526000878871 /* SentryUserFeedback.swift */; }; FAEC273D2DF3933A00878871 /* NSData+Unzip.m in Sources */ = {isa = PBXBuildFile; fileRef = FAEC273C2DF3933200878871 /* NSData+Unzip.m */; }; + FAEFA12F2E4FAE1900C431D9 /* SentrySDKSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAEFA1292E4FAE1700C431D9 /* SentrySDKSettings.swift */; }; + FAF120182E70C08F006E1DA3 /* SentryEnvelopeHeaderHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = FAF120122E70C088006E1DA3 /* SentryEnvelopeHeaderHelper.h */; }; + FAF1201A2E70C0EE006E1DA3 /* SentryEnvelopeHeaderHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = FAF120192E70C0EA006E1DA3 /* SentryEnvelopeHeaderHelper.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1111,6 +1143,41 @@ remoteGlobalIDString = 63AA759A1EB8AEF500D153DE; remoteInfo = "Sentry-iOS"; }; + 846D3F262E286ECF00D4E7E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 846D3F102E286ECF00D4E7E3 /* DuplicatedSDKTest.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D8C030CE2CEF633A007FC5B4; + remoteInfo = DuplicatedSDKTest; + }; + 846D3F282E286ECF00D4E7E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 846D3F102E286ECF00D4E7E3 /* DuplicatedSDKTest.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D89DD6362CEF650A009C3509; + remoteInfo = ModuleA; + }; + 846D3F2A2E286ECF00D4E7E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 846D3F102E286ECF00D4E7E3 /* DuplicatedSDKTest.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D89DD6482CEF6516009C3509; + remoteInfo = ModuleB; + }; + 846D3F2C2E286ECF00D4E7E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 846D3F102E286ECF00D4E7E3 /* DuplicatedSDKTest.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = D89DD6732CEF7ADF009C3509; + remoteInfo = "UITest-DuplicatedSDK"; + }; + 846D3F2E2E286ECF00D4E7E3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 846D3F102E286ECF00D4E7E3 /* DuplicatedSDKTest.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = F45243122DE56862003E8F50; + remoteInfo = "Unit Tests"; + }; 84B7FA3729B2860500AD93B1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 6327C5CA1EB8A783004E799B /* Project object */; @@ -1222,8 +1289,6 @@ 0A9E917028DC7E7000FB4182 /* SentryInternalCDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryInternalCDefines.h; path = include/SentryInternalCDefines.h; sourceTree = ""; }; 0AAE201D28ED9B9400D0CD80 /* SentryReachability.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryReachability.m; sourceTree = ""; }; 0AAE202028ED9BCC00D0CD80 /* SentryReachability.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryReachability.h; path = include/SentryReachability.h; sourceTree = ""; }; - 0ADC33EB28D9BB780078D980 /* SentryUIDeviceWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryUIDeviceWrapper.m; sourceTree = ""; }; - 0ADC33ED28D9BB890078D980 /* SentryUIDeviceWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryUIDeviceWrapper.h; path = include/SentryUIDeviceWrapper.h; sourceTree = ""; }; 0ADC33EF28D9BE690078D980 /* TestSentryUIDeviceWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryUIDeviceWrapper.swift; sourceTree = ""; }; 0AE455AC28F584D2006680E5 /* SentryReachabilityTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryReachabilityTests.m; sourceTree = ""; }; 15360CCE2432777400112302 /* SentrySessionTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentrySessionTracker.m; sourceTree = ""; }; @@ -1233,12 +1298,10 @@ 15360CEC2433A15500112302 /* SentryInstallation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryInstallation.m; sourceTree = ""; }; 15360CEF2433A16D00112302 /* SentryInstallation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryInstallation.h; path = include/SentryInstallation.h; sourceTree = ""; }; 15D0AC872459EE4D006541C2 /* SentryNSURLRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSURLRequestTests.swift; sourceTree = ""; }; - 15E0A8E0240C41CE00F044E3 /* SentryEnvelope.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryEnvelope.h; path = include/HybridPublic/SentryEnvelope.h; sourceTree = ""; }; - 15E0A8E4240C457D00F044E3 /* SentryEnvelope.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryEnvelope.m; sourceTree = ""; }; 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 = ""; }; 15E0A8EF240F638200F044E3 /* SentrySerializationNilTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySerializationNilTests.m; sourceTree = ""; }; - 15E0A8F12411A45A00F044E3 /* SentrySession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentrySession.m; sourceTree = ""; }; + 15E0A8F12411A45A00F044E3 /* SentrySessionInternal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentrySessionInternal.m; sourceTree = ""; }; 33042A0B29DAF5F400C60085 /* SentryExtraContextProvider.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryExtraContextProvider.h; sourceTree = ""; }; 33042A0C29DAF79A00C60085 /* SentryExtraContextProvider.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryExtraContextProvider.m; sourceTree = ""; }; 33042A1629DC2C4300C60085 /* SentryExtraContextProviderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryExtraContextProviderTests.swift; sourceTree = ""; }; @@ -1259,6 +1322,7 @@ 621F61F02BEA073A005E654F /* SentryEnabledFeaturesBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryEnabledFeaturesBuilder.swift; sourceTree = ""; }; 62212B862D520CB00062C2FA /* SentryEventCodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryEventCodable.swift; sourceTree = ""; }; 62277BBB2DA5183500EF06B7 /* SentryTracer+Test.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SentryTracer+Test.m"; sourceTree = ""; }; + 62278CA72E30B21A0022ABC6 /* SentryHttpTransportFlushIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryHttpTransportFlushIntegrationTests.swift; sourceTree = ""; }; 622C08D929E554B9002571D4 /* SentrySpanContext+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentrySpanContext+Private.h"; path = "include/SentrySpanContext+Private.h"; sourceTree = ""; }; 62375FB82B47F9F000CC55F1 /* SentryDependencyContainerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryDependencyContainerTests.swift; sourceTree = ""; }; 623C45AE2A651C4500D9E88B /* SentryCoreDataTracker+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryCoreDataTracker+Test.h"; sourceTree = ""; }; @@ -1421,11 +1485,11 @@ 63FE6FF920DA4C1000CDBAE8 /* SentryCrashMonitor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashMonitor.c; sourceTree = ""; }; 63FE6FFB20DA4C1000CDBAE8 /* SentryCrashMonitor_MachException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMonitor_MachException.h; sourceTree = ""; }; 63FE6FFC20DA4C1000CDBAE8 /* SentryCrashMonitor_NSException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMonitor_NSException.h; sourceTree = ""; }; - 63FE6FFD20DA4C1000CDBAE8 /* SentryCrashMonitor_AppState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMonitor_AppState.h; sourceTree = ""; }; - 63FE6FFE20DA4C1000CDBAE8 /* SentryCrashMonitorType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMonitorType.h; sourceTree = ""; }; + 63FE6FFD20DA4C1000CDBAE8 /* SentryCrashMonitor_AppState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashMonitor_AppState.h; path = ../../../Sentry/include/SentryCrashMonitor_AppState.h; sourceTree = ""; }; + 63FE6FFE20DA4C1000CDBAE8 /* SentryCrashMonitorType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashMonitorType.h; path = ../../../Sentry/include/SentryCrashMonitorType.h; sourceTree = ""; }; 63FE6FFF20DA4C1000CDBAE8 /* SentryCrashMonitor_Signal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashMonitor_Signal.c; sourceTree = ""; }; - 63FE700020DA4C1000CDBAE8 /* SentryCrashMonitor_System.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMonitor_System.h; sourceTree = ""; }; - 63FE700220DA4C1000CDBAE8 /* SentryCrashMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMonitor.h; sourceTree = ""; }; + 63FE700020DA4C1000CDBAE8 /* SentryCrashMonitor_System.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashMonitor_System.h; path = ../../../Sentry/include/SentryCrashMonitor_System.h; sourceTree = ""; }; + 63FE700220DA4C1000CDBAE8 /* SentryCrashMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashMonitor.h; path = ../../../Sentry/include/SentryCrashMonitor.h; sourceTree = ""; }; 63FE700420DA4C1000CDBAE8 /* SentryCrashCachedData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashCachedData.c; sourceTree = ""; }; 63FE700720DA4C1000CDBAE8 /* SentryCrashDate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashDate.h; sourceTree = ""; }; 63FE700820DA4C1000CDBAE8 /* SentryCrashMachineContext_Apple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMachineContext_Apple.h; sourceTree = ""; }; @@ -1465,15 +1529,15 @@ 63FE702C20DA4C1000CDBAE8 /* SentryCrashString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashString.h; sourceTree = ""; }; 63FE702D20DA4C1000CDBAE8 /* SentryCrashJSONCodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashJSONCodec.h; sourceTree = ""; }; 63FE702E20DA4C1000CDBAE8 /* SentryCrashNSErrorUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashNSErrorUtil.h; sourceTree = ""; }; - 63FE702F20DA4C1000CDBAE8 /* SentryCrashDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashDebug.h; sourceTree = ""; }; + 63FE702F20DA4C1000CDBAE8 /* SentryCrashDebug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashDebug.h; path = ../../../Sentry/include/SentryCrashDebug.h; sourceTree = ""; }; 63FE703020DA4C1000CDBAE8 /* SentryCrashObjCApple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashObjCApple.h; sourceTree = ""; }; 63FE703120DA4C1000CDBAE8 /* SentryCrashStackCursor_MachineContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashStackCursor_MachineContext.h; sourceTree = ""; }; - 63FE703220DA4C1000CDBAE8 /* SentryCrashThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashThread.h; sourceTree = ""; }; + 63FE703220DA4C1000CDBAE8 /* SentryCrashThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashThread.h; path = ../../../Sentry/include/SentryCrashThread.h; sourceTree = ""; }; 63FE703320DA4C1000CDBAE8 /* SentryCrashCPU_x86_32.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashCPU_x86_32.c; sourceTree = ""; }; 63FE703420DA4C1000CDBAE8 /* SentryCrashSignalInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashSignalInfo.h; sourceTree = ""; }; 63FE703520DA4C1000CDBAE8 /* SentryCrashSymbolicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashSymbolicator.h; sourceTree = ""; }; 63FE703620DA4C1000CDBAE8 /* SentryCrashID.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashID.c; sourceTree = ""; }; - 63FE703820DA4C1000CDBAE8 /* SentryCrashDynamicLinker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashDynamicLinker.h; sourceTree = ""; }; + 63FE703820DA4C1000CDBAE8 /* SentryCrashDynamicLinker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashDynamicLinker.h; path = ../../../Sentry/include/SentryCrashDynamicLinker.h; sourceTree = ""; }; 63FE703920DA4C1000CDBAE8 /* SentryCrashMemory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMemory.h; sourceTree = ""; }; 63FE703A20DA4C1000CDBAE8 /* SentryCrashCPU.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashCPU.c; sourceTree = ""; }; 63FE703B20DA4C1000CDBAE8 /* SentryCrashStackCursor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashStackCursor.c; sourceTree = ""; }; @@ -1482,7 +1546,7 @@ 63FE703E20DA4C1000CDBAE8 /* SentryCrashCPU_Apple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashCPU_Apple.h; sourceTree = ""; }; 63FE704020DA4C1000CDBAE8 /* SentryCrashC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashC.c; sourceTree = ""; }; 63FE704120DA4C1000CDBAE8 /* SentryCrash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrash.m; sourceTree = ""; }; - 63FE704220DA4C1000CDBAE8 /* SentryCrashReportWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashReportWriter.h; sourceTree = ""; }; + 63FE704220DA4C1000CDBAE8 /* SentryCrashReportWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashReportWriter.h; path = ../../Sentry/include/SentryCrashReportWriter.h; sourceTree = ""; }; 63FE704320DA4C1000CDBAE8 /* SentryCrashReportStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashReportStore.h; sourceTree = ""; }; 63FE704420DA4C1000CDBAE8 /* SentryCrashReport.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashReport.c; sourceTree = ""; }; 63FE704520DA4C1000CDBAE8 /* SentryCrashCachedData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashCachedData.h; sourceTree = ""; }; @@ -1491,7 +1555,7 @@ 63FE704820DA4C1000CDBAE8 /* SentryCrashReportFixer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashReportFixer.h; sourceTree = ""; }; 63FE704920DA4C1000CDBAE8 /* SentryCrashC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashC.h; sourceTree = ""; }; 63FE704A20DA4C1000CDBAE8 /* SentryCrashReportVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashReportVersion.h; sourceTree = ""; }; - 63FE704B20DA4C1000CDBAE8 /* SentryCrash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrash.h; sourceTree = ""; }; + 63FE704B20DA4C1000CDBAE8 /* SentryCrash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrash.h; path = ../../Sentry/include/SentryCrash.h; sourceTree = ""; }; 63FE704C20DA4C1000CDBAE8 /* SentryCrashReport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashReport.h; sourceTree = ""; }; 63FE704D20DA4C1000CDBAE8 /* SentryCrashReportStore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashReportStore.c; sourceTree = ""; }; 63FE705C20DA4C1000CDBAE8 /* SentryCrashInstallation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashInstallation.m; sourceTree = ""; }; @@ -1525,7 +1589,7 @@ 63FE71FB20DA66EB00CDBAE8 /* SentryCrashMonitor_NSException_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashMonitor_NSException_Tests.m; sourceTree = ""; }; 63FE71FC20DA66EB00CDBAE8 /* SentryCrashFileUtils_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashFileUtils_Tests.m; sourceTree = ""; }; 69BEE6F62620729E006DF9DF /* UrlSessionDelegateSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UrlSessionDelegateSpy.swift; sourceTree = ""; }; - 71F11CDEF5952DF5CC69AC74 /* SentryCrashUUIDConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashUUIDConversion.h; sourceTree = ""; }; + 71F11CDEF5952DF5CC69AC74 /* SentryCrashUUIDConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashUUIDConversion.h; path = ../../../Sentry/include/SentryCrashUUIDConversion.h; sourceTree = ""; }; 7B0002312477F0520035FEF1 /* SentrySessionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySessionTests.m; sourceTree = ""; }; 7B0002332477F52D0035FEF1 /* SentrySessionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySessionTests.swift; sourceTree = ""; }; 7B01CE3C271993AB00B5AF31 /* SentryTransportFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryTransportFactoryTests.swift; sourceTree = ""; }; @@ -1547,16 +1611,14 @@ 7B14089724878F950035403D /* SentryCrashStackEntryMapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashStackEntryMapper.m; sourceTree = ""; }; 7B140899248791660035403D /* SentryCrashStackEntryMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashStackEntryMapperTests.swift; sourceTree = ""; }; 7B16FD012654F86B008177D3 /* SentrySysctlTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySysctlTests.swift; sourceTree = ""; }; - 7B18DE3F28D9F748004845C6 /* SentryNSNotificationCenterWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryNSNotificationCenterWrapper.h; path = include/SentryNSNotificationCenterWrapper.h; sourceTree = ""; }; - 7B18DE4128D9F794004845C6 /* SentryNSNotificationCenterWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryNSNotificationCenterWrapper.m; sourceTree = ""; }; + 7B18DE3F28D9F748004845C6 /* SentryNotificationNames.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryNotificationNames.h; path = include/SentryNotificationNames.h; sourceTree = ""; }; 7B18DE4328D9F8F6004845C6 /* TestNSNotificationCenterWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestNSNotificationCenterWrapper.swift; sourceTree = ""; }; - 7B18DE4928DA0C8B004845C6 /* SentryNSNotificationCenterWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSNotificationCenterWrapperTests.swift; sourceTree = ""; }; 7B26BBFA24C0A66D00A79CCC /* SentrySdkInfoNilTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySdkInfoNilTests.m; sourceTree = ""; }; 7B2A70D727D5F07F008B0D15 /* SentryANRTrackerV1Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryANRTrackerV1Tests.swift; sourceTree = ""; }; 7B2A70DA27D607CF008B0D15 /* SentryThreadWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryThreadWrapper.h; path = include/SentryThreadWrapper.h; sourceTree = ""; }; 7B2A70DC27D6083D008B0D15 /* SentryThreadWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryThreadWrapper.m; sourceTree = ""; }; 7B2A70DE27D60904008B0D15 /* SentryTestThreadWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryTestThreadWrapper.swift; sourceTree = ""; }; - 7B2BB0012966F55900A1E102 /* SentryOptions+HybridSDKs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryOptions+HybridSDKs.h"; path = "include/HybridPublic/SentryOptions+HybridSDKs.h"; sourceTree = ""; }; + 7B2BB0012966F55900A1E102 /* SentryOptionsInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryOptionsInternal.h; path = include/HybridPublic/SentryOptionsInternal.h; sourceTree = ""; }; 7B30B67B26527886006B2752 /* SentryDisplayLinkWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDisplayLinkWrapper.h; path = include/SentryDisplayLinkWrapper.h; sourceTree = ""; }; 7B30B67D26527894006B2752 /* SentryDisplayLinkWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SentryDisplayLinkWrapper.m; path = include/SentryDisplayLinkWrapper.m; sourceTree = ""; }; 7B30B67F26527C3C006B2752 /* SentryFramesTrackerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryFramesTrackerTests.swift; sourceTree = ""; }; @@ -1580,7 +1642,7 @@ 7B4E23B5251A07BD00060D68 /* SentryDispatchQueueWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryDispatchQueueWrapperTests.swift; sourceTree = ""; }; 7B4E23BD251A2BD500060D68 /* SentryCrashIntegrationSessionHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryCrashIntegrationSessionHandler.h; path = include/SentryCrashIntegrationSessionHandler.h; sourceTree = ""; }; 7B4E23C1251A2C2B00060D68 /* SentryCrashIntegrationSessionHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashIntegrationSessionHandler.m; sourceTree = ""; }; - 7B4E24FB251C97B400060D68 /* SentrySession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentrySession.h; path = include/SentrySession.h; sourceTree = ""; }; + 7B4E24FB251C97B400060D68 /* SentrySessionInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentrySessionInternal.h; path = include/SentrySessionInternal.h; sourceTree = ""; }; 7B4E375425822C4500059C93 /* SentryAttachment.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryAttachment.h; path = Public/SentryAttachment.h; sourceTree = ""; }; 7B4E375A2582313100059C93 /* SentryAttachmentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryAttachmentTests.swift; sourceTree = ""; }; 7B4E375E258231FC00059C93 /* SentryAttachment.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAttachment.m; sourceTree = ""; }; @@ -1597,7 +1659,6 @@ 7B5AB65C27E48E5200F1D1BA /* TestThreadInspector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestThreadInspector.swift; sourceTree = ""; }; 7B5B94322657A816002E474B /* SentryAppStartTrackingIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryAppStartTrackingIntegrationTests.swift; sourceTree = ""; }; 7B5B94342657AD21002E474B /* SentryFramesTrackingIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryFramesTrackingIntegrationTests.swift; sourceTree = ""; }; - 7B5CAF7027F5953400ED0DB6 /* SentryEnvelope+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryEnvelope+Private.h"; path = "include/SentryEnvelope+Private.h"; sourceTree = ""; }; 7B5CAF7427F5A67C00ED0DB6 /* SentryNSURLRequestBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryNSURLRequestBuilder.h; path = include/SentryNSURLRequestBuilder.h; sourceTree = ""; }; 7B5CAF7627F5A68C00ED0DB6 /* SentryNSURLRequestBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryNSURLRequestBuilder.m; sourceTree = ""; }; 7B5CAF7C27F5AD0600ED0DB6 /* TestNSURLRequestBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestNSURLRequestBuilder.h; sourceTree = ""; }; @@ -1632,8 +1693,6 @@ 7B72D23928D074BC0014798A /* TestExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestExtensions.swift; sourceTree = ""; }; 7B77BE3427EC8445003C9020 /* SentryDiscardReasonMapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDiscardReasonMapper.h; path = include/SentryDiscardReasonMapper.h; sourceTree = ""; }; 7B77BE3627EC8460003C9020 /* SentryDiscardReasonMapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDiscardReasonMapper.m; sourceTree = ""; }; - 7B7A30C524B48321005A4C6E /* SentryCrashWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryCrashWrapper.h; path = include/SentryCrashWrapper.h; sourceTree = ""; }; - 7B7A30C724B48389005A4C6E /* SentryCrashWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashWrapper.m; sourceTree = ""; }; 7B7A30C924B48523005A4C6E /* SentryHub+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryHub+Test.h"; sourceTree = ""; }; 7B7A599426B692540060A676 /* SentryScreenFrames.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryScreenFrames.h; path = include/HybridPublic/SentryScreenFrames.h; sourceTree = ""; }; 7B7A599626B692F00060A676 /* SentryScreenFrames.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryScreenFrames.m; sourceTree = ""; }; @@ -1656,14 +1715,12 @@ 7B8713B326415BAA006D6004 /* SentryAppStartTracker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAppStartTracker.m; sourceTree = ""; }; 7B87C915295ECFD700510C52 /* SentryMetricKitEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryMetricKitEventTests.swift; sourceTree = ""; }; 7B883F48253D714C00879E62 /* SentryCrashUUIDConversion.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SentryCrashUUIDConversion.c; sourceTree = ""; }; - 7B88F2FD24BC5A4C00ADF90A /* SentrySdkInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySdkInfo.h; path = include/SentrySdkInfo.h; sourceTree = ""; }; - 7B88F2FF24BC5A7D00ADF90A /* SentrySdkInfo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySdkInfo.m; sourceTree = ""; }; 7B88F30124BC5C6D00ADF90A /* SentrySdkInfoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySdkInfoTests.swift; sourceTree = ""; }; 7B88F30324BC8E6500ADF90A /* SentrySerializationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySerializationTests.swift; sourceTree = ""; }; 7B8CA85626DD4E6200DD872C /* SentryNetworkTrackerIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNetworkTrackerIntegrationTests.swift; sourceTree = ""; }; 7B8ECBF926498906005FE2EF /* SentryAppStateManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryAppStateManager.h; path = include/SentryAppStateManager.h; sourceTree = ""; }; 7B8ECBFB26498958005FE2EF /* SentryAppStateManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAppStateManager.m; sourceTree = ""; }; - 7B9421C4260CA393001F9349 /* SentrySDK+Tests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentrySDK+Tests.h"; sourceTree = ""; }; + 7B9421C4260CA393001F9349 /* SentrySDKInternal+Tests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentrySDKInternal+Tests.h"; sourceTree = ""; }; 7B944FAD2469B43700A10721 /* TestHub.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHub.swift; sourceTree = ""; }; 7B944FAF2469B46000A10721 /* TestClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestClient.swift; sourceTree = ""; }; 7B96571F26830C9100C66E25 /* SentryScopeSyncC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryScopeSyncC.h; path = include/SentryScopeSyncC.h; sourceTree = ""; }; @@ -1676,8 +1733,6 @@ 7B98D7CE25FB650F00C5A389 /* SentryWatchdogTerminationTrackingIntegration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryWatchdogTerminationTrackingIntegration.m; sourceTree = ""; }; 7B98D7D225FB65AE00C5A389 /* SentryWatchdogTerminationTracker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryWatchdogTerminationTracker.m; sourceTree = ""; }; 7B98D7DF25FB73B900C5A389 /* SentryWatchdogTerminationTrackerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryWatchdogTerminationTrackerTests.swift; sourceTree = ""; }; - 7B98D7E325FB7A7200C5A389 /* SentryAppState.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryAppState.h; path = include/SentryAppState.h; sourceTree = ""; }; - 7B98D7E725FB7BCD00C5A389 /* SentryAppState.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAppState.m; sourceTree = ""; }; 7B98D7EB25FB7C4900C5A389 /* SentryAppStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryAppStateTests.swift; sourceTree = ""; }; 7BA0C04528055F8E003E0326 /* SentryTransportAdapter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryTransportAdapter.h; path = include/SentryTransportAdapter.h; sourceTree = ""; }; 7BA0C0472805600A003E0326 /* SentryTransportAdapter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryTransportAdapter.m; sourceTree = ""; }; @@ -1699,7 +1754,7 @@ 7BA61CCB247D14E600C130A8 /* SentryThreadInspectorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryThreadInspectorTests.swift; sourceTree = ""; }; 7BA61CCE247EB59500C130A8 /* SentryCrashUUIDConversionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashUUIDConversionTests.swift; sourceTree = ""; }; 7BA61EA525F21E660008CAA2 /* SentrySDKLogTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySDKLogTests.swift; sourceTree = ""; }; - 7BA8409F24A1EC6E00B718AA /* SentrySDKTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySDKTests.swift; sourceTree = ""; }; + 7BA8409F24A1EC6E00B718AA /* SentrySDKInternalTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySDKInternalTests.swift; sourceTree = ""; }; 7BAF3DB4243C743E008A5414 /* SentryClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryClientTests.swift; sourceTree = ""; }; 7BAF3DB8243C9777008A5414 /* SentryTransport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryTransport.h; path = include/SentryTransport.h; sourceTree = ""; }; 7BAF3DC7243DB90E008A5414 /* TestTransport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestTransport.swift; sourceTree = ""; }; @@ -1712,8 +1767,6 @@ 7BB42EF024F3B7B700D7B39A /* SentrySession+Equality.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SentrySession+Equality.m"; sourceTree = ""; }; 7BB6550C253EEB3900887E87 /* SentryUserFeedbackTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUserFeedbackTests.swift; sourceTree = ""; }; 7BB7E7C629267A28004BF96B /* EmptyIntegration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyIntegration.swift; sourceTree = ""; }; - 7BBC826C25DFCFDE005F1ED8 /* SentryInAppLogic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryInAppLogic.h; path = include/SentryInAppLogic.h; sourceTree = ""; }; - 7BBC827025DFD039005F1ED8 /* SentryInAppLogic.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryInAppLogic.m; sourceTree = ""; }; 7BBC827825DFD7D7005F1ED8 /* SentryInAppLogicTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryInAppLogicTests.swift; sourceTree = ""; }; 7BBD1888244841EC00427C76 /* SentryHttpDateParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryHttpDateParser.h; path = include/SentryHttpDateParser.h; sourceTree = ""; }; 7BBD188A244841FB00427C76 /* SentryHttpDateParser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryHttpDateParser.m; sourceTree = ""; }; @@ -1746,11 +1799,8 @@ 7BC852322458802C005A70F0 /* SentryDataCategoryMapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDataCategoryMapper.h; path = include/SentryDataCategoryMapper.h; sourceTree = ""; }; 7BC85234245880AE005A70F0 /* SentryDataCategoryMapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDataCategoryMapper.m; sourceTree = ""; }; 7BC8523624588115005A70F0 /* SentryDataCategory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDataCategory.h; path = include/SentryDataCategory.h; sourceTree = ""; }; - 7BC852382458830A005A70F0 /* SentryEnvelopeItemType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryEnvelopeItemType.h; path = include/HybridPublic/SentryEnvelopeItemType.h; sourceTree = ""; }; 7BC8523A2458849E005A70F0 /* SentryDataCategoryMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryDataCategoryMapperTests.swift; sourceTree = ""; }; - 7BC9A1FF28F41016001E7C4C /* SentryMeasurementValue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryMeasurementValue.h; path = include/SentryMeasurementValue.h; sourceTree = ""; }; 7BC9A20128F41350001E7C4C /* SentryMeasurementUnit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryMeasurementUnit.h; path = Public/SentryMeasurementUnit.h; sourceTree = ""; }; - 7BC9A20328F4166D001E7C4C /* SentryMeasurementValue.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryMeasurementValue.m; sourceTree = ""; }; 7BC9A20528F41781001E7C4C /* SentryMeasurementUnit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryMeasurementUnit.m; sourceTree = ""; }; 7BC9CD4326A99F660047518E /* SentryUIViewControllerSwizzling+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryUIViewControllerSwizzling+Test.h"; sourceTree = ""; }; 7BCFA71427D0BAB7008C662C /* SentryANRTrackerV1.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryANRTrackerV1.h; path = include/SentryANRTrackerV1.h; sourceTree = ""; }; @@ -1761,10 +1811,6 @@ 7BD337E324A356180050DB6E /* SentryCrashIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashIntegrationTests.swift; sourceTree = ""; }; 7BD47B4C268F0B080076A663 /* ClearTestState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearTestState.swift; sourceTree = ""; }; 7BD4BD4027EB0F0C0071F4FF /* SentryDiscardReason.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDiscardReason.h; path = include/SentryDiscardReason.h; sourceTree = ""; }; - 7BD4BD4227EB29BA0071F4FF /* SentryClientReport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryClientReport.h; path = include/SentryClientReport.h; sourceTree = ""; }; - 7BD4BD4427EB29F50071F4FF /* SentryClientReport.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryClientReport.m; sourceTree = ""; }; - 7BD4BD4627EB2A3D0071F4FF /* SentryDiscardedEvent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDiscardedEvent.h; path = include/SentryDiscardedEvent.h; sourceTree = ""; }; - 7BD4BD4827EB2A5D0071F4FF /* SentryDiscardedEvent.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDiscardedEvent.m; sourceTree = ""; }; 7BD4BD4A27EB2DC20071F4FF /* SentryDiscardedEventTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryDiscardedEventTests.swift; sourceTree = ""; }; 7BD4BD4C27EB31820071F4FF /* SentryClientReportTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryClientReportTests.swift; sourceTree = ""; }; 7BD4E8E527FD84480086C410 /* TestFileManagerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestFileManagerDelegate.swift; sourceTree = ""; }; @@ -1786,7 +1832,6 @@ 7BE0DC28272A9E1C004FA8B7 /* SentryBreadcrumbTrackerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryBreadcrumbTrackerTests.swift; sourceTree = ""; }; 7BE0DC2E272ABAF6004FA8B7 /* SentryAutoBreadcrumbTrackingIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryAutoBreadcrumbTrackingIntegrationTests.swift; sourceTree = ""; }; 7BE0DC30272ABCEC004FA8B7 /* SentryAutoBreadcrumbTrackingIntegration+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryAutoBreadcrumbTrackingIntegration+Test.h"; sourceTree = ""; }; - 7BE1E32624F7AE08009D3AD0 /* SentrySession+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentrySession+Private.h"; path = "include/SentrySession+Private.h"; sourceTree = ""; }; 7BE1E33124F7E3B6009D3AD0 /* SentryMigrateSessionInit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryMigrateSessionInit.h; path = include/SentryMigrateSessionInit.h; sourceTree = ""; }; 7BE1E33324F7E3CB009D3AD0 /* SentryMigrateSessionInit.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryMigrateSessionInit.m; sourceTree = ""; }; 7BE2C7F625700093003B66C7 /* SentryTestIntegration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryTestIntegration.h; sourceTree = ""; }; @@ -1806,8 +1851,6 @@ 7BECF42126145C5D00D9826E /* SentryMechanismMeta.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryMechanismMeta.h; path = Public/SentryMechanismMeta.h; sourceTree = ""; }; 7BECF42726145CD900D9826E /* SentryMechanismMeta.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryMechanismMeta.m; sourceTree = ""; }; 7BECF431261463E600D9826E /* SentryMechanismMetaTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryMechanismMetaTests.swift; sourceTree = ""; }; - 7BED3574266F7BC600EAA70D /* TestSentryCrashWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestSentryCrashWrapper.h; sourceTree = ""; }; - 7BED3575266F7BFF00EAA70D /* TestSentryCrashWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TestSentryCrashWrapper.m; sourceTree = ""; }; 7BEF4956270C4B9D00F8F30E /* SentryUIViewControllerSwizzlingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUIViewControllerSwizzlingTests.swift; sourceTree = ""; }; 7BF536D024BDF3E7004FA6A2 /* SentryEnvelopeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryEnvelopeTests.swift; sourceTree = ""; }; 7BF536D324BEF255004FA6A2 /* SentryAssertions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryAssertions.swift; sourceTree = ""; }; @@ -1819,9 +1862,6 @@ 7BF9EF752722B34700B5BBEF /* SentrySubClassFinder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySubClassFinder.h; path = include/SentrySubClassFinder.h; sourceTree = ""; }; 7BF9EF772722B35D00B5BBEF /* SentrySubClassFinder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySubClassFinder.m; sourceTree = ""; }; 7BF9EF792722B58900B5BBEF /* SentrySubClassFinderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySubClassFinderTests.swift; sourceTree = ""; }; - 7BF9EF7B2722B90E00B5BBEF /* SentryDefaultObjCRuntimeWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDefaultObjCRuntimeWrapper.h; path = include/SentryDefaultObjCRuntimeWrapper.h; sourceTree = ""; }; - 7BF9EF7D2722B91F00B5BBEF /* SentryDefaultObjCRuntimeWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDefaultObjCRuntimeWrapper.m; sourceTree = ""; }; - 7BF9EF832722D07B00B5BBEF /* SentryObjCRuntimeWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryObjCRuntimeWrapper.h; path = include/SentryObjCRuntimeWrapper.h; sourceTree = ""; }; 7BF9EF852722D10600B5BBEF /* SentryTestObjCRuntimeWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryTestObjCRuntimeWrapper.h; sourceTree = ""; }; 7BF9EF872722D13000B5BBEF /* SentryTestObjCRuntimeWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryTestObjCRuntimeWrapper.m; sourceTree = ""; }; 7BF9EF892722D57100B5BBEF /* SentryInitializeForGettingSubclassesNotCalled.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryInitializeForGettingSubclassesNotCalled.h; sourceTree = ""; }; @@ -1837,8 +1877,6 @@ 7D0637022382B34300B30749 /* SentryScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryScope.h; path = Public/SentryScope.h; sourceTree = ""; }; 7D082B8023C628780029866B /* SentryMeta.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryMeta.m; sourceTree = ""; }; 7D0FCFB02379B915004DD83A /* SentryHub.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryHub.h; path = Public/SentryHub.h; sourceTree = ""; }; - 7D427C5F237B1D200046BAC8 /* SentrySDK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentrySDK.h; path = Public/SentrySDK.h; sourceTree = ""; }; - 7D5C4418237C2E1F00DAB0A3 /* SentrySDK.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentrySDK.m; sourceTree = ""; }; 7D5C4419237C2E1F00DAB0A3 /* SentryHub.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryHub.m; sourceTree = ""; }; 7D65260B237F649E00113EA2 /* SentryScope.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryScope.m; sourceTree = ""; }; 7D7F0A5E23DF3D2C00A4629C /* SentryGlobalEventProcessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryGlobalEventProcessor.h; path = include/SentryGlobalEventProcessor.h; sourceTree = ""; }; @@ -1906,14 +1944,10 @@ 844DA81D28246DAE00E6B62E /* develop-docs */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "develop-docs"; sourceTree = ""; }; 844DA81E28246DB900E6B62E /* fastlane */ = {isa = PBXFileReference; lastKnownFileType = folder; path = fastlane; sourceTree = ""; }; 844DA81F28246DE300E6B62E /* scripts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = scripts; sourceTree = ""; }; - 844EDC6D294143B900C86F34 /* SentryNSProcessInfoWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryNSProcessInfoWrapper.h; path = include/SentryNSProcessInfoWrapper.h; sourceTree = ""; }; - 844EDC6E294143B900C86F34 /* SentryNSProcessInfoWrapper.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryNSProcessInfoWrapper.mm; sourceTree = ""; }; 844EDC712941442200C86F34 /* TestSentryNSProcessInfoWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryNSProcessInfoWrapper.swift; sourceTree = ""; }; 844EDC74294144DB00C86F34 /* SentrySystemWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySystemWrapper.h; path = include/SentrySystemWrapper.h; sourceTree = ""; }; 844EDC75294144DB00C86F34 /* SentrySystemWrapper.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentrySystemWrapper.mm; sourceTree = ""; }; 844EDC7829415AB300C86F34 /* TestSentrySystemWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentrySystemWrapper.swift; sourceTree = ""; }; - 844EDCE32947DC3100C86F34 /* SentryNSTimerFactory.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryNSTimerFactory.h; path = include/SentryNSTimerFactory.h; sourceTree = ""; }; - 844EDCE42947DC3100C86F34 /* SentryNSTimerFactory.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryNSTimerFactory.m; sourceTree = ""; }; 844EDCE72947DCD700C86F34 /* TestSentryNSTimerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryNSTimerFactory.swift; sourceTree = ""; }; 844EDD6B2949387000C86F34 /* SentryMetricProfiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryMetricProfiler.h; path = Sources/Sentry/include/SentryMetricProfiler.h; sourceTree = SOURCE_ROOT; }; 8452E77D2DBC43CF0087020B /* Brewfile-ci-build */ = {isa = PBXFileReference; lastKnownFileType = text; path = "Brewfile-ci-build"; sourceTree = ""; }; @@ -1927,7 +1961,16 @@ 845CEAEE2D83F79500B6B325 /* SentryProfilingPublicAPITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryProfilingPublicAPITests.swift; sourceTree = ""; }; 845CEB162D8A979700B6B325 /* SentryAppStartProfilingConfigurationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryAppStartProfilingConfigurationTests.swift; sourceTree = ""; }; 846628B82DF0E52C00F11CD9 /* Brewfile-ci-format */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = "Brewfile-ci-format"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 846D3F092E286ECF00D4E7E3 /* DuplicatedSDKTest-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "DuplicatedSDKTest-Bridging-Header.h"; sourceTree = ""; }; + 846D3F0A2E286ECF00D4E7E3 /* DuplicatedSDKTestApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DuplicatedSDKTestApp.swift; sourceTree = ""; }; + 846D3F0B2E286ECF00D4E7E3 /* SomeWork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SomeWork.swift; sourceTree = ""; }; + 846D3F0C2E286ECF00D4E7E3 /* UITest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITest.swift; sourceTree = ""; }; + 846D3F0E2E286ECF00D4E7E3 /* Unit_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Unit_Tests.swift; sourceTree = ""; }; + 846D3F102E286ECF00D4E7E3 /* DuplicatedSDKTest.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = DuplicatedSDKTest.xcodeproj; sourceTree = ""; }; + 846D3F112E286ECF00D4E7E3 /* DuplicatedSDKTest.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = DuplicatedSDKTest.xctestplan; sourceTree = ""; }; 846F90332D56F59D009E86C1 /* Brewfile-ci-deploy */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = "Brewfile-ci-deploy"; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 848214B42E32B10900DF6998 /* SwiftUITestSample_Crash.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = SwiftUITestSample_Crash.xctestplan; sourceTree = ""; }; + 848214B52E32B10900DF6998 /* SwiftUITestSample_Envelope.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = SwiftUITestSample_Envelope.xctestplan; sourceTree = ""; }; 8482FA992DD7C397000E9283 /* SentryFeedbackAPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryFeedbackAPI.h; path = ../../../Sentry/Public/SentryFeedbackAPI.h; sourceTree = ""; }; 8482FA9A2DD7C397000E9283 /* SentryFeedbackAPI.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = SentryFeedbackAPI.m; path = ../../../Sentry/SentryFeedbackAPI.m; sourceTree = ""; }; 848A45172BBF8D33006AAAEC /* SentryContinuousProfiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryContinuousProfiler.h; path = ../include/SentryContinuousProfiler.h; sourceTree = ""; }; @@ -1953,6 +1996,10 @@ 84A8891A28DBD28900C51DFD /* SentryDevice.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDevice.h; path = include/SentryDevice.h; sourceTree = ""; }; 84A8891B28DBD28900C51DFD /* SentryDevice.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDevice.m; sourceTree = ""; }; 84A8892028DBD8D600C51DFD /* SentryDeviceTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDeviceTests.m; sourceTree = ""; }; + 84A898522E163072009A551E /* SentryProfileConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryProfileConfiguration.h; path = ../include/SentryProfileConfiguration.h; sourceTree = ""; }; + 84A898532E163072009A551E /* SentryProfileConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryProfileConfiguration.m; sourceTree = ""; }; + 84A898CD2E1DBDD1009A551E /* SentryAppStartProfilingConfigurationChangeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryAppStartProfilingConfigurationChangeTests.swift; sourceTree = ""; }; + 84A899342E218C5F009A551E /* CLAUDE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CLAUDE.md; sourceTree = ""; }; 84A903702D39F66F00690CE4 /* SentryUserFeedbackFormViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUserFeedbackFormViewModel.swift; sourceTree = ""; }; 84AB6AAF2DB2E9BA006D6C83 /* Versioning.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Versioning.xcconfig; sourceTree = ""; }; 84AC61D029F7541E009EEF61 /* SentryDispatchSourceWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDispatchSourceWrapper.h; path = include/SentryDispatchSourceWrapper.h; sourceTree = ""; }; @@ -1979,16 +2026,13 @@ 84EACEBC2C33CA7A009B8753 /* SentryWithoutUIKit.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = SentryWithoutUIKit.modulemap; path = Sources/Resources/SentryWithoutUIKit.modulemap; sourceTree = SOURCE_ROOT; }; 84EACEDF2C3DCAE2009B8753 /* DeploymentTargets.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DeploymentTargets.xcconfig; sourceTree = ""; }; 84EB21952BF01CEA00EDDA28 /* SentryCrashInstallationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashInstallationTests.swift; sourceTree = ""; }; - 84F2A1CD2E06001300A94524 /* SentryApplaunchProfilingMalformedConfigFileTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryApplaunchProfilingMalformedConfigFileTests.swift; sourceTree = ""; }; 84F994E52A6894B500EC0190 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/CoreData.framework; sourceTree = DEVELOPER_DIR; }; 84F994E72A6894BD00EC0190 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/SystemConfiguration.framework; sourceTree = DEVELOPER_DIR; }; - 861265F72404EC1500C4AFDE /* NSArray+SentrySanitize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "NSArray+SentrySanitize.h"; path = "include/NSArray+SentrySanitize.h"; sourceTree = ""; }; - 861265F82404EC1500C4AFDE /* NSArray+SentrySanitize.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSArray+SentrySanitize.m"; 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 = ""; }; 8E0551DF26A7A63C00400526 /* TestProtocolClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestProtocolClient.swift; sourceTree = ""; }; 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 = ""; }; - 8E25C95125F836D000DC215B /* SentryRandom.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryRandom.m; sourceTree = ""; }; - 8E25C95625F836EE00DC215B /* SentryRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryRandom.h; path = include/SentryRandom.h; sourceTree = ""; }; 8E25C97425F8511A00DC215B /* TestRandom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestRandom.swift; sourceTree = ""; }; 8E4A037725F6F52100000D77 /* SentrySampleDecision.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySampleDecision.h; path = Public/SentrySampleDecision.h; sourceTree = ""; }; 8E4A037D25F76A1D00000D77 /* Dynamic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dynamic.swift; sourceTree = ""; }; @@ -2039,15 +2083,23 @@ 8F73BC302B02B87E00C3CEF4 /* SentryInstallationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryInstallationTests.swift; sourceTree = ""; }; 8FF94DF22B06A24C00BCD650 /* SentryCrash+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryCrash+Test.h"; sourceTree = ""; }; 92136D662C9D765D002A9FB8 /* SentryNSURLRequestBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSURLRequestBuilderTests.swift; sourceTree = ""; }; + 92235CAB2E15369900865983 /* SentryLogBatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogBatcher.swift; sourceTree = ""; }; + 92235CAD2E15549C00865983 /* SentryLogger.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogger.swift; sourceTree = ""; }; + 92235CAF2E155B2600865983 /* SentryLoggerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLoggerTests.swift; sourceTree = ""; }; + 9264E1EA2E2E385B00B077CF /* SentryLogMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogMessage.swift; sourceTree = ""; }; + 9264E1EC2E2E397400B077CF /* SentryLogMessageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogMessageTests.swift; sourceTree = ""; }; 92672BB529C9A2A9006B021C /* SentryBreadcrumb+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SentryBreadcrumb+Private.h"; path = "include/HybridPublic/SentryBreadcrumb+Private.h"; sourceTree = ""; }; 927A5CC32DD7626400B82404 /* SentryEnvelopeItemHeaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryEnvelopeItemHeaderTests.swift; sourceTree = ""; }; + 928207C32E251B8F009285A4 /* SentryScope+PrivateSwift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryScope+PrivateSwift.h"; path = "include/SentryScope+PrivateSwift.h"; sourceTree = ""; }; 9286059429A5096600F96038 /* SentryGeo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryGeo.h; path = Public/SentryGeo.h; sourceTree = ""; }; 9286059629A5098900F96038 /* SentryGeo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryGeo.m; sourceTree = ""; }; 9286059829A50BAA00F96038 /* SentryGeoTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SentryGeoTests.swift; sourceTree = ""; }; + 928BED2A2E16977A00B4D398 /* SentryLogBatcherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogBatcherTests.swift; sourceTree = ""; }; 92B6BDA82E05B8F000D538B3 /* SentryLogLevelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogLevelTests.swift; sourceTree = ""; }; 92B6BDAC2E05B9F700D538B3 /* SentryLogTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogTests.swift; sourceTree = ""; }; 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 = ""; }; + 92EC54CD2E1EB54B00A10AC2 /* SentryClient+Logs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryClient+Logs.h"; path = "include/SentryClient+Logs.h"; sourceTree = ""; }; 92ECD73B2E05ACDE0063EC10 /* SentryLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLog.swift; sourceTree = ""; }; 92ECD73D2E05AD2B0063EC10 /* SentryLogLevel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogLevel.swift; sourceTree = ""; }; 92ECD73F2E05AD500063EC10 /* SentryLogAttribute.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLogAttribute.swift; sourceTree = ""; }; @@ -2063,9 +2115,6 @@ 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 = ""; }; D4009EB12D771BB90007AF30 /* SentryFileIOTrackerSwiftHelpersTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryFileIOTrackerSwiftHelpersTests.swift; sourceTree = ""; }; - D40604462DD2471600C40DC0 /* SentryNSApplication.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryNSApplication.m; sourceTree = ""; }; - D40604482DD2472600C40DC0 /* SentryNSApplication.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryNSApplication.h; path = include/SentryNSApplication.h; sourceTree = ""; }; - D406044A2DD2483D00C40DC0 /* SentryApplication.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryApplication.h; path = include/SentryApplication.h; sourceTree = ""; }; D41415A62DEEE532003B14D5 /* SentryRedactViewHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryRedactViewHelper.swift; sourceTree = ""; }; D41909922D48FFF6002B83D0 /* SentryNSDictionarySanitize+Tests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryNSDictionarySanitize+Tests.h"; sourceTree = ""; }; D41909942D490006002B83D0 /* SentryNSDictionarySanitize+Tests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SentryNSDictionarySanitize+Tests.m"; sourceTree = ""; }; @@ -2100,6 +2149,9 @@ D456B4312D706BDD007068CB /* SentrySpanOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySpanOperation.h; path = include/SentrySpanOperation.h; sourceTree = ""; }; D456B4352D706BEE007068CB /* SentryTraceOrigin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryTraceOrigin.h; path = include/SentryTraceOrigin.h; sourceTree = ""; }; D456B4372D706BFB007068CB /* SentrySpanDataKey.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySpanDataKey.h; path = include/SentrySpanDataKey.h; sourceTree = ""; }; + D45B4AF42E019E1500C31DFB /* TestSentryViewRenderer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryViewRenderer.swift; sourceTree = ""; }; + D45B4AF62E01A0FA00C31DFB /* TestSentryViewPhotographer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryViewPhotographer.swift; sourceTree = ""; }; + D45CE9742E5F454300BFEDB2 /* SentryScreenshotSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryScreenshotSource.swift; sourceTree = ""; }; D45E2D762E003EBF0072A6B7 /* TestRedactOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestRedactOptions.swift; sourceTree = ""; }; D467125D2DCCFF2500D4074A /* SentryReplayOptionsObjcTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryReplayOptionsObjcTests.m; sourceTree = ""; }; D46712612DCD059500D4074A /* SentryRedactDefaultOptionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryRedactDefaultOptionsTests.swift; sourceTree = ""; }; @@ -2114,6 +2166,7 @@ D48724E12D354D16005DE483 /* SentryTraceOriginTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryTraceOriginTests.swift; sourceTree = ""; }; D48E8B8A2D3E79610032E35E /* SentryTraceOrigin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryTraceOrigin.swift; sourceTree = ""; }; D48E8B9C2D3E82AC0032E35E /* SentrySpanOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySpanOperation.swift; sourceTree = ""; }; + D49064892DFAE1F600555785 /* SentryScreenshotOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryScreenshotOptions.swift; sourceTree = ""; }; D49480D22DC23E8E00A3B6E9 /* SentryReplayTypeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryReplayTypeTests.swift; sourceTree = ""; }; D49480D62DC23FE200A3B6E9 /* SentrySessionReplayDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySessionReplayDelegate.swift; sourceTree = ""; }; D4A2360A2D5F84FA00D55C58 /* SwiftUITestSample_Base.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = SwiftUITestSample_Base.xctestplan; sourceTree = ""; }; @@ -2123,13 +2176,19 @@ D4B0DC7E2DA9257200DE61B6 /* SentryRenderVideoResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryRenderVideoResult.swift; sourceTree = ""; }; D4BCA0C22DA93C25009E49AB /* SentrySessionReplayIntegration+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentrySessionReplayIntegration+Test.h"; sourceTree = ""; }; D4C5F5992D4249E0002A9BF6 /* DataSentryTracingIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataSentryTracingIntegrationTests.swift; sourceTree = ""; }; + D4CA34822E378C9000E92A61 /* SentryArrayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryArrayTests.swift; 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 = ""; }; D4CD2A7C2DE9F91900DA9F59 /* SentryRedactRegion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryRedactRegion.swift; sourceTree = ""; }; D4CD2A7D2DE9F91900DA9F59 /* SentryRedactRegionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryRedactRegionType.swift; sourceTree = ""; }; + D4D12E792DFC607F00DC45C4 /* SentryScreenshotOptionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryScreenshotOptionsTests.swift; sourceTree = ""; }; + D4DEE6582E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryProfileTimeseriesTests.m; sourceTree = ""; }; + D4ECA3FF2E3CBEDE00C757EA /* SentryDummyPrivateEmptyClass.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDummyPrivateEmptyClass.m; sourceTree = ""; }; + D4ECA4002E3CBEDE00C757EA /* SentryDummyPublicEmptyClass.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDummyPublicEmptyClass.m; sourceTree = ""; }; D4EDF9832D0B2A1D0071E7B3 /* Data+SentryTracing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Data+SentryTracing.swift"; sourceTree = ""; }; D4EE12D12DE9AC3300385BAF /* TestNSNotificationCenterWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestNSNotificationCenterWrapperTests.swift; sourceTree = ""; }; D4F2B5342D0C69D100649E42 /* SentryCrashCTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashCTests.swift; sourceTree = ""; }; + D4F7BD7C2E4373BB004A2D77 /* SentryLevelMapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryLevelMapperTests.swift; sourceTree = ""; }; D4FC68162DD632E7001B74FF /* SentryDispatchSourceProviderProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDispatchSourceProviderProtocol.h; path = include/SentryDispatchSourceProviderProtocol.h; sourceTree = ""; }; D4FC68192DD63465001B74FF /* SentryDispatchQueueWrapperTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDispatchQueueWrapperTests.m; sourceTree = ""; }; D801990F286B089000C277F0 /* SentryCrashReportSinkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashReportSinkTests.swift; sourceTree = ""; }; @@ -2158,7 +2217,7 @@ D8199DCF29376FF40074249E /* SentrySwiftUI.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SentrySwiftUI.xcconfig; sourceTree = ""; }; D8199DD029377C130074249E /* SentrySwiftUI.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; path = SentrySwiftUI.podspec; sourceTree = ""; }; D81A346B291AECC7005A27A9 /* PrivateSentrySDKOnly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PrivateSentrySDKOnly.h; path = include/HybridPublic/PrivateSentrySDKOnly.h; sourceTree = ""; }; - D81FDF10280EA0080045E0E4 /* SentryScreenShotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryScreenShotTests.swift; sourceTree = ""; }; + D81FDF10280EA0080045E0E4 /* SentryScreenshotSourceTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryScreenshotSourceTests.swift; sourceTree = ""; }; D820CDB52BB1895F00BA339D /* SentrySessionReplayIntegration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySessionReplayIntegration.h; path = include/HybridPublic/SentrySessionReplayIntegration.h; sourceTree = ""; }; D820CDB62BB1895F00BA339D /* SentrySessionReplayIntegration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySessionReplayIntegration.m; sourceTree = ""; }; D82859412C3E753C009A28AA /* SentrySessionReplaySyncC.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySessionReplaySyncC.h; path = include/SentrySessionReplaySyncC.h; sourceTree = ""; }; @@ -2192,9 +2251,6 @@ D855B3E727D652AF00BCED76 /* SentryCoreDataTrackingIntegrationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCoreDataTrackingIntegrationTest.swift; sourceTree = ""; }; D855B3E927D652C700BCED76 /* TestCoreDataStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestCoreDataStack.swift; sourceTree = ""; }; D85790282976A69F00C6AC1F /* TestDebugImageProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestDebugImageProvider.swift; sourceTree = ""; }; - D85852B827EDDC5900C6D8AE /* SentryUIApplication.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryUIApplication.m; sourceTree = ""; }; - D858FA642A29EAB3002A3503 /* SentryBinaryImageCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryBinaryImageCache.h; path = include/HybridPublic/SentryBinaryImageCache.h; sourceTree = ""; }; - D858FA652A29EAB3002A3503 /* SentryBinaryImageCache.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryBinaryImageCache.m; sourceTree = ""; }; D859696927BECD8F0036A46E /* SentryCoreDataTrackingIntegration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCoreDataTrackingIntegration.m; sourceTree = ""; }; D859696D27BECDA20036A46E /* SentryCoreDataTracker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCoreDataTracker.m; sourceTree = ""; }; D859697127BECDD20036A46E /* SentryCoreDataSwizzling.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCoreDataSwizzling.m; sourceTree = ""; }; @@ -2203,7 +2259,7 @@ D8603DD7284F894C000E1227 /* SentryBaggage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryBaggage.h; path = Public/SentryBaggage.h; sourceTree = ""; }; D86130112BB563FD004C0F5E /* SentrySessionReplayIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySessionReplayIntegrationTests.swift; sourceTree = ""; }; D861301B2BB5A267004C0F5E /* SentrySessionReplayTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySessionReplayTests.swift; sourceTree = ""; }; - D865892D29D6ECA7000BE151 /* SentryCrashBinaryImageCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryCrashBinaryImageCache.h; sourceTree = ""; }; + D865892D29D6ECA7000BE151 /* SentryCrashBinaryImageCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryCrashBinaryImageCache.h; path = ../../Sentry/include/SentryCrashBinaryImageCache.h; sourceTree = ""; }; D865892E29D6ECA7000BE151 /* SentryCrashBinaryImageCache.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SentryCrashBinaryImageCache.c; sourceTree = ""; }; D867063A27C3BC2400048851 /* SentryCoreDataTrackingIntegration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCoreDataTrackingIntegration.h; path = include/SentryCoreDataTrackingIntegration.h; sourceTree = ""; }; D867063B27C3BC2400048851 /* SentryCoreDataSwizzling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCoreDataSwizzling.h; path = include/SentryCoreDataSwizzling.h; sourceTree = ""; }; @@ -2253,12 +2309,11 @@ D8B665BA2B95F54200BD0E7B /* SentryPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryPrivate.h; path = include/SentryPrivate.h; sourceTree = ""; }; D8B665BB2B95F5A100BD0E7B /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = module.modulemap; path = Sources/Sentry/include/module.modulemap; sourceTree = SOURCE_ROOT; }; D8B76B042808060E000A58C4 /* SentryScreenshotIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryScreenshotIntegrationTests.swift; sourceTree = ""; }; - D8B76B0728081461000A58C4 /* TestSentryScreenShot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryScreenShot.swift; sourceTree = ""; }; + D8B76B0728081461000A58C4 /* TestSentryScreenshotProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryScreenshotProvider.swift; sourceTree = ""; }; D8BBD32628FD9FBF0011F850 /* SentrySwift.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentrySwift.h; path = include/SentrySwift.h; sourceTree = ""; }; D8BC28C72BFF5EBB0054DA4D /* SentryTouchTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryTouchTracker.swift; sourceTree = ""; }; D8BC28CB2BFF78220054DA4D /* SentryRRWebTouchEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryRRWebTouchEvent.swift; sourceTree = ""; }; D8BC28D42C00C6D30054DA4D /* StringExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensionsTests.swift; sourceTree = ""; }; - D8BC83BA2AFCF08C00A662B7 /* SentryUIApplication+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryUIApplication+Private.h"; sourceTree = ""; }; D8BD2E27292D1F7300D96C6A /* SDK.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SDK.xcconfig; sourceTree = ""; }; D8BD2E67293619F600D96C6A /* PrivatesHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PrivatesHeader.h; path = include/HybridPublic/PrivatesHeader.h; sourceTree = ""; }; D8BFE37029A3782F002E73F3 /* SentryTimeToDisplayTracker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryTimeToDisplayTracker.h; path = include/SentryTimeToDisplayTracker.h; sourceTree = ""; }; @@ -2266,7 +2321,6 @@ D8BFE37729A76519002E73F3 /* SentryTimeToDisplayTrackerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryTimeToDisplayTrackerTest.swift; sourceTree = ""; }; D8C66A342A77B1F70015696A /* SentryPropagationContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryPropagationContext.h; sourceTree = ""; }; D8C66A352A77B1F70015696A /* SentryPropagationContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryPropagationContext.m; sourceTree = ""; }; - D8C67E9928000E23007E326E /* SentryUIApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryUIApplication.h; path = include/SentryUIApplication.h; sourceTree = ""; }; D8CAC02A2BA0663E00E38F34 /* SentryReplayOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SentryReplayOptions.swift; sourceTree = ""; }; D8CAC02B2BA0663E00E38F34 /* SentryVideoInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SentryVideoInfo.swift; sourceTree = ""; }; D8CB74142947246600A5F964 /* SentryEnvelopeAttachmentHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryEnvelopeAttachmentHeader.h; path = include/SentryEnvelopeAttachmentHeader.h; sourceTree = ""; }; @@ -2276,7 +2330,6 @@ D8CB742A294B1DD000A5F964 /* SentryUIApplicationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUIApplicationTests.swift; sourceTree = ""; }; D8CB742C294B294B00A5F964 /* MockUIScene.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MockUIScene.h; sourceTree = ""; }; D8CB742D294B294B00A5F964 /* MockUIScene.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MockUIScene.m; sourceTree = ""; }; - D8CCFC622A1520C900DE232E /* SentryBinaryImageCacheTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryBinaryImageCacheTests.m; sourceTree = ""; }; D8CE69BB277E39C700C6EC5C /* SentryFileIOTrackingIntegrationObjCTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryFileIOTrackingIntegrationObjCTests.m; sourceTree = ""; }; D8DBE0C92C0E093000FAB1FD /* SentryTouchTrackerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryTouchTrackerTests.swift; sourceTree = ""; }; D8DBE0D12C0EFFC300FAB1FD /* SentryReplayOptionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryReplayOptionsTests.swift; sourceTree = ""; }; @@ -2295,27 +2348,61 @@ F41362102E1C55AF00B84443 /* SentryScopePersistentStore+Tags.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+Tags.swift"; sourceTree = ""; }; F41362122E1C566100B84443 /* SentryScopePersistentStore+User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+User.swift"; sourceTree = ""; }; F41362142E1C568400B84443 /* SentryScopePersistentStore+Context.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+Context.swift"; sourceTree = ""; }; + F443DB262E09BE8C009A9045 /* LoadValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadValidatorTests.swift; sourceTree = ""; }; F44858122E0357940013E63B /* SentryCrashDynamicLinker+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryCrashDynamicLinker+Test.h"; sourceTree = ""; }; + F451FAA52E0B304E0050ACF2 /* LoadValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadValidator.swift; sourceTree = ""; }; F452437D2DE60B71003E8F50 /* SentryUseNSExceptionCallstackWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryUseNSExceptionCallstackWrapper.m; sourceTree = ""; }; F45243862DE65968003E8F50 /* ExceptionCatcher.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ExceptionCatcher.h; sourceTree = ""; }; F45243872DE65968003E8F50 /* ExceptionCatcher.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExceptionCatcher.m; sourceTree = ""; }; F452438B2DE65BC0003E8F50 /* SentryUseNSExceptionCallstackWrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryUseNSExceptionCallstackWrapper.h; path = include/SentryUseNSExceptionCallstackWrapper.h; sourceTree = ""; }; F458D1122E180BB00028273E /* SentryFileManagerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryFileManagerProtocol.swift; sourceTree = ""; }; F458D1142E1869AD0028273E /* SentryScopePersistentStore+String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+String.swift"; sourceTree = ""; }; - F46DA6C22E1DBCA000DF6E3B /* SentryScopePersistentStore+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+Helper.swift"; sourceTree = ""; }; F458D1162E186DF20028273E /* SentryScopePersistentStore+Fingerprint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+Fingerprint.swift"; sourceTree = ""; }; F458D1182E186E000028273E /* SentryScopePersistentStore+Extras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+Extras.swift"; sourceTree = ""; }; + F46DA6C22E1DBCA000DF6E3B /* SentryScopePersistentStore+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+Helper.swift"; sourceTree = ""; }; + F46E0BA72E6A19F900DAA75C /* SentryCrashWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashWrapperTests.swift; sourceTree = ""; }; + F48E2E092E6637840073CB22 /* TestSentryCrashWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryCrashWrapper.swift; sourceTree = ""; }; + F48F74F22E5F9959009D4E7D /* SentryCrashBinaryImageCacheTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashBinaryImageCacheTests.m; sourceTree = ""; }; + F48F75702E5FA630009D4E7D /* SentryBinaryImageCacheCallbacks.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryBinaryImageCacheCallbacks.m; sourceTree = ""; }; + F48F75722E5FA649009D4E7D /* SentryBinaryImageCacheCallbacks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryBinaryImageCacheCallbacks.h; path = ../../Sentry/include/SentryBinaryImageCacheCallbacks.h; sourceTree = ""; }; + F48F767B2E60B555009D4E7D /* SentryNSTimerFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSTimerFactory.swift; sourceTree = ""; }; + F49236EA2E5E4B2F00663673 /* SentryBinaryImageCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryBinaryImageCache.swift; sourceTree = ""; }; F49D41972DEA27AF00D9244E /* SentryUseNSExceptionCallstackWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUseNSExceptionCallstackWrapperTests.swift; sourceTree = ""; }; F49D41992DEA2FB000D9244E /* SentryCrashExceptionApplicationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashExceptionApplicationTests.swift; sourceTree = ""; }; F49D419B2DEA30B800D9244E /* SentryCrashExceptionApplicationHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryCrashExceptionApplicationHelper.h; path = include/SentryCrashExceptionApplicationHelper.h; sourceTree = ""; }; F49D419D2DEA3D0300D9244E /* SentryCrashExceptionApplicationHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashExceptionApplicationHelper.m; sourceTree = ""; }; + F4A930222E65FDAF006DA6EF /* SentryMobileProvisionParser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryMobileProvisionParser.swift; sourceTree = ""; }; + F4A930242E661856006DA6EF /* SentryMobileProvisionParserTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryMobileProvisionParserTests.swift; sourceTree = ""; }; F4AACD602E01ACE800DDDD1E /* SentryCrashDynamicLinkerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashDynamicLinkerTests.m; sourceTree = ""; }; + F4DC35552E1FFD610077CE89 /* SentryVideoFrameProcessor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryVideoFrameProcessor.swift; sourceTree = ""; }; + F4DC35572E1FFE1B0077CE89 /* SentryVideoFrameProcessorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryVideoFrameProcessorTests.swift; sourceTree = ""; }; + F4DCC9DC2E4AA9D0008ECE45 /* SentrySDKSettingsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySDKSettingsTests.swift; sourceTree = ""; }; + F4DCC9E32E4AACE0008ECE45 /* SentrySDKSettings+Equality.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentrySDKSettings+Equality.h"; sourceTree = ""; }; + F4DCC9E42E4AACE0008ECE45 /* SentrySDKSettings+Equality.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "SentrySDKSettings+Equality.m"; sourceTree = ""; }; F4E3DCCA2E1579240093CB80 /* SentryScopePersistentStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryScopePersistentStore.swift; sourceTree = ""; }; + F4FE9DBC2E621F100014FED5 /* SentryRandom.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryRandom.swift; sourceTree = ""; }; + F4FE9DFB2E622CD70014FED5 /* SentryDefaultObjCRuntimeWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryDefaultObjCRuntimeWrapper.swift; sourceTree = ""; }; + F4FE9DFC2E622CD70014FED5 /* SentryObjCRuntimeWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryObjCRuntimeWrapper.swift; sourceTree = ""; }; + F4FE9E072E6248E40014FED5 /* SentryCrashWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashWrapper.swift; sourceTree = ""; }; + FA01BCB12E69352A00968DFA /* SentryDiscardedEvent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryDiscardedEvent.swift; sourceTree = ""; }; FA034AC72DD3DB4900FE3107 /* SentryIntegrationProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryIntegrationProtocol.h; path = Public/SentryIntegrationProtocol.h; sourceTree = ""; }; - FA3734812E0EEA670091EF24 /* SentryScreenshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryScreenshot.swift; sourceTree = ""; }; + FA18417D2E4B457B005DEDC7 /* SentryApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryApplication.swift; sourceTree = ""; }; + FA21A2E92E60E9C700E7EADB /* EnvelopeComparison.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnvelopeComparison.swift; sourceTree = ""; }; + FA34C1A22E692A5000BC52AA /* SentryEnvelopeItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryEnvelopeItem.swift; sourceTree = ""; }; FA3734832E0F07A20091EF24 /* SentryDependencyContainerSwiftHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDependencyContainerSwiftHelper.h; path = include/SentryDependencyContainerSwiftHelper.h; sourceTree = ""; }; FA3734852E0F092F0091EF24 /* SentryDependencyContainerSwiftHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDependencyContainerSwiftHelper.m; sourceTree = ""; }; + FA3854352E267DA20045A563 /* SentryUser+Serialize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryUser+Serialize.h"; path = "include/SentryUser+Serialize.h"; sourceTree = ""; }; + FA3A42712E1C5F9B00A08C39 /* SentryNSNotificationCenterWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSNotificationCenterWrapper.swift; sourceTree = ""; }; + FA3AEE772E68E2830092283E /* SentryEnvelopeHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryEnvelopeHeader.swift; sourceTree = ""; }; + FA458CBD2E691A6E0061B13D /* SentryProcessInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryProcessInfo.swift; sourceTree = ""; }; FA4C32962DF7513F001D7B00 /* SentryExperimentalOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryExperimentalOptions.swift; sourceTree = ""; }; + FA4C32972DF7513F001D7B01 /* SentryAppState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryAppState.swift; sourceTree = ""; }; + FA6555132E30181B009917BC /* SentrySDKInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySDKInternal.h; path = include/SentrySDKInternal.h; sourceTree = ""; }; + FA6555152E30182B009917BC /* SentrySDKInternal.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySDKInternal.m; sourceTree = ""; }; + FA6555192E30189E009917BC /* SentrySDKTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySDKTests.swift; sourceTree = ""; }; + FA6614392E4B593000657755 /* SentryApplicationExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryApplicationExtensions.swift; sourceTree = ""; }; + FA6614FB2E4B8E1500657755 /* TestSentryUIApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryUIApplication.swift; sourceTree = ""; }; + FA6615042E4BA4D200657755 /* ThreadSafeApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThreadSafeApplication.swift; sourceTree = ""; }; FA67DCC02DDBD4C800896B02 /* SentrySDKLog+Configure.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentrySDKLog+Configure.swift"; sourceTree = ""; }; FA67DCC22DDBD4EA00896B02 /* Locks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Locks.swift; sourceTree = ""; }; FA67DCC32DDBD4EA00896B02 /* NumberExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NumberExtensions.swift; sourceTree = ""; }; @@ -2354,18 +2441,39 @@ FA67DCEF2DDBD4EA00896B02 /* URLSessionTaskHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionTaskHelper.swift; sourceTree = ""; }; FA67DCF22DDBD4EA00896B02 /* SwiftDescriptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftDescriptor.swift; sourceTree = ""; }; FA6FC0A22E0B5AC800ED2669 /* SentrySdkPackage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySdkPackage.swift; sourceTree = ""; }; + FA6FC0A92E0B6B0E00ED2669 /* SentrySdkInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySdkInfo.swift; sourceTree = ""; }; FA7206DE2E0B37780072FDD4 /* SentryProfileCollector.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryProfileCollector.h; sourceTree = ""; }; FA7206E02E0B37C60072FDD4 /* SentryProfileCollector.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryProfileCollector.mm; sourceTree = ""; }; FA8A36172DEAA1EB0058D883 /* SentryThread+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryThread+Private.h"; path = "include/SentryThread+Private.h"; sourceTree = ""; }; FA8E58F02E0AD4220049F69D /* SentryDispatchQueueWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryDispatchQueueWrapper.swift; sourceTree = ""; }; FA90FAA72E06614B008CAAE8 /* SentryExtraPackages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryExtraPackages.swift; sourceTree = ""; }; FA90FAFC2E070A3B008CAAE8 /* SentryURLRequestFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryURLRequestFactory.swift; sourceTree = ""; }; + FA94E68B2E6B92BE00576666 /* SentryClientReport.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryClientReport.swift; sourceTree = ""; }; + FA94E6B12E6D265500576666 /* SentryEnvelope.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryEnvelope.swift; sourceTree = ""; }; + FA94E71B2E6F26BF00576666 /* SentrySerialization+ReplayRecording.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentrySerialization+ReplayRecording.swift"; sourceTree = ""; }; + FA94E7232E6F32FA00576666 /* SentryEnvelopeItemType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryEnvelopeItemType.swift; sourceTree = ""; }; + FAAB29F02E3D252000ACD577 /* SentrySession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySession.swift; sourceTree = ""; }; + FAAB2EDF2E4BE96F00FE8B7E /* TestSentryNSApplication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentryNSApplication.swift; sourceTree = ""; }; + FAAB2F962E4D344F00FE8B7E /* SentryUIDeviceWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUIDeviceWrapper.swift; sourceTree = ""; }; + FAAB30F22E4E8F2C00FE8B7E /* SentryInAppLogic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryInAppLogic.swift; sourceTree = ""; }; FAB359972E05D7E90083D5E3 /* SentryEventSwiftHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryEventSwiftHelper.h; path = include/SentryEventSwiftHelper.h; sourceTree = ""; }; FAB359992E05D8080083D5E3 /* SentryEventSwiftHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryEventSwiftHelper.m; sourceTree = ""; }; + FAB7BBA82E2577A2007301E1 /* SentryModels+Serializable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryModels+Serializable.h"; path = "include/SentryModels+Serializable.h"; sourceTree = ""; }; + FABB48B12E59310D0071397E /* SentryMeasurementValue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryMeasurementValue.swift; sourceTree = ""; }; + FABE8E142E307A5C0040809A /* SentrySDK.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySDK.swift; sourceTree = ""; }; + FABE8E162E307A7C0040809A /* Dependencies.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dependencies.swift; sourceTree = ""; }; FAC62B642E15A40C0003909D /* SentrySDKThreadTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySDKThreadTests.swift; sourceTree = ""; }; + FAC735222E25AA7A006C5A64 /* SentryProfilingSwiftHelpersTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryProfilingSwiftHelpersTests.m; sourceTree = ""; }; + FACEED122E3179A10007B4AC /* SentyOptionsInternal.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentyOptionsInternal.m; sourceTree = ""; }; + FAE2DAB72E1F317900262307 /* SentryProfilingSwiftHelpers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryProfilingSwiftHelpers.m; sourceTree = ""; }; + FAE2DAB92E1F318900262307 /* SentryProfilingSwiftHelpers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryProfilingSwiftHelpers.h; path = Sources/Sentry/include/SentryProfilingSwiftHelpers.h; sourceTree = SOURCE_ROOT; }; + FAE80C232E4695AE0010A595 /* SentryEvent+Serialize.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentryEvent+Serialize.h"; path = "include/SentryEvent+Serialize.h"; sourceTree = ""; }; FAEC270D2DF3526000878871 /* SentryUserFeedback.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUserFeedback.swift; sourceTree = ""; }; FAEC273C2DF3933200878871 /* NSData+Unzip.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSData+Unzip.m"; sourceTree = ""; }; FAEC273E2DF393E000878871 /* NSData+Unzip.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSData+Unzip.h"; sourceTree = ""; }; + FAEFA1292E4FAE1700C431D9 /* SentrySDKSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySDKSettings.swift; sourceTree = ""; }; + FAF120122E70C088006E1DA3 /* SentryEnvelopeHeaderHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryEnvelopeHeaderHelper.h; path = include/SentryEnvelopeHeaderHelper.h; sourceTree = ""; }; + FAF120192E70C0EA006E1DA3 /* SentryEnvelopeHeaderHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryEnvelopeHeaderHelper.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -2497,10 +2605,25 @@ 621D9F2D2B9B030E003D94DE /* Helper */ = { isa = PBXGroup; children = ( + FA94E71B2E6F26BF00576666 /* SentrySerialization+ReplayRecording.swift */, + FA94E7232E6F32FA00576666 /* SentryEnvelopeItemType.swift */, + FA458CBD2E691A6E0061B13D /* SentryProcessInfo.swift */, + F4A930222E65FDAF006DA6EF /* SentryMobileProvisionParser.swift */, + F4FE9DBC2E621F100014FED5 /* SentryRandom.swift */, + F48F767B2E60B555009D4E7D /* SentryNSTimerFactory.swift */, + FABE8E162E307A7C0040809A /* Dependencies.swift */, + FA6FC0A92E0B6B0E00ED2669 /* SentrySdkInfo.swift */, + FA18417D2E4B457B005DEDC7 /* SentryApplication.swift */, + FA6614392E4B593000657755 /* SentryApplicationExtensions.swift */, + FA6615042E4BA4D200657755 /* ThreadSafeApplication.swift */, + FABE8E142E307A5C0040809A /* SentrySDK.swift */, + FA3A42712E1C5F9B00A08C39 /* SentryNSNotificationCenterWrapper.swift */, FA6FC0A22E0B5AC800ED2669 /* SentrySdkPackage.swift */, FA8E58F02E0AD4220049F69D /* SentryDispatchQueueWrapper.swift */, 84B0E0062CD963F9007FB332 /* SentryIconography.swift */, 621F61F02BEA073A005E654F /* SentryEnabledFeaturesBuilder.swift */, + F4FE9DFB2E622CD70014FED5 /* SentryDefaultObjCRuntimeWrapper.swift */, + F4FE9DFC2E622CD70014FED5 /* SentryObjCRuntimeWrapper.swift */, ); path = Helper; sourceTree = ""; @@ -2508,6 +2631,7 @@ 62872B602BA1B84400A4FA7D /* Swift */ = { isa = PBXGroup; children = ( + F443DB242E09BE61009A9045 /* Core */, 62872B612BA1B84C00A4FA7D /* Extensions */, ); path = Swift; @@ -2570,19 +2694,18 @@ 630436011EBCB8CA00C4D3FA /* Protocol */ = { isa = PBXGroup; children = ( - 15E0A8E0240C41CE00F044E3 /* SentryEnvelope.h */, - 7B5CAF7027F5953400ED0DB6 /* SentryEnvelope+Private.h */, - 15E0A8E4240C457D00F044E3 /* SentryEnvelope.m */, + FAF120122E70C088006E1DA3 /* SentryEnvelopeHeaderHelper.h */, + FAF120192E70C0EA006E1DA3 /* SentryEnvelopeHeaderHelper.m */, D8CB74182947285A00A5F964 /* SentryEnvelopeItemHeader.h */, D8CB741A2947286500A5F964 /* SentryEnvelopeItemHeader.m */, D8CB74142947246600A5F964 /* SentryEnvelopeAttachmentHeader.h */, D8CB7416294724CC00A5F964 /* SentryEnvelopeAttachmentHeader.m */, - 7BC852382458830A005A70F0 /* SentryEnvelopeItemType.h */, 6304360F1EC0600A00C4D3FA /* SentrySerializable.h */, 6271ADF22BA06D9B0098D2E9 /* SentryInternalSerializable.h */, 639FCF961EBC7B9700778193 /* SentryEvent.h */, 639FCF971EBC7B9700778193 /* SentryEvent.m */, D880E3B02860A5A0008A90DB /* SentryEvent+Private.h */, + FAE80C232E4695AE0010A595 /* SentryEvent+Serialize.h */, 639FCF9E1EBC804600778193 /* SentryException.h */, 639FCF9F1EBC804600778193 /* SentryException.m */, 6334313F20AD9AE40077E581 /* SentryMechanism.h */, @@ -2602,6 +2725,7 @@ 843FB3212D0CD04D00558F18 /* SentryUserAccess.h */, 843FB3222D0CD04D00558F18 /* SentryUserAccess.m */, 92F6726A29C8B7B000BFD34D /* SentryUser+Private.h */, + FA3854352E267DA20045A563 /* SentryUser+Serialize.h */, 9286059429A5096600F96038 /* SentryGeo.h */, 9286059629A5098900F96038 /* SentryGeo.m */, 63B818F71EC34639002FDF4C /* SentryDebugMeta.h */, @@ -2609,20 +2733,13 @@ 6360850B1ED2AFE100E8599E /* SentryBreadcrumb.h */, 6360850C1ED2AFE100E8599E /* SentryBreadcrumb.m */, 92672BB529C9A2A9006B021C /* SentryBreadcrumb+Private.h */, - 7B4E24FB251C97B400060D68 /* SentrySession.h */, - 15E0A8F12411A45A00F044E3 /* SentrySession.m */, - 7BE1E32624F7AE08009D3AD0 /* SentrySession+Private.h */, - 7B88F2FD24BC5A4C00ADF90A /* SentrySdkInfo.h */, - 7B88F2FF24BC5A7D00ADF90A /* SentrySdkInfo.m */, + 7B4E24FB251C97B400060D68 /* SentrySessionInternal.h */, + 15E0A8F12411A45A00F044E3 /* SentrySessionInternal.m */, 7BFC169A2524995700FF6266 /* SentryMessage.h */, 7BFC16A025249A9D00FF6266 /* SentryMessage.m */, 7B4E375425822C4500059C93 /* SentryAttachment.h */, D86B6834294348A400B8B1FC /* SentryAttachment+Private.h */, 7B4E375E258231FC00059C93 /* SentryAttachment.m */, - 7BD4BD4227EB29BA0071F4FF /* SentryClientReport.h */, - 7BD4BD4427EB29F50071F4FF /* SentryClientReport.m */, - 7BD4BD4627EB2A3D0071F4FF /* SentryDiscardedEvent.h */, - 7BD4BD4827EB2A5D0071F4FF /* SentryDiscardedEvent.m */, 7BC9A20128F41350001E7C4C /* SentryMeasurementUnit.h */, 7BC9A20528F41781001E7C4C /* SentryMeasurementUnit.m */, A8F17B2D2901765900990B25 /* SentryRequest.m */, @@ -2642,8 +2759,8 @@ 63295AF41EF3C7DB002D4490 /* SentryNSDictionarySanitize.m */, 7B0DC72D288698F70039995F /* NSMutableDictionary+Sentry.h */, 7B0DC72E288698F70039995F /* NSMutableDictionary+Sentry.m */, - 861265F72404EC1500C4AFDE /* NSArray+SentrySanitize.h */, - 861265F82404EC1500C4AFDE /* NSArray+SentrySanitize.m */, + 861265F72404EC1500C4AFDE /* SentryArray.h */, + 861265F82404EC1500C4AFDE /* SentryArray.m */, 7B6438A826A70F24000D0F65 /* UIViewController+Sentry.h */, 7B6438A926A70F24000D0F65 /* UIViewController+Sentry.m */, 0A2D8D9728997887008720F6 /* NSLocale+Sentry.h */, @@ -2679,6 +2796,7 @@ 6304360C1EC05CEF00C4D3FA /* Frameworks */, 6327C5D41EB8A783004E799B /* Products */, 7D826E3C2390840E00EED93D /* Utils */, + F474CB872E2EC5040001DF41 /* Recovered References */, ); indentWidth = 4; sourceTree = ""; @@ -2727,15 +2845,9 @@ 7B0A54272521C22C00A71716 /* SentryFrameRemover.m */, 7B14089524878F090035403D /* SentryCrashStackEntryMapper.h */, 7B14089724878F950035403D /* SentryCrashStackEntryMapper.m */, - 7BBC826C25DFCFDE005F1ED8 /* SentryInAppLogic.h */, - 7BBC827025DFD039005F1ED8 /* SentryInAppLogic.m */, 7B7D873124864BB900D2ECFF /* SentryCrashMachineContextWrapper.h */, 7B7D873324864C6600D2ECFF /* SentryCrashDefaultMachineContextWrapper.h */, 7B7D873524864C9D00D2ECFF /* SentryCrashDefaultMachineContextWrapper.m */, - 7B7A30C524B48321005A4C6E /* SentryCrashWrapper.h */, - 7B7A30C724B48389005A4C6E /* SentryCrashWrapper.m */, - 0ADC33ED28D9BB890078D980 /* SentryUIDeviceWrapper.h */, - 0ADC33EB28D9BB780078D980 /* SentryUIDeviceWrapper.m */, 62C97D372CC64E4900DDA204 /* SentryUncaughtNSExceptions.h */, 62C97D392CC64E6B00DDA204 /* SentryUncaughtNSExceptions.m */, ); @@ -2751,6 +2863,7 @@ 7D0637022382B34300B30749 /* SentryScope.h */, 7D65260B237F649E00113EA2 /* SentryScope.m */, 632331F7240506DF008D91D6 /* SentryScope+Private.h */, + 928207C32E251B8F009285A4 /* SentryScope+PrivateSwift.h */, 7BCFBD662681C95000BC27D8 /* SentryScopeObserver.h */, 15360CEF2433A16D00112302 /* SentryInstallation.h */, 15360CEC2433A15500112302 /* SentryInstallation.m */, @@ -2817,35 +2930,24 @@ 7BC63F0928081288009D9E37 /* SentrySwizzleWrapper.m */, 7BD729952463E83300EA3610 /* SentryDateUtil.h */, 7BD729972463E93500EA3610 /* SentryDateUtil.m */, - 7B98D7E325FB7A7200C5A389 /* SentryAppState.h */, - 7B98D7E725FB7BCD00C5A389 /* SentryAppState.m */, + FAB7BBA82E2577A2007301E1 /* SentryModels+Serializable.h */, 7B8ECBF926498906005FE2EF /* SentryAppStateManager.h */, 7B8ECBFB26498958005FE2EF /* SentryAppStateManager.m */, 7BD86EC4264A63F6005439DB /* SentrySysctl.h */, 7BD86EC6264A641D005439DB /* SentrySysctl.m */, - 7BF9EF832722D07B00B5BBEF /* SentryObjCRuntimeWrapper.h */, - 7BF9EF7B2722B90E00B5BBEF /* SentryDefaultObjCRuntimeWrapper.h */, - 7BF9EF7D2722B91F00B5BBEF /* SentryDefaultObjCRuntimeWrapper.m */, D8479327278873A100BE8E99 /* SentryByteCountFormatter.h */, D84793242788737D00BE8E99 /* SentryByteCountFormatter.m */, 7B2A70DA27D607CF008B0D15 /* SentryThreadWrapper.h */, 7B2A70DC27D6083D008B0D15 /* SentryThreadWrapper.m */, - 7B18DE3F28D9F748004845C6 /* SentryNSNotificationCenterWrapper.h */, - 7B18DE4128D9F794004845C6 /* SentryNSNotificationCenterWrapper.m */, + 7B18DE3F28D9F748004845C6 /* SentryNotificationNames.h */, 84A8891A28DBD28900C51DFD /* SentryDevice.h */, 84A8891B28DBD28900C51DFD /* SentryDevice.m */, - 844EDC6D294143B900C86F34 /* SentryNSProcessInfoWrapper.h */, - 844EDC6E294143B900C86F34 /* SentryNSProcessInfoWrapper.mm */, 844EDC74294144DB00C86F34 /* SentrySystemWrapper.h */, 844EDC75294144DB00C86F34 /* SentrySystemWrapper.mm */, - 844EDCE32947DC3100C86F34 /* SentryNSTimerFactory.h */, - 844EDCE42947DC3100C86F34 /* SentryNSTimerFactory.m */, FAB359972E05D7E90083D5E3 /* SentryEventSwiftHelper.h */, FAB359992E05D8080083D5E3 /* SentryEventSwiftHelper.m */, 33042A0B29DAF5F400C60085 /* SentryExtraContextProvider.h */, 33042A0C29DAF79A00C60085 /* SentryExtraContextProvider.m */, - D858FA642A29EAB3002A3503 /* SentryBinaryImageCache.h */, - D858FA652A29EAB3002A3503 /* SentryBinaryImageCache.m */, D8739D152BEEA33F007D2F66 /* SentryLevelHelper.h */, D8739D162BEEA33F007D2F66 /* SentryLevelHelper.m */, F452438B2DE65BC0003E8F50 /* SentryUseNSExceptionCallstackWrapper.h */, @@ -2873,6 +2975,7 @@ 844DA7F6282435CD00E6B62E /* README.md */, 630C01951EC341D600C52CEF /* Resources */, 63AA76AA1EB9D5CD00D153DE /* Configuration */, + 846D3F122E286ECF00D4E7E3 /* DuplicatedSDKTest */, 63AA75931EB8AEDB00D153DE /* SentryTests */, 8431EFDB29B27B3D00D8DC56 /* SentryProfilerTests */, D8F01DE32A125D7B008F4996 /* HybridSDKTest */, @@ -2888,11 +2991,10 @@ D4F2B5332D0C69CC00649E42 /* Recording */, 62872B602BA1B84400A4FA7D /* Swift */, 7B3878E92490D90400EBDEA2 /* SentryClient+TestInit.h */, - D8BC83BA2AFCF08C00A662B7 /* SentryUIApplication+Private.h */, 84A305592BC9FD1600D84283 /* SentryTraceProfiler+Test.h */, 7B569DFE2590EEF600B653FC /* SentryScope+Equality.h */, 7B569E052590F04700B653FC /* SentryScope+Properties.h */, - 7B9421C4260CA393001F9349 /* SentrySDK+Tests.h */, + 7B9421C4260CA393001F9349 /* SentrySDKInternal+Tests.h */, 8431D4572BE175A1009EAEC1 /* SentryContinuousProfiler+Test.h */, 639889D21EDF06C100EA7442 /* SentryTests-Bridging-Header.h */, 63B819131EC352A7002FDF4C /* SentryInterfacesTests.m */, @@ -2910,13 +3012,16 @@ 15D0AC872459EE4D006541C2 /* SentryNSURLRequestTests.swift */, 7B0A54552523178700A71716 /* SentryScopeSwiftTests.swift */, D8918B212849FA6D00701F9A /* SentrySDKIntegrationTestsBase.swift */, - 7BA8409F24A1EC6E00B718AA /* SentrySDKTests.swift */, + 7BA8409F24A1EC6E00B718AA /* SentrySDKInternalTests.swift */, + FA6555192E30189E009917BC /* SentrySDKTests.swift */, FAC62B642E15A40C0003909D /* SentrySDKThreadTests.swift */, 7B0002332477F52D0035FEF1 /* SentrySessionTests.swift */, 8E70B10025CB8695002B3155 /* SentrySpanIdTests.swift */, 8ED3D305264DFE700049393B /* SwiftDescriptorTests.swift */, 0A1B497228E597DD00D7BFA3 /* TestLogOutput.swift */, D8AE48C02C57B1550092A2A6 /* SentryLevelTests.swift */, + 92235CAF2E155B2600865983 /* SentryLoggerTests.swift */, + 928BED2A2E16977A00B4D398 /* SentryLogBatcherTests.swift */, F49D41992DEA2FB000D9244E /* SentryCrashExceptionApplicationTests.swift */, 7B6438AD26A710E6000D0F65 /* Categories */, D8BC28D32C00C6A60054DA4D /* Extensions */, @@ -2971,15 +3076,19 @@ 63AA76941EB9C1C200D153DE /* SentryClient.h */, 63AA75ED1EB8B3C400D153DE /* SentryClient.m */, 7B85DC1C24EFAFCD007D01D2 /* SentryClient+Private.h */, - 7D427C5F237B1D200046BAC8 /* SentrySDK.h */, - 7D5C4418237C2E1F00DAB0A3 /* SentrySDK.m */, + 92EC54CD2E1EB54B00A10AC2 /* SentryClient+Logs.h */, 7B610D5E2512390E00B0B5D9 /* SentrySDK+Private.h */, + FA6555132E30181B009917BC /* SentrySDKInternal.h */, + FA6555152E30182B009917BC /* SentrySDKInternal.m */, + FACEED122E3179A10007B4AC /* SentyOptionsInternal.m */, 63EED6BC2237923600E02400 /* SentryOptions.h */, 63EED6BD2237923600E02400 /* SentryOptions.m */, 7BDEAA002632A4580001EA25 /* SentryOptions+Private.h */, - 7B2BB0012966F55900A1E102 /* SentryOptions+HybridSDKs.h */, + 7B2BB0012966F55900A1E102 /* SentryOptionsInternal.h */, 7D9B079F23D1E89800C5FC8E /* SentryMeta.h */, 7D082B8023C628780029866B /* SentryMeta.m */, + D4ECA3FF2E3CBEDE00C757EA /* SentryDummyPrivateEmptyClass.m */, + D4ECA4002E3CBEDE00C757EA /* SentryDummyPublicEmptyClass.m */, ); path = Sentry; sourceTree = ""; @@ -3044,6 +3153,8 @@ 63FE6FE920DA4C1000CDBAE8 /* Recording */ = { isa = PBXGroup; children = ( + F48F75722E5FA649009D4E7D /* SentryBinaryImageCacheCallbacks.h */, + F48F75702E5FA630009D4E7D /* SentryBinaryImageCacheCallbacks.m */, 63FE704B20DA4C1000CDBAE8 /* SentryCrash.h */, 63FE704120DA4C1000CDBAE8 /* SentryCrash.m */, 63FE704920DA4C1000CDBAE8 /* SentryCrashC.h */, @@ -3172,9 +3283,10 @@ 63FE71D220DA66C500CDBAE8 /* SentryCrash */ = { isa = PBXGroup; children = ( + F46E0BA72E6A19F900DAA75C /* SentryCrashWrapperTests.swift */, + F48F74F22E5F9959009D4E7D /* SentryCrashBinaryImageCacheTests.m */, F4AACD602E01ACE800DDDD1E /* SentryCrashDynamicLinkerTests.m */, 63FE71F120DA66EA00CDBAE8 /* Container+DeepSearch_Tests.m */, - D8CCFC622A1520C900DE232E /* SentryBinaryImageCacheTests.m */, 63FE71F620DA66EB00CDBAE8 /* FileBasedTestCase.h */, 63FE71D920DA66E700CDBAE8 /* FileBasedTestCase.m */, 84EB21952BF01CEA00EDDA28 /* SentryCrashInstallationTests.swift */, @@ -3219,8 +3331,7 @@ 7BBC827825DFD7D7005F1ED8 /* SentryInAppLogicTests.swift */, D801990F286B089000C277F0 /* SentryCrashReportSinkTests.swift */, 0A283E78291A67E000EF4126 /* SentryUIDeviceWrapperTests.swift */, - 7BED3574266F7BC600EAA70D /* TestSentryCrashWrapper.h */, - 7BED3575266F7BFF00EAA70D /* TestSentryCrashWrapper.m */, + F48E2E092E6637840073CB22 /* TestSentryCrashWrapper.swift */, 0ADC33EF28D9BE690078D980 /* TestSentryUIDeviceWrapper.swift */, 7B984A9E28E572AF001F4BEE /* CrashReport.swift */, 7BF69E062987D1FE002EBCA4 /* SentryCrashDoctorTests.swift */, @@ -3268,6 +3379,8 @@ 7B3D0474249A3D5800E106B6 /* Protocol */ = { isa = PBXGroup; children = ( + F4DCC9DC2E4AA9D0008ECE45 /* SentrySDKSettingsTests.swift */, + 9264E1EC2E2E397400B077CF /* SentryLogMessageTests.swift */, 92B6BDAC2E05B9F700D538B3 /* SentryLogTests.swift */, 92ECD7472E05B5760063EC10 /* SentryLogAttributeTests.swift */, 92B6BDA82E05B8F000D538B3 /* SentryLogLevelTests.swift */, @@ -3283,6 +3396,8 @@ 7B26BBFA24C0A66D00A79CCC /* SentrySdkInfoNilTests.m */, 7B6D98E724C6D336005502FA /* SentrySdkInfo+Equality.h */, 7B6D98E824C6D336005502FA /* SentrySdkInfo+Equality.m */, + F4DCC9E32E4AACE0008ECE45 /* SentrySDKSettings+Equality.h */, + F4DCC9E42E4AACE0008ECE45 /* SentrySDKSettings+Equality.m */, 7B82D54824E2A2D400EE670F /* SentryIdTests.swift */, 7B04A9AA24EA5F8D00E710B1 /* SentryUserTests.swift */, 9286059829A50BAA00F96038 /* SentryGeoTests.swift */, @@ -3331,6 +3446,7 @@ 7B6438AD26A710E6000D0F65 /* Categories */ = { isa = PBXGroup; children = ( + D4CA34822E378C9000E92A61 /* SentryArrayTests.swift */, D41909922D48FFF6002B83D0 /* SentryNSDictionarySanitize+Tests.h */, D41909942D490006002B83D0 /* SentryNSDictionarySanitize+Tests.m */, D42E48582D48FC8F00D251BC /* SentryNSDictionarySanitizeTests.swift */, @@ -3426,6 +3542,7 @@ 7B4E23B5251A07BD00060D68 /* SentryDispatchQueueWrapperTests.swift */, 8E0551DF26A7A63C00400526 /* TestProtocolClient.swift */, 7B4D308926FC616B00C94DE9 /* SentryHttpTransportTests.swift */, + 62278CA72E30B21A0022ABC6 /* SentryHttpTransportFlushIntegrationTests.swift */, FAEC273E2DF393E000878871 /* NSData+Unzip.h */, FAEC273C2DF3933200878871 /* NSData+Unzip.m */, 62A3C7BD2B7E2A6A00C75227 /* SentrySpotlightTransportTests.swift */, @@ -3457,6 +3574,8 @@ 7BD7299B24654CD500EA3610 /* Helper */ = { isa = PBXGroup; children = ( + F4A930242E661856006DA6EF /* SentryMobileProvisionParserTests.swift */, + D4F7BD7C2E4373BB004A2D77 /* SentryLevelMapperTests.swift */, D8AE48BE2C578D540092A2A6 /* SentrySDKLog.swift */, 849AC3FF29E0C1FF00889C16 /* SentryFormatterTests.swift */, 7B88F30324BC8E6500ADF90A /* SentrySerializationTests.swift */, @@ -3466,6 +3585,7 @@ 62F05D292C0DB1C800916E3F /* SentryLogTestHelper.h */, 62F05D2A2C0DB1F100916E3F /* SentryLogTestHelper.m */, 7BBD18BA24530D2600427C76 /* SentryFileManagerTests.swift */, + FA21A2E92E60E9C700E7EADB /* EnvelopeComparison.swift */, 7BD4E8E727FD95900086C410 /* SentryMigrateSessionInitTests.m */, 7BD4E8E527FD84480086C410 /* TestFileManagerDelegate.swift */, 631501BA1EE6F30B00512C5B /* SentrySwizzleTests.m */, @@ -3484,7 +3604,6 @@ 7BF9EF872722D13000B5BBEF /* SentryTestObjCRuntimeWrapper.m */, D85D3BE9278DF63D001B2889 /* SentryByteCountFormatterTests.swift */, 7B2A70DE27D60904008B0D15 /* SentryTestThreadWrapper.swift */, - 7B18DE4928DA0C8B004845C6 /* SentryNSNotificationCenterWrapperTests.swift */, 84A8892028DBD8D600C51DFD /* SentryDeviceTests.m */, 8431EE5A29ADB8EA00D8DC56 /* SentryTimeTests.m */, 62C3168A2B1F865A000D7031 /* SentryTimeSwiftTests.swift */, @@ -3804,6 +3923,8 @@ children = ( 03F84D3127DD4191008FE43F /* SentryBacktrace.cpp */, 03F84D1227DD414C008FE43F /* SentryBacktrace.hpp */, + FAE2DAB92E1F318900262307 /* SentryProfilingSwiftHelpers.h */, + FAE2DAB72E1F317900262307 /* SentryProfilingSwiftHelpers.m */, 03F84D1827DD414C008FE43F /* SentryCompiler.h */, 03F84D1C27DD414C008FE43F /* SentryCPU.h */, 03F84D2C27DD4191008FE43F /* SentryMachLogging.cpp */, @@ -3816,6 +3937,8 @@ 84AF45A429A7FFA500FBB177 /* SentryProfiledTracerConcurrency.h */, 84AF45A529A7FFA500FBB177 /* SentryProfiledTracerConcurrency.mm */, 840B7EF22BBF83DF008B8120 /* SentryProfiler+Private.h */, + 84A898522E163072009A551E /* SentryProfileConfiguration.h */, + 84A898532E163072009A551E /* SentryProfileConfiguration.m */, 8431D4612BE1B534009EAEC1 /* SentryProfilerDefines.h */, 03F84D2B27DD4191008FE43F /* SentryProfiler.mm */, 84A305552BC9EF8C00D84283 /* SentryTraceProfiler.h */, @@ -3852,6 +3975,8 @@ 8431EFDB29B27B3D00D8DC56 /* SentryProfilerTests */ = { isa = PBXGroup; children = ( + D4DEE6582E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m */, + FAC735222E25AA7A006C5A64 /* SentryProfilingSwiftHelpersTests.m */, 849472802971C107002603DE /* SentrySystemWrapperTests.swift */, 849472822971C2CD002603DE /* SentryNSProcessInfoWrapperTests.swift */, 849472842971C41A002603DE /* SentryNSTimerFactoryTest.swift */, @@ -3861,8 +3986,8 @@ 035E73CD27D5790A005EEB11 /* SentryThreadMetadataCacheTests.mm */, 03F9D37B2819A65C00602916 /* SentryProfilerTests.mm */, 84A305472BC72A0A00D84283 /* SentryAppLaunchProfilingTests.swift */, - 84F2A1CD2E06001300A94524 /* SentryApplaunchProfilingMalformedConfigFileTests.swift */, 845CEB162D8A979700B6B325 /* SentryAppStartProfilingConfigurationTests.swift */, + 84A898CD2E1DBDD1009A551E /* SentryAppStartProfilingConfigurationChangeTests.swift */, 845CEAEE2D83F79500B6B325 /* SentryProfilingPublicAPITests.swift */, 8419C0C328C1889D001C8259 /* SentryTraceProfilerTests.swift */, 8446F5182BE172290040D57E /* SentryContinuousProfilerTests.swift */, @@ -3920,6 +4045,8 @@ 84B7FA3B29B2866200AD93B1 /* SentryTestUtils-ObjC-BridgingHeader.h */, 62C25C852B075F4900C68CBD /* TestOptions.swift */, 62FC69352BEDFF18002D3EF2 /* SentryLogExtensions.swift */, + D45B4AF42E019E1500C31DFB /* TestSentryViewRenderer.swift */, + D45B4AF62E01A0FA00C31DFB /* TestSentryViewPhotographer.swift */, ); path = SentryTestUtils; sourceTree = ""; @@ -3932,6 +4059,48 @@ path = Feedback; sourceTree = ""; }; + 846D3F0D2E286ECF00D4E7E3 /* DuplicatedSDKTest */ = { + isa = PBXGroup; + children = ( + 846D3F092E286ECF00D4E7E3 /* DuplicatedSDKTest-Bridging-Header.h */, + 846D3F0A2E286ECF00D4E7E3 /* DuplicatedSDKTestApp.swift */, + 846D3F0B2E286ECF00D4E7E3 /* SomeWork.swift */, + 846D3F0C2E286ECF00D4E7E3 /* UITest.swift */, + ); + path = DuplicatedSDKTest; + sourceTree = ""; + }; + 846D3F0F2E286ECF00D4E7E3 /* Unit Tests */ = { + isa = PBXGroup; + children = ( + 846D3F0E2E286ECF00D4E7E3 /* Unit_Tests.swift */, + ); + path = "Unit Tests"; + sourceTree = ""; + }; + 846D3F122E286ECF00D4E7E3 /* DuplicatedSDKTest */ = { + isa = PBXGroup; + children = ( + 846D3F0D2E286ECF00D4E7E3 /* DuplicatedSDKTest */, + 846D3F0F2E286ECF00D4E7E3 /* Unit Tests */, + 846D3F102E286ECF00D4E7E3 /* DuplicatedSDKTest.xcodeproj */, + 846D3F112E286ECF00D4E7E3 /* DuplicatedSDKTest.xctestplan */, + ); + path = DuplicatedSDKTest; + sourceTree = ""; + }; + 846D3F132E286ECF00D4E7E3 /* Products */ = { + isa = PBXGroup; + children = ( + 846D3F272E286ECF00D4E7E3 /* DuplicatedSDKTest.app */, + 846D3F292E286ECF00D4E7E3 /* ModuleA.framework */, + 846D3F2B2E286ECF00D4E7E3 /* ModuleB.framework */, + 846D3F2D2E286ECF00D4E7E3 /* UITest-DuplicatedSDK.xctest */, + 846D3F2F2E286ECF00D4E7E3 /* Unit Tests.xctest */, + ); + name = Products; + sourceTree = ""; + }; 847B1A002C618ACA002CB1F3 /* UserFeedback */ = { isa = PBXGroup; children = ( @@ -3967,13 +4136,6 @@ 8E25C94F25F836AB00DC215B /* Tools */ = { isa = PBXGroup; children = ( - 8E25C95625F836EE00DC215B /* SentryRandom.h */, - 8E25C95125F836D000DC215B /* SentryRandom.m */, - D406044A2DD2483D00C40DC0 /* SentryApplication.h */, - D8C67E9928000E23007E326E /* SentryUIApplication.h */, - D85852B827EDDC5900C6D8AE /* SentryUIApplication.m */, - D40604482DD2472600C40DC0 /* SentryNSApplication.h */, - D40604462DD2471600C40DC0 /* SentryNSApplication.m */, D8F6A24A2885515B00320515 /* SentryPredicateDescriptor.h */, D8F6A2452885512100320515 /* SentryPredicateDescriptor.m */, 0A2D8DA6289BC905008720F6 /* SentryViewHierarchyProvider.h */, @@ -3994,8 +4156,6 @@ D8603DD4284F8497000E1227 /* SentryBaggage.m */, 620379DA2AFE1415005AC0C1 /* SentryBuildAppStartSpans.h */, 620379DC2AFE1432005AC0C1 /* SentryBuildAppStartSpans.m */, - 7BC9A1FF28F41016001E7C4C /* SentryMeasurementValue.h */, - 7BC9A20328F4166D001E7C4C /* SentryMeasurementValue.m */, 7BE912AA272162AF00E49E62 /* SentryNoOpSpan.h */, 7BE912AC272162D900E49E62 /* SentryNoOpSpan.m */, 8E4A037725F6F52100000D77 /* SentrySampleDecision.h */, @@ -4061,7 +4221,6 @@ F41362102E1C55AF00B84443 /* SentryScopePersistentStore+Tags.swift */, F41362122E1C566100B84443 /* SentryScopePersistentStore+User.swift */, F46DA6C22E1DBCA000DF6E3B /* SentryScopePersistentStore+Helper.swift */, - F458D11A2E186E0D0028273E /* SentryScopePersistentStore+Level.swift */, F458D1182E186E000028273E /* SentryScopePersistentStore+Extras.swift */, F458D1162E186DF20028273E /* SentryScopePersistentStore+Fingerprint.swift */, ); @@ -4118,6 +4277,8 @@ D46D45E12D5F3FD600A1CB35 /* Sentry_Base.xctestplan */, D46D45E92D5F411700A1CB35 /* SentrySwiftUI_Base.xctestplan */, D4A2360A2D5F84FA00D55C58 /* SwiftUITestSample_Base.xctestplan */, + 848214B42E32B10900DF6998 /* SwiftUITestSample_Crash.xctestplan */, + 848214B52E32B10900DF6998 /* SwiftUITestSample_Envelope.xctestplan */, ); path = Plans; sourceTree = ""; @@ -4141,6 +4302,14 @@ path = Transactions; sourceTree = ""; }; + D49064862DFAE1B700555785 /* Screenshot */ = { + isa = PBXGroup; + children = ( + D49064892DFAE1F600555785 /* SentryScreenshotOptions.swift */, + ); + path = Screenshot; + sourceTree = ""; + }; D4CBA2522DE06D1600581618 /* SentryTestUtilsTests */ = { isa = PBXGroup; children = ( @@ -4167,6 +4336,9 @@ D800942328F82E8D005D3943 /* Swift */ = { isa = PBXGroup; children = ( + F4FE9E062E6248BB0014FED5 /* SentryCrash */, + FABB48B22E59310D0071397E /* Transaction */, + FAAB29F02E3D252000ACD577 /* SentrySession.swift */, FA67DCF32DDBD4EA00896B02 /* Core */, D8CAC02D2BA0663E00E38F34 /* Integrations */, 621D9F2D2B9B030E003D94DE /* Helper */, @@ -4175,6 +4347,7 @@ D856272A2A374A6800FB8062 /* Tools */, D8B665BB2B95F5A100BD0E7B /* module.modulemap */, FA4C32962DF7513F001D7B00 /* SentryExperimentalOptions.swift */, + FA4C32972DF7513F001D7B01 /* SentryAppState.swift */, ); path = Swift; sourceTree = ""; @@ -4193,6 +4366,7 @@ D8DBE0C92C0E093000FAB1FD /* SentryTouchTrackerTests.swift */, D8DBE0D12C0EFFC300FAB1FD /* SentryReplayOptionsTests.swift */, D467125D2DCCFF2500D4074A /* SentryReplayOptionsObjcTests.m */, + F4DC35572E1FFE1B0077CE89 /* SentryVideoFrameProcessorTests.swift */, ); path = SessionReplay; sourceTree = ""; @@ -4263,9 +4437,11 @@ D81FDF0F280E9FEC0045E0E4 /* Tools */ = { isa = PBXGroup; children = ( + FA6614FB2E4B8E1500657755 /* TestSentryUIApplication.swift */, + FAAB2EDF2E4BE96F00FE8B7E /* TestSentryNSApplication.swift */, D43A2A132DD4815E00114724 /* SentryWeakMapTests.swift */, D4009EA02D77196F0007AF30 /* ViewCapture */, - D81FDF10280EA0080045E0E4 /* SentryScreenShotTests.swift */, + D81FDF10280EA0080045E0E4 /* SentryScreenshotSourceTests.swift */, D8F6A24C2885534E00320515 /* SentryPredicateDescriptorTests.swift */, 0A5370A028A3EC2400B2DCDE /* SentryViewHierarchyProviderTests.swift */, D8CB742A294B1DD000A5F964 /* SentryUIApplicationTests.swift */, @@ -4313,9 +4489,16 @@ D856272A2A374A6800FB8062 /* Tools */ = { isa = PBXGroup; children = ( + FA94E6B12E6D265500576666 /* SentryEnvelope.swift */, + FA94E68B2E6B92BE00576666 /* SentryClientReport.swift */, + FA3AEE772E68E2830092283E /* SentryEnvelopeHeader.swift */, + FA01BCB12E69352A00968DFA /* SentryDiscardedEvent.swift */, + 92235CAD2E15549C00865983 /* SentryLogger.swift */, + 92235CAB2E15369900865983 /* SentryLogBatcher.swift */, + F451FAA52E0B304E0050ACF2 /* LoadValidator.swift */, + FA34C1A22E692A5000BC52AA /* SentryEnvelopeItem.swift */, FA90FAFC2E070A3B008CAAE8 /* SentryURLRequestFactory.swift */, FA67DCC02DDBD4C800896B02 /* SentrySDKLog+Configure.swift */, - FA3734812E0EEA670091EF24 /* SentryScreenshot.swift */, ); path = Tools; sourceTree = ""; @@ -4400,6 +4583,7 @@ D878C6C22BC8066D0039D6A3 /* Docs */ = { isa = PBXGroup; children = ( + 84A899342E218C5F009A551E /* CLAUDE.md */, 844DA81028246D5000E6B62E /* CONTRIBUTING.md */, 844DA80E28246D5000E6B62E /* LICENSE.md */, 840B7EF02BBF2B5F008B8120 /* MIGRATION.md */, @@ -4445,7 +4629,8 @@ isa = PBXGroup; children = ( D8B76B042808060E000A58C4 /* SentryScreenshotIntegrationTests.swift */, - D8B76B0728081461000A58C4 /* TestSentryScreenShot.swift */, + D8B76B0728081461000A58C4 /* TestSentryScreenshotProvider.swift */, + D4D12E792DFC607F00DC45C4 /* SentryScreenshotOptionsTests.swift */, ); path = Screenshot; sourceTree = ""; @@ -4491,6 +4676,7 @@ D8CAC02A2BA0663E00E38F34 /* SentryReplayOptions.swift */, D8CAC02B2BA0663E00E38F34 /* SentryVideoInfo.swift */, D802994D2BA836EF000F0081 /* SentryOnDemandReplay.swift */, + F4DC35552E1FFD610077CE89 /* SentryVideoFrameProcessor.swift */, D4B0DC7E2DA9257200DE61B6 /* SentryRenderVideoResult.swift */, D451ED5E2D92ECDE00C9BEA8 /* SentryReplayFrame.swift */, D451ED5C2D92ECD200C9BEA8 /* SentryOnDemandReplayError.swift */, @@ -4510,6 +4696,7 @@ D8CAC02D2BA0663E00E38F34 /* Integrations */ = { isa = PBXGroup; children = ( + D49064862DFAE1B700555785 /* Screenshot */, D8739CF72BECFF92007D2F66 /* Performance */, D8CAC02C2BA0663E00E38F34 /* SessionReplay */, D452FCBC2DDB6FA800AFF56F /* WatchdogTerminations */, @@ -4520,10 +4707,12 @@ D8F016B12B9622B7007B9AFB /* Protocol */ = { isa = PBXGroup; children = ( + FAEFA1292E4FAE1700C431D9 /* SentrySDKSettings.swift */, 620078752D38F1110022CB67 /* Codable */, + 92ECD73B2E05ACDE0063EC10 /* SentryLog.swift */, 92ECD73F2E05AD500063EC10 /* SentryLogAttribute.swift */, 92ECD73D2E05AD2B0063EC10 /* SentryLogLevel.swift */, - 92ECD73B2E05ACDE0063EC10 /* SentryLog.swift */, + 9264E1EA2E2E385B00B077CF /* SentryLogMessage.swift */, F458D1122E180BB00028273E /* SentryFileManagerProtocol.swift */, ); path = Protocol; @@ -4538,6 +4727,37 @@ path = HybridSDKTest; sourceTree = ""; }; + F443DB242E09BE61009A9045 /* Core */ = { + isa = PBXGroup; + children = ( + F443DB252E09BE67009A9045 /* Tools */, + ); + path = Core; + sourceTree = ""; + }; + F443DB252E09BE67009A9045 /* Tools */ = { + isa = PBXGroup; + children = ( + F443DB262E09BE8C009A9045 /* LoadValidatorTests.swift */, + ); + path = Tools; + sourceTree = ""; + }; + F474CB872E2EC5040001DF41 /* Recovered References */ = { + isa = PBXGroup; + children = ( + ); + name = "Recovered References"; + sourceTree = ""; + }; + F4FE9E062E6248BB0014FED5 /* SentryCrash */ = { + isa = PBXGroup; + children = ( + F4FE9E072E6248E40014FED5 /* SentryCrashWrapper.swift */, + ); + path = SentryCrash; + sourceTree = ""; + }; FA67DCC62DDBD4EA00896B02 /* Extensions */ = { isa = PBXGroup; children = ( @@ -4560,11 +4780,14 @@ FA67DCCC2DDBD4EA00896B02 /* Helper */ = { isa = PBXGroup; children = ( + F49236EA2E5E4B2F00663673 /* SentryBinaryImageCache.swift */, + FAAB2F962E4D344F00FE8B7E /* SentryUIDeviceWrapper.swift */, FA90FAA72E06614B008CAAE8 /* SentryExtraPackages.swift */, FA67DCC82DDBD4EA00896B02 /* Log */, FA67DCC92DDBD4EA00896B02 /* SentryBaggageSerialization.swift */, FA67DCCA2DDBD4EA00896B02 /* SentryCurrentDateProvider.swift */, FA67DCCB2DDBD4EA00896B02 /* SentryFileContents.swift */, + FAAB30F22E4E8F2C00FE8B7E /* SentryInAppLogic.swift */, ); path = Helper; sourceTree = ""; @@ -4640,6 +4863,7 @@ FA67DCE52DDBD4EA00896B02 /* SentryViewRenderer.swift */, FA67DCE62DDBD4EA00896B02 /* SentryViewRendererV2.swift */, FA67DCE72DDBD4EA00896B02 /* SentryViewScreenshotProvider.swift */, + D45CE9742E5F454300BFEDB2 /* SentryScreenshotSource.swift */, FA67DCE82DDBD4EA00896B02 /* SentryUIRedactBuilder.swift */, D41415A62DEEE532003B14D5 /* SentryRedactViewHelper.swift */, ); @@ -4673,6 +4897,14 @@ path = Core; sourceTree = ""; }; + FABB48B22E59310D0071397E /* Transaction */ = { + isa = PBXGroup; + children = ( + FABB48B12E59310D0071397E /* SentryMeasurementValue.swift */, + ); + path = Transaction; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -4683,7 +4915,6 @@ 92E5F3D62CDBB3BF00B7AD98 /* SentrySampling.h in Headers */, 92672BB629C9A2A9006B021C /* SentryBreadcrumb+Private.h in Headers */, 03BCC38E27E2A377003232C7 /* SentryProfilingConditionals.h in Headers */, - 0ADC33EE28D9BB890078D980 /* SentryUIDeviceWrapper.h in Headers */, 848A451A2BBF8D33006AAAEC /* SentryContinuousProfiler.h in Headers */, 8E133FA625E72EB400ABD0BF /* SentrySamplingContext.h in Headers */, 0A9BF4E428A114B50068D266 /* SentryViewHierarchyIntegration.h in Headers */, @@ -4706,7 +4937,6 @@ 63FE717720DA4C1100CDBAE8 /* SentryCrashReportWriter.h in Headers */, 84DEE86B2B686BD400A7BC17 /* SentrySamplerDecision.h in Headers */, 7B4E23BE251A2BD500060D68 /* SentryCrashIntegrationSessionHandler.h in Headers */, - 7B88F2FE24BC5A4C00ADF90A /* SentrySdkInfo.h in Headers */, D4291A692DD61A3F00772088 /* SentryDispatchQueueProviderProtocol.h in Headers */, 7BCFBD672681C95000BC27D8 /* SentryScopeObserver.h in Headers */, D81A346C291AECC7005A27A9 /* PrivateSentrySDKOnly.h in Headers */, @@ -4719,19 +4949,15 @@ 0A2D8DA8289BC905008720F6 /* SentryViewHierarchyProvider.h in Headers */, 8EAE980C261E9F530073B6B3 /* SentryUIViewControllerPerformanceTracker.h in Headers */, 63FE717D20DA4C1100CDBAE8 /* SentryCrashCachedData.h in Headers */, - 7BC9A20028F41016001E7C4C /* SentryMeasurementValue.h in Headers */, - 7BBC826D25DFCFDE005F1ED8 /* SentryInAppLogic.h in Headers */, 03BCC38A27E1BF49003232C7 /* SentryTime.h in Headers */, 925824C22CB5897700C9B20B /* SentrySessionReplayIntegration-Hybrid.h in Headers */, 7B0A54222521C21E00A71716 /* SentryFrameRemover.h in Headers */, 63FE70CD20DA4C1000CDBAE8 /* SentryCrashDoctor.h in Headers */, - D8C67E9B28000E24007E326E /* SentryUIApplication.h in Headers */, 7B6438AA26A70F24000D0F65 /* UIViewController+Sentry.h in Headers */, 33EB2A912C3412E4004FED3D /* SentryWithoutUIKit.h in Headers */, 639FCFAC1EBC811400778193 /* SentryUser.h in Headers */, F44858132E03579D0013E63B /* SentryCrashDynamicLinker+Test.h in Headers */, D8CB74192947285A00A5F964 /* SentryEnvelopeItemHeader.h in Headers */, - D40604492DD2472600C40DC0 /* SentryNSApplication.h in Headers */, 7D7F0A5F23DF3D2C00A4629C /* SentryGlobalEventProcessor.h in Headers */, D867063D27C3BC2400048851 /* SentryCoreDataTrackingIntegration.h in Headers */, 0A2D8D5D289815EB008720F6 /* SentryBaseIntegration.h in Headers */, @@ -4746,6 +4972,7 @@ 03F84D2527DD414C008FE43F /* SentryThreadState.hpp in Headers */, 8E4E7C6D25DAAAFE006AB9E2 /* SentryTransaction.h in Headers */, 63FE715D20DA4C1100CDBAE8 /* SentryCrashSymbolicator.h in Headers */, + FAE2DABA2E1F318900262307 /* SentryProfilingSwiftHelpers.h in Headers */, D8ACE3CF2762187D00F5A213 /* SentryFileIOTrackingIntegration.h in Headers */, 7BECF42226145C5D00D9826E /* SentryMechanismMeta.h in Headers */, 63FE718920DA4C1100CDBAE8 /* SentryCrash.h in Headers */, @@ -4761,6 +4988,7 @@ 7BAF3DD92440AEC8008A5414 /* SentryRequestManager.h in Headers */, 62862B1C2B1DDBC8009B16E3 /* SentryDelayedFrame.h in Headers */, 627E7589299F6FE40085504D /* SentryInternalDefines.h in Headers */, + FA3854362E267DA60045A563 /* SentryUser+Serialize.h in Headers */, 7BE3C77B2446111500A38442 /* SentryRateLimitParser.h in Headers */, 7D0637032382B34300B30749 /* SentryScope.h in Headers */, 03F84D2727DD414C008FE43F /* SentryMachLogging.hpp in Headers */, @@ -4769,12 +4997,11 @@ 8E4A037825F6F52100000D77 /* SentrySampleDecision.h in Headers */, 63FE717920DA4C1100CDBAE8 /* SentryCrashReportStore.h in Headers */, 0AAE202128ED9BCC00D0CD80 /* SentryReachability.h in Headers */, - D858FA662A29EAB3002A3503 /* SentryBinaryImageCache.h in Headers */, A839D89824864B80003B7AFD /* SentrySystemEventBreadcrumbs.h in Headers */, 7B14089624878F090035403D /* SentryCrashStackEntryMapper.h in Headers */, 63FE714920DA4C1100CDBAE8 /* SentryCrashStackCursor_Backtrace.h in Headers */, 7BFC169B2524995700FF6266 /* SentryMessage.h in Headers */, - 7B18DE4028D9F748004845C6 /* SentryNSNotificationCenterWrapper.h in Headers */, + 7B18DE4028D9F748004845C6 /* SentryNotificationNames.h in Headers */, 03F84D1E27DD414C008FE43F /* SentryBacktrace.hpp in Headers */, 629258592DAFA57F0049388F /* SentryCrashCxaThrowSwapper.h in Headers */, 63AA76991EB9C1C200D153DE /* SentryDefines.h in Headers */, @@ -4782,11 +5009,11 @@ 84AF45A629A7FFA500FBB177 /* SentryProfiledTracerConcurrency.h in Headers */, 7B2A70DB27D607CF008B0D15 /* SentryThreadWrapper.h in Headers */, 8EAE980B261E9F530073B6B3 /* SentryPerformanceTracker.h in Headers */, + F48F75732E5FA649009D4E7D /* SentryBinaryImageCacheCallbacks.h in Headers */, 63FE718520DA4C1100CDBAE8 /* SentryCrashC.h in Headers */, 8EA1ED0D2669028C00E62B98 /* SentryUIViewControllerSwizzling.h in Headers */, D820CDB82BB1895F00BA339D /* SentrySessionReplayIntegration.h in Headers */, F49D419C2DEA30C300D9244E /* SentryCrashExceptionApplicationHelper.h in Headers */, - 7B98D7E425FB7A7200C5A389 /* SentryAppState.h in Headers */, 7BDEAA022632A4580001EA25 /* SentryOptions+Private.h in Headers */, A8AFFCCD29069C3E00967CD7 /* SentryHttpStatusCodeRange.h in Headers */, D83D079B2B7F9D1C00CC9674 /* SentryMsgPackSerializer.h in Headers */, @@ -4794,15 +5021,14 @@ 15E0A8EA240F2C9000F044E3 /* SentrySerialization.h in Headers */, 63FE70EF20DA4C1000CDBAE8 /* SentryCrashMonitor_AppState.h in Headers */, 635B3F381EBC6E2500A6176D /* SentryAsynchronousOperation.h in Headers */, - 7BD4BD4727EB2A3D0071F4FF /* SentryDiscardedEvent.h in Headers */, 7BBD18972449DC1D00427C76 /* SentryRateLimits.h in Headers */, 844EDC76294144DB00C86F34 /* SentrySystemWrapper.h in Headers */, 7B3B473025D6CBFC00D01640 /* SentryNSError.h in Headers */, 630436101EC0600A00C4D3FA /* SentrySerializable.h in Headers */, 63FE70DD20DA4C1000CDBAE8 /* SentryCrashMonitor_Signal.h in Headers */, 63FE710320DA4C1000CDBAE8 /* SentryCrashMachineContext_Apple.h in Headers */, - 844EDC6F294143B900C86F34 /* SentryNSProcessInfoWrapper.h in Headers */, D8479328278873A100BE8E99 /* SentryByteCountFormatter.h in Headers */, + 928207C42E251B8F009285A4 /* SentryScope+PrivateSwift.h in Headers */, 63AA76981EB9C1C200D153DE /* SentryClient.h in Headers */, 0A9E917128DC7E7000FB4182 /* SentryInternalCDefines.h in Headers */, 63FE711F20DA4C1000CDBAE8 /* SentryCrashObjC.h in Headers */, @@ -4815,16 +5041,17 @@ 33EB2A922C341300004FED3D /* Sentry.h in Headers */, 7B3398632459C14000BD9C96 /* SentryEnvelopeRateLimit.h in Headers */, 6304360A1EC0595B00C4D3FA /* SentryNSDataUtils.h in Headers */, - 7BF9EF7C2722B90E00B5BBEF /* SentryDefaultObjCRuntimeWrapper.h in Headers */, + FA6555142E30181B009917BC /* SentrySDKInternal.h in Headers */, 63FE718720DA4C1100CDBAE8 /* SentryCrashReportVersion.h in Headers */, 0A56DA5F28ABA01B00C400D5 /* SentryTransactionContext+Private.h in Headers */, 8E7C98312693E1CC00E6336C /* SentryTraceHeader.h in Headers */, 62C316812B1F2E93000D7031 /* SentryDelayedFramesTracker.h in Headers */, 92D957772E05A4F300E20E66 /* SentryAsyncLog.h in Headers */, + 92EC54CE2E1EB54B00A10AC2 /* SentryClient+Logs.h in Headers */, 7BBD18912449BE9000427C76 /* SentryDefaultRateLimits.h in Headers */, 7B8713AE26415ADF006D6004 /* SentryAppStartTrackingIntegration.h in Headers */, 7B7D873224864BB900D2ECFF /* SentryCrashMachineContextWrapper.h in Headers */, - 861265F92404EC1500C4AFDE /* NSArray+SentrySanitize.h in Headers */, + 861265F92404EC1500C4AFDE /* SentryArray.h in Headers */, 63FE712320DA4C1000CDBAE8 /* SentryCrashID.h in Headers */, 7DC27EC523997EB7006998B5 /* SentryAutoBreadcrumbTrackingIntegration.h in Headers */, 63FE707F20DA4C1000CDBAE8 /* SentryCrashVarArgs.h in Headers */, @@ -4833,7 +5060,6 @@ 7BC9A20228F41350001E7C4C /* SentryMeasurementUnit.h in Headers */, 7B8ECBFA26498907005FE2EF /* SentryAppStateManager.h in Headers */, 639FCFA01EBC804600778193 /* SentryException.h in Headers */, - D406044B2DD2483D00C40DC0 /* SentryApplication.h in Headers */, 7BA235632600B61200E12865 /* SentryInternalNotificationNames.h in Headers */, 7BAF3DB9243C9777008A5414 /* SentryTransport.h in Headers */, 845C16D52A622A5B00EC9519 /* SentryTracer+Private.h in Headers */, @@ -4848,6 +5074,7 @@ D456B4382D706BFE007068CB /* SentrySpanDataKey.h in Headers */, 7B77BE3527EC8445003C9020 /* SentryDiscardReasonMapper.h in Headers */, 7B610D602512390E00B0B5D9 /* SentrySDK+Private.h in Headers */, + FAF120182E70C08F006E1DA3 /* SentryEnvelopeHeaderHelper.h in Headers */, 62A456E12B03704A003F19A1 /* SentryUIEventTrackerMode.h in Headers */, 03F84D2327DD414C008FE43F /* SentryThreadHandle.hpp in Headers */, 7B6C5EE0264E8E050010D138 /* SentryFramesTracker.h in Headers */, @@ -4858,20 +5085,17 @@ 15360CD2243277A000112302 /* SentrySessionTracker.h in Headers */, 63FE718B20DA4C1100CDBAE8 /* SentryCrashReport.h in Headers */, 7D0FCFB22379B915004DD83A /* SentryHub.h in Headers */, - 7B7A30C624B48321005A4C6E /* SentryCrashWrapper.h in Headers */, 92F6726B29C8B7B100BFD34D /* SentryUser+Private.h in Headers */, 7BE1E33224F7E3B6009D3AD0 /* SentryMigrateSessionInit.h in Headers */, 632F43501F581D5400A18A36 /* SentryCrashExceptionApplication.h in Headers */, 7B85DC1E24EFAFCD007D01D2 /* SentryClient+Private.h in Headers */, A8AFFCCF2906C03700967CD7 /* SentryRequest.h in Headers */, - 7BD4BD4327EB29BA0071F4FF /* SentryClientReport.h in Headers */, D82859442C3E753C009A28AA /* SentrySessionReplaySyncC.h in Headers */, 8459FCBE2BD73E820038E9C9 /* SentryProfilerSerialization.h in Headers */, - 7B2BB0032966F55900A1E102 /* SentryOptions+HybridSDKs.h in Headers */, + 7B2BB0032966F55900A1E102 /* SentryOptionsInternal.h in Headers */, 7BF9EF762722B34700B5BBEF /* SentrySubClassFinder.h in Headers */, 7BC852332458802C005A70F0 /* SentryDataCategoryMapper.h in Headers */, 7BDB03B7251364F800BAE198 /* _SentryDispatchQueueWrapperInternal.h in Headers */, - 7BF9EF842722D07B00B5BBEF /* SentryObjCRuntimeWrapper.h in Headers */, 621AE74B2C626C230012E730 /* SentryANRTrackerV2.h in Headers */, 639889B71EDECFA800EA7442 /* SentryBreadcrumbTracker.h in Headers */, 632331F9240506DF008D91D6 /* SentryScope+Private.h in Headers */, @@ -4887,6 +5111,7 @@ 63FE70EB20DA4C1000CDBAE8 /* SentryCrashMonitor_MachException.h in Headers */, 7B30B67C26527886006B2752 /* SentryDisplayLinkWrapper.h in Headers */, D456B4362D706BF2007068CB /* SentryTraceOrigin.h in Headers */, + FAE80C242E4695B40010A595 /* SentryEvent+Serialize.h in Headers */, 7BD86ECF264A7C77005439DB /* SentryAppStartMeasurement.h in Headers */, 0354A22B2A134D9C003C3A04 /* SentryProfilerState.h in Headers */, 7DC8310A2398283C0043DD9A /* SentryCrashIntegration.h in Headers */, @@ -4900,7 +5125,6 @@ 63FE710920DA4C1000CDBAE8 /* SentryCrashFileUtils.h in Headers */, D865892F29D6ECA7000BE151 /* SentryCrashBinaryImageCache.h in Headers */, 6344DDB41EC309E000D9160D /* SentryCrashReportSink.h in Headers */, - 7D427C62237B1D200046BAC8 /* SentrySDK.h in Headers */, D8C66A362A77B1F70015696A /* SentryPropagationContext.h in Headers */, D867063F27C3BC2400048851 /* SentryCoreDataTracker.h in Headers */, 7B6C5EDA264E8D860010D138 /* SentryFramesTrackingIntegration.h in Headers */, @@ -4910,13 +5134,10 @@ 7BD86EC5264A63F6005439DB /* SentrySysctl.h in Headers */, 63BE85701ECEC6DE00DC44F5 /* SentryDateUtils.h in Headers */, 63FE709520DA4C1000CDBAE8 /* SentryCrashReportFilterBasic.h in Headers */, - 844EDCE52947DC3100C86F34 /* SentryNSTimerFactory.h in Headers */, D8B088B629C9E3FF00213258 /* SentryTracerConfiguration.h in Headers */, 7B63459D280EBA6300CFA05A /* SentryUIEventTracker.h in Headers */, 7B7D873424864C6600D2ECFF /* SentryCrashDefaultMachineContextWrapper.h in Headers */, 7BA61CC8247D125400C130A8 /* SentryThreadInspector.h in Headers */, - 7BE1E32824F7AE08009D3AD0 /* SentrySession+Private.h in Headers */, - 7B5CAF7127F5953400ED0DB6 /* SentryEnvelope+Private.h in Headers */, 63FE713320DA4C1100CDBAE8 /* SentryCrashCPU.h in Headers */, 6271ADF32BA06D9B0098D2E9 /* SentryInternalSerializable.h in Headers */, D8853C842833EABC00700D64 /* SentryANRTrackerV1.h in Headers */, @@ -4941,6 +5162,7 @@ 622C08DB29E554B9002571D4 /* SentrySpanContext+Private.h in Headers */, D8AB40DB2806EC1900E5E9F7 /* SentryScreenshotIntegration.h in Headers */, 7BF9EF722722A84800B5BBEF /* SentryClassRegistrator.h in Headers */, + 84A898552E163072009A551E /* SentryProfileConfiguration.h in Headers */, 63FE715520DA4C1100CDBAE8 /* SentryCrashStackCursor_MachineContext.h in Headers */, 62E081A929ED4260000F69FC /* SentryBreadcrumbDelegate.h in Headers */, 15360CF02433A16D00112302 /* SentryInstallation.h in Headers */, @@ -4950,15 +5172,12 @@ 638DC9A01EBC6B6400A66E41 /* SentryRequestOperation.h in Headers */, 7B7A599526B692540060A676 /* SentryScreenFrames.h in Headers */, 6344DDB01EC308E400D9160D /* SentryCrashInstallationReporter.h in Headers */, - 8E25C95725F836EE00DC215B /* SentryRandom.h in Headers */, 7B5CAF7527F5A67C00ED0DB6 /* SentryNSURLRequestBuilder.h in Headers */, 63FE70ED20DA4C1000CDBAE8 /* SentryCrashMonitor_NSException.h in Headers */, 7BA61CB4247BC3EB00C130A8 /* SentryCrashBinaryImageProvider.h in Headers */, 63FE713D20DA4C1100CDBAE8 /* SentryAsyncSafeLog.h in Headers */, D43A2A102DD47FB700114724 /* SentryWeakMap.h in Headers */, D8A3649D2C91AA3300AC569B /* SentryReplayApi.h in Headers */, - 15E0A8E1240C41CE00F044E3 /* SentryEnvelope.h in Headers */, - 7BC852392458830A005A70F0 /* SentryEnvelopeItemType.h in Headers */, 63AA769D1EB9C57A00D153DE /* SentryError.h in Headers */, 63FE714F20DA4C1100CDBAE8 /* SentryCrashNSErrorUtil.h in Headers */, 84A7890A2C0E9F6400FF0803 /* SentrySpan+Private.h in Headers */, @@ -4976,7 +5195,7 @@ 6292585E2DAFA8290049388F /* SentryCrashMach-O.h in Headers */, 63FE715320DA4C1100CDBAE8 /* SentryCrashObjCApple.h in Headers */, 63FE710120DA4C1000CDBAE8 /* SentryCrashDate.h in Headers */, - 7B4E24FC251C97B500060D68 /* SentrySession.h in Headers */, + 7B4E24FC251C97B500060D68 /* SentrySessionInternal.h in Headers */, D8B665BC2B95F73200BD0E7B /* SentryPrivate.h in Headers */, 7B7D872C2486480B00D2ECFF /* SentryStacktraceBuilder.h in Headers */, 7B42C48027E08F33009B58C2 /* SentryDependencyContainer.h in Headers */, @@ -4990,6 +5209,7 @@ 639FCF9C1EBC7F9500778193 /* SentryThread.h in Headers */, 63FE716B20DA4C1100CDBAE8 /* SentryCrashJSONCodecObjC.h in Headers */, D4FC68172DD632E7001B74FF /* SentryDispatchSourceProviderProtocol.h in Headers */, + FAB7BBA92E2577A6007301E1 /* SentryModels+Serializable.h in Headers */, 63AA76A51EB9CBC200D153DE /* SentryDsn.h in Headers */, 844EDD6C2949387000C86F34 /* SentryMetricProfiler.h in Headers */, F452438A2DE65968003E8F50 /* ExceptionCatcher.h in Headers */, @@ -5239,6 +5459,12 @@ ); productRefGroup = 6327C5D41EB8A783004E799B /* Products */; projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 846D3F132E286ECF00D4E7E3 /* Products */; + ProjectRef = 846D3F102E286ECF00D4E7E3 /* DuplicatedSDKTest.xcodeproj */; + }, + ); projectRoot = ""; targets = ( 63AA759A1EB8AEF500D153DE /* Sentry */, @@ -5253,6 +5479,44 @@ }; /* End PBXProject section */ +/* Begin PBXReferenceProxy section */ + 846D3F272E286ECF00D4E7E3 /* DuplicatedSDKTest.app */ = { + isa = PBXReferenceProxy; + fileType = wrapper.application; + path = DuplicatedSDKTest.app; + remoteRef = 846D3F262E286ECF00D4E7E3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 846D3F292E286ECF00D4E7E3 /* ModuleA.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ModuleA.framework; + remoteRef = 846D3F282E286ECF00D4E7E3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 846D3F2B2E286ECF00D4E7E3 /* ModuleB.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = ModuleB.framework; + remoteRef = 846D3F2A2E286ECF00D4E7E3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 846D3F2D2E286ECF00D4E7E3 /* UITest-DuplicatedSDK.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "UITest-DuplicatedSDK.xctest"; + remoteRef = 846D3F2C2E286ECF00D4E7E3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 846D3F2F2E286ECF00D4E7E3 /* Unit Tests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = "Unit Tests.xctest"; + remoteRef = 846D3F2E2E286ECF00D4E7E3 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + /* Begin PBXResourcesBuildPhase section */ 63AA75991EB8AEF500D153DE /* Resources */ = { isa = PBXResourcesBuildPhase; @@ -5330,17 +5594,20 @@ 0A2D8D9628997845008720F6 /* NSLocale+Sentry.m in Sources */, 7B0DC730288698F70039995F /* NSMutableDictionary+Sentry.m in Sources */, 628094742D39584C00B3F18B /* SentryUserCodable.swift in Sources */, - 7BD4BD4527EB29F50071F4FF /* SentryClientReport.m in Sources */, 631E6D341EBC679C00712345 /* SentryQueueableRequestManager.m in Sources */, 7B8713B426415BAA006D6004 /* SentryAppStartTracker.m in Sources */, 7BDB03BB2513652900BAE198 /* _SentryDispatchQueueWrapperInternal.m in Sources */, FA6FC0A32E0B5ACE00ED2669 /* SentrySdkPackage.swift in Sources */, D8739D142BEE5049007D2F66 /* SentryRRWebSpanEvent.swift in Sources */, + FAAB2F972E4D345800FE8B7E /* SentryUIDeviceWrapper.swift in Sources */, 7B6C5EDE264E8DF00010D138 /* SentryFramesTracker.m in Sources */, D84F833E2A1CC401005828E0 /* SentrySwiftAsyncIntegration.m in Sources */, 7B6438AB26A70F24000D0F65 /* UIViewController+Sentry.m in Sources */, 84302A812B5767A50027A629 /* SentryLaunchProfiling.m in Sources */, 63AA76A31EB9CBAA00D153DE /* SentryDsn.m in Sources */, + D490648A2DFAE1F600555785 /* SentryScreenshotOptions.swift in Sources */, + FA6FC0AA2E0B6B1100ED2669 /* SentrySdkInfo.swift in Sources */, + FA94E6B22E6D265800576666 /* SentryEnvelope.swift in Sources */, 84DBC62C2CE82F12000C4904 /* SentryFeedback.swift in Sources */, F41362132E1C566100B84443 /* SentryScopePersistentStore+User.swift in Sources */, 63B818FA1EC34639002FDF4C /* SentryDebugMeta.m in Sources */, @@ -5355,11 +5622,13 @@ 621AE74D2C626C510012E730 /* SentryANRTrackerV2.m in Sources */, 84CFA4CA2C9DF884008DA5F4 /* SentryUserFeedbackWidget.swift in Sources */, FAEC270E2DF3526000878871 /* SentryUserFeedback.swift in Sources */, + FAF1201A2E70C0EE006E1DA3 /* SentryEnvelopeHeaderHelper.m in Sources */, F49D419E2DEA3D0600D9244E /* SentryCrashExceptionApplicationHelper.m in Sources */, D8ACE3C82762187200F5A213 /* SentryFileIOTracker.m in Sources */, 7BE3C77D2446112C00A38442 /* SentryRateLimitParser.m in Sources */, D8B088B729C9E3FF00213258 /* SentryTracerConfiguration.m in Sources */, FA7206E12E0B37C80072FDD4 /* SentryProfileCollector.mm in Sources */, + 9264E1EB2E2E385E00B077CF /* SentryLogMessage.swift in Sources */, 8ECC674A25C23A20000E2BF6 /* SentryTransactionContext.m in Sources */, 03BCC38C27E1C01A003232C7 /* SentryTime.mm in Sources */, A8F17B342902870300990B25 /* SentryHttpStatusCodeRange.m in Sources */, @@ -5374,10 +5643,8 @@ 7B63459B280EB9E200CFA05A /* SentryUIEventTrackingIntegration.m in Sources */, 15E0A8ED240F2CB000F044E3 /* SentrySerialization.m in Sources */, 7BC85235245880AE005A70F0 /* SentryDataCategoryMapper.m in Sources */, - 7B7A30C824B48389005A4C6E /* SentryCrashWrapper.m in Sources */, D8ACE3C92762187200F5A213 /* SentryFileIOTrackingIntegration.m in Sources */, 620078742D38F0DF0022CB67 /* SentryCodable.swift in Sources */, - F45243892DE65968003E8F50 /* ExceptionCatcher.m in Sources */, 63FE713B20DA4C1100CDBAE8 /* SentryCrashFileUtils.c in Sources */, 63FE716920DA4C1100CDBAE8 /* SentryCrashStackCursor.c in Sources */, 7BA61CCA247D128B00C130A8 /* SentryThreadInspector.m in Sources */, @@ -5386,7 +5653,6 @@ 7BA0C0482805600A003E0326 /* SentryTransportAdapter.m in Sources */, 63FE712920DA4C1000CDBAE8 /* SentryCrashCPU_arm.c in Sources */, 03F84D3427DD4191008FE43F /* SentryThreadMetadataCache.cpp in Sources */, - 7B88F30024BC5A7D00ADF90A /* SentrySdkInfo.m in Sources */, 62862B1E2B1DDC35009B16E3 /* SentryDelayedFrame.m in Sources */, 84AC61D729F75A98009EEF61 /* SentryDispatchFactory.m in Sources */, 15360CD62432832400112302 /* SentryAutoSessionTrackingIntegration.m in Sources */, @@ -5404,29 +5670,28 @@ F458D1172E186DF20028273E /* SentryScopePersistentStore+Fingerprint.swift in Sources */, D8CB7417294724CC00A5F964 /* SentryEnvelopeAttachmentHeader.m in Sources */, D84793262788737D00BE8E99 /* SentryByteCountFormatter.m in Sources */, + FAEFA12F2E4FAE1900C431D9 /* SentrySDKSettings.swift in Sources */, 63AA769E1EB9C57A00D153DE /* SentryError.mm in Sources */, 7B8713B026415B22006D6004 /* SentryAppStartTrackingIntegration.m in Sources */, 8E133FA225E72DEF00ABD0BF /* SentrySamplingContext.m in Sources */, + F451FAA62E0B304E0050ACF2 /* LoadValidator.swift in Sources */, D81988C02BEBFFF70020E36C /* SentryReplayRecording.swift in Sources */, 7B6C5F8726034395007F7DFF /* SentryWatchdogTerminationLogic.m in Sources */, - 7BBC827125DFD039005F1ED8 /* SentryInAppLogic.m in Sources */, 63FE708D20DA4C1000CDBAE8 /* SentryCrashReportFilterBasic.m in Sources */, 63FE718120DA4C1100CDBAE8 /* SentryCrashDoctor.m in Sources */, 63FE713720DA4C1100CDBAE8 /* SentryCrashCPU_x86_64.c in Sources */, 8ECC674725C23A20000E2BF6 /* SentrySpanContext.m in Sources */, D473ACD72D8090FC000F1CC6 /* FileManager+SentryTracing.swift in Sources */, D4AF00212D2E92FD00F5F3D7 /* SentryNSFileManagerSwizzling.m in Sources */, - 7B18DE4228D9F794004845C6 /* SentryNSNotificationCenterWrapper.m in Sources */, 639FCFA91EBC80CC00778193 /* SentryFrame.m in Sources */, - D858FA672A29EAB3002A3503 /* SentryBinaryImageCache.m in Sources */, 8E564AEA267AF22600FE117D /* SentryNetworkTracker.m in Sources */, 15360CED2433A15500112302 /* SentryInstallation.m in Sources */, - 7B98D7E825FB7BCD00C5A389 /* SentryAppState.m in Sources */, D8370B6A273DF1E900F66E2D /* SentryNSURLSessionTaskSearch.m in Sources */, 7B30B67E26527894006B2752 /* SentryDisplayLinkWrapper.m in Sources */, 63FE711D20DA4C1000CDBAE8 /* SentryCrashCPU_arm64.c in Sources */, 844EDC77294144DB00C86F34 /* SentrySystemWrapper.mm in Sources */, D451ED5F2D92ECDE00C9BEA8 /* SentryReplayFrame.swift in Sources */, + FA94E71C2E6F26C500576666 /* SentrySerialization+ReplayRecording.swift in Sources */, D49480D72DC23FE300A3B6E9 /* SentrySessionReplayDelegate.swift in Sources */, FA67DCC12DDBD4C800896B02 /* SentrySDKLog+Configure.swift in Sources */, 6281C5722D3E4F12009D0978 /* DecodeArbitraryData.swift in Sources */, @@ -5437,13 +5702,16 @@ 7BA61CAD247BAA0B00C130A8 /* SentryDebugImageProvider.m in Sources */, 63FE70E720DA4C1000CDBAE8 /* SentryCrashMonitor.c in Sources */, 84354E1229BF944900CDBB8B /* SentryProfileTimeseries.m in Sources */, + FA94E6912E6B92C100576666 /* SentryClientReport.swift in Sources */, 7D5C441C237C2E1F00DAB0A3 /* SentryHub.m in Sources */, 84E13B842CBF1D91003B52EC /* SentryUserFeedbackWidgetButtonMegaphoneIconView.swift in Sources */, 63FE715920DA4C1100CDBAE8 /* SentryCrashCPU_x86_32.c in Sources */, + 92235CAE2E15549C00865983 /* SentryLogger.swift in Sources */, D8C66A372A77B1F70015696A /* SentryPropagationContext.m in Sources */, 7BE912AD272162D900E49E62 /* SentryNoOpSpan.m in Sources */, 63FE710D20DA4C1000CDBAE8 /* SentryCrashStackCursor_MachineContext.c in Sources */, 63FE70E120DA4C1000CDBAE8 /* SentryCrashMonitor_CPPException.cpp in Sources */, + FA458CC32E691A730061B13D /* SentryProcessInfo.swift in Sources */, D8F6A2472885512100320515 /* SentryPredicateDescriptor.m in Sources */, A839D89A24864BA8003B7AFD /* SentrySystemEventBreadcrumbs.m in Sources */, 84A305582BC9EF8C00D84283 /* SentryTraceProfiler.mm in Sources */, @@ -5457,13 +5725,11 @@ 63FE716720DA4C1100CDBAE8 /* SentryCrashCPU.c in Sources */, 63FE717320DA4C1100CDBAE8 /* SentryCrashC.c in Sources */, 6293F5752D422A95002BC3BD /* SentryStacktraceCodable.swift in Sources */, - FA3734822E0EEA670091EF24 /* SentryScreenshot.swift in Sources */, 63FE712120DA4C1000CDBAE8 /* SentryCrashSymbolicator.c in Sources */, 627C77892D50B6840055E966 /* SentryBreadcrumbCodable.swift in Sources */, 63FE70D720DA4C1000CDBAE8 /* SentryCrashMonitor_MachException.c in Sources */, 7B96572226830D2400C66E25 /* SentryScopeSyncC.c in Sources */, 0A9BF4E228A114940068D266 /* SentryViewHierarchyIntegration.m in Sources */, - 0ADC33EC28D9BB780078D980 /* SentryUIDeviceWrapper.m in Sources */, 7BBD188B244841FB00427C76 /* SentryHttpDateParser.m in Sources */, D8AFC03D2BDA79BF00118BE1 /* SentryReplayVideoMaker.swift in Sources */, 840A11122B61E27500650D02 /* SentrySamplerDecision.m in Sources */, @@ -5471,7 +5737,6 @@ 8E4E7C8225DAB2A5006AB9E2 /* SentryTracer.m in Sources */, 848A45192BBF8D33006AAAEC /* SentryContinuousProfiler.mm in Sources */, D81988C32BEC189C0020E36C /* SentryRRWebMetaEvent.swift in Sources */, - 15E0A8E5240C457D00F044E3 /* SentryEnvelope.m in Sources */, F458D1192E186E000028273E /* SentryScopePersistentStore+Extras.swift in Sources */, 8EC3AE7A25CA23B600E7591A /* SentrySpan.m in Sources */, 6360850E1ED2AFE100E8599E /* SentryBreadcrumb.m in Sources */, @@ -5495,6 +5760,7 @@ 7BC63F0A28081288009D9E37 /* SentrySwizzleWrapper.m in Sources */, 6276350C2D59FACC00F7CEF6 /* SentryEventDecoder.swift in Sources */, 7B6C5EDC264E8DA80010D138 /* SentryFramesTrackingIntegration.m in Sources */, + F4FE9E082E6248E40014FED5 /* SentryCrashWrapper.swift in Sources */, 849B8F9A2C6E906900148E1F /* SentryUserFeedbackConfiguration.swift in Sources */, 63295AF71EF3C7DB002D4490 /* SentryNSDictionarySanitize.m in Sources */, 7B8ECBFC26498958005FE2EF /* SentryAppStateManager.m in Sources */, @@ -5504,14 +5770,18 @@ FA67DCF82DDBD4EA00896B02 /* SentryProfileOptions.swift in Sources */, FA67DCF92DDBD4EA00896B02 /* HTTPHeaderSanitizer.swift in Sources */, FA67DCFA2DDBD4EA00896B02 /* SentryViewRendererV2.swift in Sources */, + FAAB30F32E4E8F2C00FE8B7E /* SentryInAppLogic.swift in Sources */, FA67DCFB2DDBD4EA00896B02 /* SentryId.swift in Sources */, FA67DCFC2DDBD4EA00896B02 /* SentryFramesDelayResult.swift in Sources */, FA67DCFD2DDBD4EA00896B02 /* SentryANRTracker.swift in Sources */, FA67DCFE2DDBD4EA00896B02 /* SentryANRTrackerV2Delegate.swift in Sources */, + FABE8E152E307A5E0040809A /* SentrySDK.swift in Sources */, FA67DCFF2DDBD4EA00896B02 /* SentryMXManager.swift in Sources */, D41415A72DEEE532003B14D5 /* SentryRedactViewHelper.swift in Sources */, + FA66143A2E4B593900657755 /* SentryApplicationExtensions.swift in Sources */, FA67DD002DDBD4EA00896B02 /* SentryMaskRenderer.swift in Sources */, FA67DD012DDBD4EA00896B02 /* SentryMXCallStackTree.swift in Sources */, + FAAB29F12E3D252300ACD577 /* SentrySession.swift in Sources */, FA67DD022DDBD4EA00896B02 /* SentryViewScreenshotProvider.swift in Sources */, FA67DD032DDBD4EA00896B02 /* SentryTransactionNameSource.swift in Sources */, FA67DD042DDBD4EA00896B02 /* SwiftDescriptor.swift in Sources */, @@ -5523,37 +5793,44 @@ FA67DD0A2DDBD4EA00896B02 /* SentryBaggageSerialization.swift in Sources */, FA67DD0B2DDBD4EA00896B02 /* UIViewExtensions.swift in Sources */, FA67DD0C2DDBD4EA00896B02 /* SentryMaskRendererV2.swift in Sources */, + FA6555162E30182B009917BC /* SentrySDKInternal.m in Sources */, FA67DD0D2DDBD4EA00896B02 /* SentryUIRedactBuilder.swift in Sources */, FA67DD0E2DDBD4EA00896B02 /* SentryFileContents.swift in Sources */, FA67DD0F2DDBD4EA00896B02 /* SentryViewControllerBreadcrumbTracking.swift in Sources */, FA67DD102DDBD4EA00896B02 /* StringExtensions.swift in Sources */, FA67DD112DDBD4EA00896B02 /* SentryANRType.swift in Sources */, FA67DD122DDBD4EA00896B02 /* Locks.swift in Sources */, + FA21F0B42E4A2A80008B4E5A /* SentryAppState.swift in Sources */, FA67DD132DDBD4EA00896B02 /* NumberExtensions.swift in Sources */, FA67DD142DDBD4EA00896B02 /* SentryGraphicsImageRenderer.swift in Sources */, FA4C32972DF7513F001D7B00 /* SentryExperimentalOptions.swift in Sources */, FA67DD152DDBD4EA00896B02 /* UrlSanitized.swift in Sources */, FA67DD162DDBD4EA00896B02 /* SentryViewPhotographer.swift in Sources */, + F48F75712E5FA630009D4E7D /* SentryBinaryImageCacheCallbacks.m in Sources */, FA67DD182DDBD4EA00896B02 /* UIImageHelper.swift in Sources */, FA67DD192DDBD4EA00896B02 /* SwizzleClassNameExclude.swift in Sources */, 7B2A70DD27D6083D008B0D15 /* SentryThreadWrapper.m in Sources */, D8ACE3C72762187200F5A213 /* SentryNSDataSwizzling.m in Sources */, + F48F767C2E60B555009D4E7D /* SentryNSTimerFactory.swift in Sources */, 638DC9A11EBC6B6400A66E41 /* SentryRequestOperation.m in Sources */, + FA6615052E4BA4D700657755 /* ThreadSafeApplication.swift in Sources */, 63AA767A1EB8D20500D153DE /* SentryLogC.m in Sources */, 84B0DFF42CD2CF64007FB332 /* SentryUserFeedbackFormController.swift in Sources */, 6344DDBA1EC3115C00D9160D /* SentryCrashReportConverter.m in Sources */, 63FE70FD20DA4C1000CDBAE8 /* SentryCrashCachedData.c in Sources */, A8F17B2E2901765900990B25 /* SentryRequest.m in Sources */, + FABE8E172E307A7F0040809A /* Dependencies.swift in Sources */, 7BE1E33424F7E3CB009D3AD0 /* SentryMigrateSessionInit.m in Sources */, + D4ECA4012E3CBEDE00C757EA /* SentryDummyPublicEmptyClass.m in Sources */, + D4ECA4022E3CBEDE00C757EA /* SentryDummyPrivateEmptyClass.m in Sources */, D80299502BA83A88000F0081 /* SentryPixelBuffer.swift in Sources */, - 15E0A8F22411A45A00F044E3 /* SentrySession.m in Sources */, - 844EDCE62947DC3100C86F34 /* SentryNSTimerFactory.m in Sources */, + 15E0A8F22411A45A00F044E3 /* SentrySessionInternal.m in Sources */, D83D079C2B7F9D1C00CC9674 /* SentryMsgPackSerializer.m in Sources */, D452FCBF2DDB6FD200AFF56F /* SentryWatchdogTerminationAttributesProcessor.swift in Sources */, 7B6D1261265F784000C9BE4B /* PrivateSentrySDKOnly.m in Sources */, 63BE85711ECEC6DE00DC44F5 /* SentryDateUtils.m in Sources */, + FA3AEE782E68E2830092283E /* SentryEnvelopeHeader.swift in Sources */, D451ED5D2D92ECD200C9BEA8 /* SentryOnDemandReplayError.swift in Sources */, - 7BD4BD4927EB2A5D0071F4FF /* SentryDiscardedEvent.m in Sources */, 628308612D50ADAC00EAEF77 /* SentryRequestCodable.swift in Sources */, 03F84D3827DD4191008FE43F /* SentryBacktrace.cpp in Sources */, D8739D182BEEA33F007D2F66 /* SentryLevelHelper.m in Sources */, @@ -5566,21 +5843,26 @@ 849B8F9C2C6E906900148E1F /* SentryUserFeedbackThemeConfiguration.swift in Sources */, F452437E2DE60B71003E8F50 /* SentryUseNSExceptionCallstackWrapper.m in Sources */, 63FE70D320DA4C1000CDBAE8 /* SentryCrashMonitor_AppState.c in Sources */, + FA1841832E4B457F005DEDC7 /* SentryApplication.swift in Sources */, 849B8F9D2C6E906900148E1F /* SentryUserFeedbackWidgetConfiguration.swift in Sources */, 620467AC2D3FFD230025F06C /* SentryNSErrorCodable.swift in Sources */, 639FCFA51EBC809A00778193 /* SentryStacktrace.m in Sources */, D84D2CC32C29AD120011AF8A /* SentrySessionReplay.swift in Sources */, + F4FE9DFD2E622CD70014FED5 /* SentryDefaultObjCRuntimeWrapper.swift in Sources */, + F4FE9DFE2E622CD70014FED5 /* SentryObjCRuntimeWrapper.swift in Sources */, + 84A898542E163072009A551E /* SentryProfileConfiguration.m in Sources */, 849B8F9B2C6E906900148E1F /* SentryUserFeedbackIntegrationDriver.swift in Sources */, FA3734862E0F09320091EF24 /* SentryDependencyContainerSwiftHelper.m in Sources */, 63FE70DF20DA4C1000CDBAE8 /* SentryCrashMonitorType.c in Sources */, D468C0622D3669A200964230 /* SentryFileIOTracker+SwiftHelpers.swift in Sources */, - 7BF9EF7E2722B91F00B5BBEF /* SentryDefaultObjCRuntimeWrapper.m in Sources */, + F49236EB2E5E4B2F00663673 /* SentryBinaryImageCache.swift in Sources */, 7BC3936E25B1AB72004F03D3 /* SentryLevelMapper.m in Sources */, 6304360B1EC0595B00C4D3FA /* SentryNSDataUtils.m in Sources */, D81988C52BEC18CA0020E36C /* SentryRRWebCustomEvent.swift in Sources */, 639889B81EDECFA800EA7442 /* SentryBreadcrumbTracker.m in Sources */, 84AF45A729A7FFA500FBB177 /* SentryProfiledTracerConcurrency.mm in Sources */, 7DC8310C2398283C0043DD9A /* SentryCrashIntegration.m in Sources */, + D45CE9752E5F454E00BFEDB2 /* SentryScreenshotSource.swift in Sources */, 03F84D3227DD4191008FE43F /* SentryProfiler.mm in Sources */, 635B3F391EBC6E2500A6176D /* SentryAsynchronousOperation.m in Sources */, 63FE717520DA4C1100CDBAE8 /* SentryCrash.m in Sources */, @@ -5591,10 +5873,9 @@ D85596F3280580F10041FF8B /* SentryScreenshotIntegration.m in Sources */, 92ECD73E2E05AD320063EC10 /* SentryLogLevel.swift in Sources */, 92ECD7402E05AD580063EC10 /* SentryLogAttribute.swift in Sources */, + FA01BCB22E69352A00968DFA /* SentryDiscardedEvent.swift in Sources */, 7BAF3DCE243DCBFE008A5414 /* SentryTransportFactory.m in Sources */, - 844EDC70294143B900C86F34 /* SentryNSProcessInfoWrapper.mm in Sources */, F4E3DCCB2E1579240093CB80 /* SentryScopePersistentStore.swift in Sources */, - 7D5C441A237C2E1F00DAB0A3 /* SentrySDK.m in Sources */, 7D65260E237F649E00113EA2 /* SentryScope.m in Sources */, D4EDF9842D0B2A210071E7B3 /* Data+SentryTracing.swift in Sources */, 84281C472A57905700EE88F2 /* SentrySample.m in Sources */, @@ -5607,6 +5888,7 @@ 639FCF9D1EBC7F9500778193 /* SentryThread.mm in Sources */, D88B30A92D48D8C3008DE513 /* SentryMaskingPreviewView.swift in Sources */, 849B8F992C6E906900148E1F /* SentryUserFeedbackFormConfiguration.swift in Sources */, + F4DC35562E1FFD620077CE89 /* SentryVideoFrameProcessor.swift in Sources */, 8E8C57A225EEFC07001CEEFA /* SentrySampling.m in Sources */, 8454CF8D293EAF9A006AC140 /* SentryMetricProfiler.m in Sources */, 63FE714120DA4C1100CDBAE8 /* SentryCrashDate.c in Sources */, @@ -5614,12 +5896,12 @@ 63FE70DB20DA4C1000CDBAE8 /* SentryCrashMonitor_System.m in Sources */, 7BA61CBB247BC5D800C130A8 /* SentryCrashDefaultBinaryImageProvider.m in Sources */, 63FE713120DA4C1100CDBAE8 /* SentryCrashDynamicLinker.c in Sources */, - 8E25C95325F836D000DC215B /* SentryRandom.m in Sources */, 03F84D3527DD4191008FE43F /* SentryThreadHandle.cpp in Sources */, 0A2D8DA9289BC905008720F6 /* SentryViewHierarchyProvider.m in Sources */, D84D2CDD2C2BF7370011AF8A /* SentryReplayEvent.swift in Sources */, D8BC28CC2BFF78220054DA4D /* SentryRRWebTouchEvent.swift in Sources */, D452FC592DDB4B1700AFF56F /* SentryWatchdogTerminationBreadcrumbProcessor.m in Sources */, + FAE2DAB82E1F317900262307 /* SentryProfilingSwiftHelpers.m in Sources */, 8EA1ED0B2668F8C400E62B98 /* SentryUIViewControllerSwizzling.m in Sources */, 7B98D7CF25FB650F00C5A389 /* SentryWatchdogTerminationTrackingIntegration.m in Sources */, 8E5D38DD261D4A3E000D363D /* SentryPerformanceTrackingIntegration.m in Sources */, @@ -5629,7 +5911,7 @@ D8A3649C2C91AA3300AC569B /* SentryReplayApi.m in Sources */, 7B42C48227E08F4B009B58C2 /* SentryDependencyContainer.m in Sources */, 639FCFAD1EBC811400778193 /* SentryUser.m in Sources */, - D40604472DD2471600C40DC0 /* SentryNSApplication.m in Sources */, + FA94E7242E6F339400576666 /* SentryEnvelopeItemType.swift in Sources */, 7DAC589123D8B2E0001CF26B /* SentryGlobalEventProcessor.m in Sources */, 7BBD189E244EC8D200427C76 /* SentryRetryAfterHeaderParser.m in Sources */, F41362152E1C568400B84443 /* SentryScopePersistentStore+Context.swift in Sources */, @@ -5639,8 +5921,11 @@ 7B14089824878F950035403D /* SentryCrashStackEntryMapper.m in Sources */, D8BC28C82BFF5EBB0054DA4D /* SentryTouchTracker.swift in Sources */, 63FE711720DA4C1000CDBAE8 /* SentryCrashStackCursor_Backtrace.c in Sources */, + FA3A42722E1C5F9B00A08C39 /* SentryNSNotificationCenterWrapper.swift in Sources */, 63FE70CB20DA4C1000CDBAE8 /* SentryCrashReportFixer.c in Sources */, + F4A930232E65FDBF006DA6EF /* SentryMobileProvisionParser.swift in Sources */, 63FE710F20DA4C1000CDBAE8 /* SentryCrashNSErrorUtil.m in Sources */, + FA34C1A32E692A5000BC52AA /* SentryEnvelopeItem.swift in Sources */, 8ECC674925C23A20000E2BF6 /* SentrySpanId.m in Sources */, 6344DDB51EC309E000D9160D /* SentryCrashReportSink.m in Sources */, D43B26D62D70964C007747FD /* SentrySpanOperation.m in Sources */, @@ -5651,28 +5936,29 @@ D8F67B1B2BE9728600C9197B /* SentrySRDefaultBreadcrumbConverter.swift in Sources */, 8EBF870926140D37001A6853 /* SentryPerformanceTracker.m in Sources */, D865893029D6ECA7000BE151 /* SentryCrashBinaryImageCache.c in Sources */, - 7BC9A20428F4166D001E7C4C /* SentryMeasurementValue.m in Sources */, D859696B27BECD8F0036A46E /* SentryCoreDataTrackingIntegration.m in Sources */, 7BD86EC7264A641D005439DB /* SentrySysctl.m in Sources */, 84281C432A578E5600EE88F2 /* SentryProfilerState.mm in Sources */, D859697327BECDD20036A46E /* SentryCoreDataSwizzling.m in Sources */, + FABB48B32E59310D0071397E /* SentryMeasurementValue.swift in Sources */, 639889BD1EDED18400EA7442 /* SentrySwizzle.m in Sources */, 8453421228BE855D00C22EEC /* SentrySampleDecision.m in Sources */, FA8E58F12E0AD4270049F69D /* SentryDispatchQueueWrapper.swift in Sources */, 7B7D872E2486482600D2ECFF /* SentryStacktraceBuilder.m in Sources */, - 861265FA2404EC1500C4AFDE /* NSArray+SentrySanitize.m in Sources */, + 861265FA2404EC1500C4AFDE /* SentryArray.m in Sources */, D802994E2BA836EF000F0081 /* SentryOnDemandReplay.swift in Sources */, D8603DD6284F8497000E1227 /* SentryBaggage.m in Sources */, + F4FE9DBD2E621F100014FED5 /* SentryRandom.swift in Sources */, 63FE711520DA4C1000CDBAE8 /* SentryCrashJSONCodec.c in Sources */, 03F84D3327DD4191008FE43F /* SentryMachLogging.cpp in Sources */, - D85852BA27EDDC5900C6D8AE /* SentryUIApplication.m in Sources */, + 92235CAC2E15369900865983 /* SentryLogBatcher.swift in Sources */, FAB3599A2E05D8080083D5E3 /* SentryEventSwiftHelper.m in Sources */, F41362112E1C55AF00B84443 /* SentryScopePersistentStore+Tags.swift in Sources */, - F458D11B2E186E0D0028273E /* SentryScopePersistentStore+Level.swift in Sources */, 7B4E375F258231FC00059C93 /* SentryAttachment.m in Sources */, 636085141ED47BE600E8599E /* SentryFileManager.m in Sources */, 63FE710B20DA4C1000CDBAE8 /* SentryCrashMach.c in Sources */, 63FE707720DA4C1000CDBAE8 /* SentryDictionaryDeepSearch.m in Sources */, + FACEED132E3179A10007B4AC /* SentyOptionsInternal.m in Sources */, 8482FA9C2DD7C397000E9283 /* SentryFeedbackAPI.m in Sources */, 7BC9A20628F41781001E7C4C /* SentryMeasurementUnit.m in Sources */, 63FE71A020DA4C1100CDBAE8 /* SentryCrashInstallation.m in Sources */, @@ -5744,6 +6030,7 @@ D808FB88281AB33C009A2A33 /* SentryUIEventTrackerTests.swift in Sources */, D49480D32DC23E9300A3B6E9 /* SentryReplayTypeTests.swift in Sources */, D8F8F5572B835BC600AC5465 /* SentryMsgPackSerializerTests.m in Sources */, + FA65551A2E3018A3009917BC /* SentrySDKTests.swift in Sources */, 0A283E79291A67E000EF4126 /* SentryUIDeviceWrapperTests.swift in Sources */, 63FE720D20DA66EC00CDBAE8 /* SentryCrashNSErrorUtilTests.m in Sources */, 69BEE6F72620729E006DF9DF /* UrlSessionDelegateSpy.swift in Sources */, @@ -5757,12 +6044,13 @@ 8431EE5B29ADB8EA00D8DC56 /* SentryTimeTests.m in Sources */, 7B0A54562523178700A71716 /* SentryScopeSwiftTests.swift in Sources */, 7B5B94332657A816002E474B /* SentryAppStartTrackingIntegrationTests.swift in Sources */, + 62278CA82E30B21A0022ABC6 /* SentryHttpTransportFlushIntegrationTests.swift in Sources */, 0A5370A128A3EC2400B2DCDE /* SentryViewHierarchyProviderTests.swift in Sources */, D8FFE50C2703DBB400607131 /* SwizzlingCallTests.swift in Sources */, 7BFAA6E7297AA16A00E7E02E /* SentryCrashMonitor_CppException_Tests.mm in Sources */, 9286059929A50BAB00F96038 /* SentryGeoTests.swift in Sources */, 621655662DB12A8900810504 /* SentryCrashMach-OTests.m in Sources */, - D8B76B0828081461000A58C4 /* TestSentryScreenShot.swift in Sources */, + D8B76B0828081461000A58C4 /* TestSentryScreenshotProvider.swift in Sources */, A8AFFCD22907DA7600967CD7 /* SentryHttpStatusCodeRangeTests.swift in Sources */, 7BE2C7F8257000A4003B66C7 /* SentryTestIntegration.m in Sources */, 84A8892128DBD8D600C51DFD /* SentryDeviceTests.m in Sources */, @@ -5800,14 +6088,17 @@ D4F2B5352D0C69D500649E42 /* SentryCrashCTests.swift in Sources */, 7B56D73524616E5600B842DA /* SentryConcurrentRateLimitsDictionaryTests.swift in Sources */, 7B7D8730248648AD00D2ECFF /* SentryStacktraceBuilderTests.swift in Sources */, + FA21A2EF2E60E9CB00E7EADB /* EnvelopeComparison.swift in Sources */, 62E081AB29ED4322000F69FC /* SentryBreadcrumbTestDelegate.swift in Sources */, D8751FA5274743710032F4DE /* SentryNSURLSessionTaskSearchTests.swift in Sources */, D86F419827C8FEFA00490520 /* SentryCoreDataTrackerExtension.swift in Sources */, + F4DCC9E52E4AACE0008ECE45 /* SentrySDKSettings+Equality.m in Sources */, 7BF536D124BDF3E7004FA6A2 /* SentryEnvelopeTests.swift in Sources */, 7B98D7E025FB73B900C5A389 /* SentryWatchdogTerminationTrackerTests.swift in Sources */, 63FE721620DA66EC00CDBAE8 /* SentryCrashReportFixer_Tests.m in Sources */, + D4D12E7A2DFC608800DC45C4 /* SentryScreenshotOptionsTests.swift in Sources */, 7B6C5ED6264E62CA0010D138 /* SentryTransactionTests.swift in Sources */, - D81FDF12280EA1060045E0E4 /* SentryScreenShotTests.swift in Sources */, + D81FDF12280EA1060045E0E4 /* SentryScreenshotSourceTests.swift in Sources */, D8019910286B089000C277F0 /* SentryCrashReportSinkTests.swift in Sources */, D885266427739D01001269FC /* SentryFileIOTrackingIntegrationTests.swift in Sources */, 7BBD18992449DE9D00427C76 /* TestRateLimits.swift in Sources */, @@ -5829,10 +6120,9 @@ 63FE721B20DA66EC00CDBAE8 /* Container+DeepSearch_Tests.m in Sources */, 8EA05EED267C2AB200C82B30 /* SentryNetworkTrackerTests.swift in Sources */, D4E3F35E2D4A877300F79E2B /* SentryNSDictionarySanitize+Tests.m in Sources */, - 7BA840A024A1EC6E00B718AA /* SentrySDKTests.swift in Sources */, + 7BA840A024A1EC6E00B718AA /* SentrySDKInternalTests.swift in Sources */, D8AE48BF2C578D540092A2A6 /* SentrySDKLog.swift in Sources */, D8F6A24E288553A800320515 /* SentryPredicateDescriptorTests.swift in Sources */, - 7B18DE4A28DA0C8B004845C6 /* SentryNSNotificationCenterWrapperTests.swift in Sources */, 7B0002322477F0520035FEF1 /* SentrySessionTests.m in Sources */, 62CFD9AD2C99770B00834E1B /* SentryInvalidJSONString.m in Sources */, 62375FB92B47F9F000CC55F1 /* SentryDependencyContainerTests.swift in Sources */, @@ -5843,11 +6133,11 @@ D4E3F35D2D4A864600F79E2B /* SentryNSDictionarySanitizeTests.swift in Sources */, 7B984A9F28E572AF001F4BEE /* CrashReport.swift in Sources */, D4AF00252D2E93C400F5F3D7 /* SentryNSFileManagerSwizzlingTests.m in Sources */, - 7BED3576266F7BFF00EAA70D /* TestSentryCrashWrapper.m in Sources */, D46712622DCD059900D4074A /* SentryRedactDefaultOptionsTests.swift in Sources */, D480F9DB2DE47AF2009A0594 /* SentryScopePersistentStoreTests.swift in Sources */, + F4DC35582E1FFE1F0077CE89 /* SentryVideoFrameProcessorTests.swift in Sources */, + F48F74F32E5F9959009D4E7D /* SentryCrashBinaryImageCacheTests.m in Sources */, 7BC6EC18255C44540059822A /* SentryDebugMetaTests.swift in Sources */, - D8CCFC632A1520C900DE232E /* SentryBinaryImageCacheTests.m in Sources */, A811D867248E2770008A41EA /* SentrySystemEventBreadcrumbsTest.swift in Sources */, 7B82D54924E2A2D400EE670F /* SentryIdTests.swift in Sources */, 623FD9062D3FA9C800803EDA /* NSNumberDecodableWrapperTests.swift in Sources */, @@ -5860,7 +6150,9 @@ D86130122BB563FD004C0F5E /* SentrySessionReplayIntegrationTests.swift in Sources */, 7BFC16BA2524D4AF00FF6266 /* SentryMessage+Equality.m in Sources */, 92136D672C9D7660002A9FB8 /* SentryNSURLRequestBuilderTests.swift in Sources */, + F48E2E0A2E6637840073CB22 /* TestSentryCrashWrapper.swift in Sources */, D855B3E827D652AF00BCED76 /* SentryCoreDataTrackingIntegrationTest.swift in Sources */, + 9264E1ED2E2E397C00B077CF /* SentryLogMessageTests.swift in Sources */, D855AD62286ED6A4002573E1 /* SentryCrashTests.m in Sources */, D8AFC0012BD252B900118BE1 /* SentryOnDemandReplayTests.swift in Sources */, 0A9415BA28F96CAC006A5DD1 /* TestSentryReachability.swift in Sources */, @@ -5873,6 +6165,7 @@ 8EAE8E5E2681768000D6958B /* URLSessionTaskMock.m in Sources */, D8CE69BC277E39C700C6EC5C /* SentryFileIOTrackingIntegrationObjCTests.m in Sources */, D85D3BEA278DF63D001B2889 /* SentryByteCountFormatterTests.swift in Sources */, + FAAB2EE02E4BE97500FE8B7E /* TestSentryNSApplication.swift in Sources */, 7BBD18A2244EE2FD00427C76 /* TestResponseFactory.swift in Sources */, 628B89022D841D7F004B6F2A /* SentryDateUtilsTests.swift in Sources */, D808FB8B281BCE96009A2A33 /* TestSentrySwizzleWrapper.swift in Sources */, @@ -5887,13 +6180,16 @@ 7BB6550D253EEB3900887E87 /* SentryUserFeedbackTests.swift in Sources */, 7BBD18B7245180FF00427C76 /* SentryDsnTests.m in Sources */, D8DBE0D22C0EFFC300FAB1FD /* SentryReplayOptionsTests.swift in Sources */, + D4F7BD822E4373BF004A2D77 /* SentryLevelMapperTests.swift in Sources */, D4291A6D2DD62ACE00772088 /* SentryDispatchFactoryTests.m in Sources */, 62950F1029E7FE0100A42624 /* SentryTransactionContextTests.swift in Sources */, 0A2D7BBA29152CBF008727AF /* SentryWatchdogTerminationScopeObserverTests.swift in Sources */, 7BD4BD4B27EB2DC20071F4FF /* SentryDiscardedEventTests.swift in Sources */, 63FE721A20DA66EC00CDBAE8 /* SentryCrashSysCtl_Tests.m in Sources */, + F46E0BA82E6A19F900DAA75C /* SentryCrashWrapperTests.swift in Sources */, 7B88F30424BC8E6500ADF90A /* SentrySerializationTests.swift in Sources */, 843FB3432D156B9900558F18 /* SentryFeedbackTests.swift in Sources */, + F4A930252E661856006DA6EF /* SentryMobileProvisionParserTests.swift in Sources */, 623E16C32D6C57C000CF1625 /* SentryANRTypeTests.swift in Sources */, D80694C42B7CC9AE00B820E6 /* SentryReplayEventTests.swift in Sources */, 7B34721728086A9D0041F047 /* SentrySwizzleWrapperTests.swift in Sources */, @@ -5903,6 +6199,7 @@ 7B869EBE249B964D004F4FDB /* SentryThreadEquality.swift in Sources */, 6205CF262D549D8A001E6049 /* SentryDateCodableTests.swift in Sources */, 7BC6EBF8255C05060059822A /* TestData.swift in Sources */, + 92235CB02E155B2600865983 /* SentryLoggerTests.swift in Sources */, 7B88F30224BC5C6D00ADF90A /* SentrySdkInfoTests.swift in Sources */, 7BC8523B2458849E005A70F0 /* SentryDataCategoryMapperTests.swift in Sources */, 63FE721220DA66EC00CDBAE8 /* SentryCrashMach_Tests.m in Sources */, @@ -5918,6 +6215,7 @@ 7B2A70D827D5F080008B0D15 /* SentryANRTrackerV1Tests.swift in Sources */, 63FE722120DA66EC00CDBAE8 /* SentryCrashDynamicLinker_Tests.m in Sources */, D43647F32D5CFBC7001468E0 /* FileManagerTracingIntegrationTests.swift in Sources */, + 928BED2B2E16977A00B4D398 /* SentryLogBatcherTests.swift in Sources */, 63FE720120DA66EC00CDBAE8 /* RFC3339UTFString_Tests.m in Sources */, 63AA76701EB8CB4B00D153DE /* SentryTests.m in Sources */, 8E70B0FD25CB72BE002B3155 /* SentrySpanTests.swift in Sources */, @@ -5951,11 +6249,13 @@ 7BDDE3CC2966BD4700EB9177 /* SentryMXManagerTests.swift in Sources */, 7BC6EC0C255C3DF80059822A /* SentryThreadTests.swift in Sources */, D42E48572D48DF1600D251BC /* SentryBuildAppStartSpansTests.swift in Sources */, + F443DB272E09BE8C009A9045 /* LoadValidatorTests.swift in Sources */, D884A20527C80F6300074664 /* SentryCoreDataTrackerTest.swift in Sources */, 8E70B10125CB8695002B3155 /* SentrySpanIdTests.swift in Sources */, 62E2119A2DAE99FC007D7262 /* SentryAsyncSafeLog.m in Sources */, 84EB21962BF01CEA00EDDA28 /* SentryCrashInstallationTests.swift in Sources */, 7BFE7A0A27A1B6B000D2B66E /* SentryWatchdogTerminationTrackingIntegrationTests.swift in Sources */, + FA6614FC2E4B8E1A00657755 /* TestSentryUIApplication.swift in Sources */, D8292D7D2A39A027009872F7 /* UrlSanitizedTests.swift in Sources */, 621D22012DBB7E09006F9C48 /* SentryANRTrackerV1IntegrationTests.swift in Sources */, 7BA61CAF247BBF3C00C130A8 /* SentryDebugImageProviderTests.swift in Sources */, @@ -5984,6 +6284,7 @@ 7BFA69F627E0840400233199 /* SentryANRTrackingIntegrationTests.swift in Sources */, 7BBD18B62451807600427C76 /* SentryDefaultRateLimitsTests.swift in Sources */, 63FE720620DA66EC00CDBAE8 /* SentryCrashMonitor_AppState_Tests.m in Sources */, + F4DCC9DD2E4AA9D0008ECE45 /* SentrySDKSettingsTests.swift in Sources */, 7B4E375B2582313100059C93 /* SentryAttachmentTests.swift in Sources */, 63FE721320DA66EC00CDBAE8 /* SentryCrashMonitor_Signal_Tests.m in Sources */, 7BBD18B32451805500427C76 /* SentryRateLimitsParserTests.swift in Sources */, @@ -5993,6 +6294,7 @@ F45243882DE65968003E8F50 /* ExceptionCatcher.m in Sources */, 7B59398224AB47650003AAD2 /* SentrySessionTrackerTests.swift in Sources */, D43647F12D5CFB71001468E0 /* SentrySpanKeyTests.swift in Sources */, + D4CA34832E378C9900E92A61 /* SentryArrayTests.swift in Sources */, 7B05A61824A4D14A00EF211D /* SentrySessionGeneratorTests.swift in Sources */, D8CB742B294B1DD000A5F964 /* SentryUIApplicationTests.swift in Sources */, 63FE720920DA66EC00CDBAE8 /* XCTestCase+SentryCrash.m in Sources */, @@ -6010,6 +6312,7 @@ 8431EFE229B27BAD00D8DC56 /* SentryNSTimerFactoryTest.swift in Sources */, 8431EFDD29B27B5300D8DC56 /* SentrySamplingProfilerTests.mm in Sources */, 8431D4552BE1745A009EAEC1 /* SentryProfileTestFixture.swift in Sources */, + FAC735232E25AA81006C5A64 /* SentryProfilingSwiftHelpersTests.m in Sources */, 8431EFDC29B27B5300D8DC56 /* SentryProfilerTests.mm in Sources */, 8431D4562BE1745F009EAEC1 /* SentryContinuousProfilerTests.swift in Sources */, 8431EFE129B27B5300D8DC56 /* SentryThreadMetadataCacheTests.mm in Sources */, @@ -6018,10 +6321,12 @@ 845CEAEF2D83F79500B6B325 /* SentryProfilingPublicAPITests.swift in Sources */, 8431EFE829B27BAD00D8DC56 /* SentrySystemWrapperTests.swift in Sources */, 84A305492BC7328400D84283 /* SentryAppLaunchProfilingTests.swift in Sources */, - 84F2A1CE2E06001300A94524 /* SentryApplaunchProfilingMalformedConfigFileTests.swift in Sources */, + D4DEE6592E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m in Sources */, + 84F2A1CE2E06001300A94524 /* (null) in Sources */, 845CEB172D8A979700B6B325 /* SentryAppStartProfilingConfigurationTests.swift in Sources */, 8431EFE529B27BAD00D8DC56 /* SentryNSProcessInfoWrapperTests.swift in Sources */, 8431EFDE29B27B5300D8DC56 /* SentryTraceProfilerTests.swift in Sources */, + 84A898CE2E1DBDD1009A551E /* SentryAppStartProfilingConfigurationChangeTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -6035,6 +6340,7 @@ 84EB21942BF01C6C00EDDA28 /* TestNSNotificationCenterWrapper.swift in Sources */, 84B7FA4229B28CDE00AD93B1 /* TestCurrentDateProvider.swift in Sources */, 62C25C862B075F4900C68CBD /* TestOptions.swift in Sources */, + D45B4AF52E019E1A00C31DFB /* TestSentryViewRenderer.swift in Sources */, 62FC69362BEDFF18002D3EF2 /* SentryLogExtensions.swift in Sources */, 84AEB46A2C2F97FC007E46E1 /* ArrayAccesses.swift in Sources */, 84B7FA3F29B28BAD00AD93B1 /* TestTransport.swift in Sources */, @@ -6059,6 +6365,7 @@ D452FE6F2DDC890A00AFF56F /* TestFileManager.swift in Sources */, 8431F01729B2851500D8DC56 /* TestSentrySystemWrapper.swift in Sources */, 84281C632A579D0700EE88F2 /* SentryProfilerMocks.mm in Sources */, + D45B4AF72E01A10100C31DFB /* TestSentryViewPhotographer.swift in Sources */, D8FC98AB2CD0DAB30009824C /* BreadcrumbExtension.swift in Sources */, 84B7FA4129B28CD200AD93B1 /* TestSentryDispatchQueueWrapper.swift in Sources */, 84B7FA3E29B28ADD00AD93B1 /* TestClient.swift in Sources */, @@ -6158,6 +6465,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = D8BD2E27292D1F7300D96C6A /* SDK.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = Debug; }; @@ -6165,6 +6479,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = D8BD2E27292D1F7300D96C6A /* SDK.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = Release; }; @@ -6172,6 +6493,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = 63AA75C51EB8B00100D153DE /* Sentry.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = Debug; }; @@ -6179,6 +6507,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = 63AA75C51EB8B00100D153DE /* Sentry.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = Release; }; @@ -6259,6 +6594,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = D8BD2E27292D1F7300D96C6A /* SDK.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = TestCI; }; @@ -6266,6 +6608,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = 63AA75C51EB8B00100D153DE /* Sentry.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = TestCI; }; @@ -6310,6 +6659,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = D8BD2E27292D1F7300D96C6A /* SDK.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = DebugWithoutUIKit; }; @@ -6317,6 +6673,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = 63AA75C51EB8B00100D153DE /* Sentry.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = DebugWithoutUIKit; }; @@ -6707,6 +7070,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = D8BD2E27292D1F7300D96C6A /* SDK.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = ReleaseWithoutUIKit; }; @@ -6714,6 +7084,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = 63AA75C51EB8B00100D153DE /* Sentry.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = ReleaseWithoutUIKit; }; @@ -7004,6 +7381,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = D8BD2E27292D1F7300D96C6A /* SDK.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = Test; }; @@ -7011,6 +7395,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = 63AA75C51EB8B00100D153DE /* Sentry.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = Test; }; @@ -7776,6 +8167,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = D8BD2E27292D1F7300D96C6A /* SDK.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = DebugV9; }; @@ -7783,6 +8181,13 @@ isa = XCBuildConfiguration; baseConfigurationReference = 63AA75C51EB8B00100D153DE /* Sentry.xcconfig */; buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); }; name = DebugV9; }; @@ -8047,6 +8452,286 @@ }; name = DebugV9; }; + FACBE8A82E21D804006C501A /* ReleaseV9 */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D8BD2E27292D1F7300D96C6A /* SDK.xcconfig */; + buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); + }; + name = ReleaseV9; + }; + FACBE8A92E21D804006C501A /* ReleaseV9 */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 63AA75C51EB8B00100D153DE /* Sentry.xcconfig */; + buildSettings = { + CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES; + OTHER_CFLAGS = ( + "-Wnullable-to-nonnull-conversion", + "-Wnullability-completeness", + "-Wno-error=nullable-to-nonnull-conversion", + "-Wno-error=nullability-completeness", + ); + }; + name = ReleaseV9; + }; + FACBE8AA2E21D804006C501A /* ReleaseV9 */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 63AA76AE1EB9D5CD00D153DE /* SentryTests.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CODE_SIGNING_ALLOWED = NO; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = Tests/SentryTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_SWIFT_FLAGS = "-DSENTRY_USE_UIKIT"; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.Sentry.tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; + SWIFT_INCLUDE_PATHS = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Tests/SentryTests/SentryTests-Bridging-Header.h"; + SWIFT_OBJC_INTEROP_MODE = objc; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 5.0; + TVOS_DEPLOYMENT_TARGET = 13.0; + }; + name = ReleaseV9; + }; + FACBE8AB2E21D804006C501A /* ReleaseV9 */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D8199DCF29376FF40074249E /* SentrySwiftUI.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + BUILD_LIBRARY_FOR_DISTRIBUTION = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_C_LANGUAGE_STANDARD = gnu11; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Sentry. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + MODULEMAP_FILE = ""; + MTL_FAST_MATH = YES; + OTHER_SWIFT_FLAGS = "-DCARTHAGE"; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentrySwiftUI; + PROVISIONING_PROFILE_SPECIFIER = ""; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_INCLUDE_PATHS = Sources/SentrySwiftUI/; + SWIFT_OBJC_BRIDGING_HEADER = ""; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = ReleaseV9; + }; + FACBE8AC2E21D804006C501A /* ReleaseV9 */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 63AA76AE1EB9D5CD00D153DE /* SentryTests.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = "SentryTests-Info.plist"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.Sentry.tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Tests/SentryTests/SentryTests-Bridging-Header.h"; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 5.0; + }; + name = ReleaseV9; + }; + FACBE8AD2E21D804006C501A /* ReleaseV9 */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 63AA76AE1EB9D5CD00D153DE /* SentryTests.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "c++14"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + EXECUTABLE_PREFIX = lib; + GCC_C_LANGUAGE_STANDARD = gnu99; + MACH_O_TYPE = staticlib; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryTestUtils; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + SWIFT_OBJC_BRIDGING_HEADER = "SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h"; + SWIFT_VERSION = 5.0; + }; + name = ReleaseV9; + }; + FACBE8AE2E21D804006C501A /* ReleaseV9 */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "Apple Development"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Mac Developer"; + CODE_SIGN_STYLE = Manual; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + "DEVELOPMENT_TEAM[sdk=macosx*]" = ""; + "DEVELOPMENT_TEAM[sdk=watchos*]" = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Sentry. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu17 gnu++20"; + MTL_FAST_MATH = YES; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SentryTestUtilsDynamic; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = ReleaseV9; + }; + FACBE8AF2E21D804006C501A /* ReleaseV9 */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 63AA76AE1EB9D5CD00D153DE /* SentryTests.xcconfig */; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_FILE = ""; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); + OTHER_SWIFT_FLAGS = "-DSENTRY_USE_UIKIT"; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.Sentry.tests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; + SWIFT_INCLUDE_PATHS = ""; + SWIFT_OBJC_BRIDGING_HEADER = "Tests/SentrySwiftUITests/SentryTests-Bridging-Header.h"; + SWIFT_OBJC_INTEROP_MODE = objc; + SWIFT_SWIFT3_OBJC_INFERENCE = Off; + SWIFT_VERSION = 5.0; + TVOS_DEPLOYMENT_TARGET = 13.0; + }; + name = ReleaseV9; + }; + FACBE8B02E21D804006C501A /* ReleaseV9 */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_FLOAT_CONVERSION = YES; + CODE_SIGNING_ALLOWED = NO; + CODE_SIGNING_REQUIRED = NO; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; + INFOPLIST_FILE = SentryTestUtilsTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + OTHER_SWIFT_FLAGS = "-DSENTRY_USE_UIKIT"; + PRODUCT_BUNDLE_IDENTIFIER = io.sentry.Sentry.TestUtilsTests; + PRODUCT_NAME = SentryTestUtilsTests; + PROVISIONING_PROFILE_SPECIFIER = ""; + "PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*]" = ""; + SWIFT_VERSION = 5.0; + TVOS_DEPLOYMENT_TARGET = 13.0; + }; + name = ReleaseV9; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -8059,6 +8744,7 @@ D8079A6727178911004B0F61 /* Test */, 7BFC80A8282B736400E83A05 /* TestCI */, 6327C5E61EB8A783004E799B /* Release */, + FACBE8A82E21D804006C501A /* ReleaseV9 */, 8483D06A2AC7627800143615 /* ReleaseWithoutUIKit */, ); defaultConfigurationIsVisible = 0; @@ -8073,6 +8759,7 @@ D8079A6827178911004B0F61 /* Test */, 7BFC80A9282B736400E83A05 /* TestCI */, 63AA75A21EB8AEF500D153DE /* Release */, + FACBE8A92E21D804006C501A /* ReleaseV9 */, 8483D06B2AC7627800143615 /* ReleaseWithoutUIKit */, ); defaultConfigurationIsVisible = 0; @@ -8087,6 +8774,7 @@ D8079A6927178911004B0F61 /* Test */, 7BFC80AA282B736400E83A05 /* TestCI */, 63AA766E1EB8CB2F00D153DE /* Release */, + FACBE8AA2E21D804006C501A /* ReleaseV9 */, 8483D06C2AC7627800143615 /* ReleaseWithoutUIKit */, ); defaultConfigurationIsVisible = 0; @@ -8101,6 +8789,7 @@ 8431EFD629B27B1100D8DC56 /* Test */, 8431EFD729B27B1100D8DC56 /* TestCI */, 8431EFD829B27B1100D8DC56 /* Release */, + FACBE8AC2E21D804006C501A /* ReleaseV9 */, 8483D06F2AC7627800143615 /* ReleaseWithoutUIKit */, ); defaultConfigurationIsVisible = 0; @@ -8115,6 +8804,7 @@ 8431F01229B284F200D8DC56 /* Test */, 8431F01329B284F200D8DC56 /* TestCI */, 8431F01429B284F200D8DC56 /* Release */, + FACBE8AD2E21D804006C501A /* ReleaseV9 */, 8483D0702AC7627800143615 /* ReleaseWithoutUIKit */, ); defaultConfigurationIsVisible = 0; @@ -8129,6 +8819,7 @@ D4CBA24C2DE06D0200581618 /* Test */, D4CBA24D2DE06D0200581618 /* TestCI */, D4CBA24E2DE06D0200581618 /* Release */, + FACBE8B02E21D804006C501A /* ReleaseV9 */, D4CBA24F2DE06D0200581618 /* ReleaseWithoutUIKit */, ); defaultConfigurationIsVisible = 0; @@ -8143,6 +8834,7 @@ D8199DAF29376E9B0074249E /* Test */, D8199DB029376E9B0074249E /* TestCI */, D8199DB129376E9B0074249E /* Release */, + FACBE8AB2E21D804006C501A /* ReleaseV9 */, 8483D06E2AC7627800143615 /* ReleaseWithoutUIKit */, ); defaultConfigurationIsVisible = 0; @@ -8157,6 +8849,7 @@ D833D7302D1321C100961E7A /* Test */, D833D7312D1321C100961E7A /* TestCI */, D833D7322D1321C100961E7A /* Release */, + FACBE8AF2E21D804006C501A /* ReleaseV9 */, D833D7332D1321C100961E7A /* ReleaseWithoutUIKit */, ); defaultConfigurationIsVisible = 0; @@ -8171,6 +8864,7 @@ D84DAD542B17428D003CF120 /* Test */, D84DAD552B17428D003CF120 /* TestCI */, D84DAD562B17428D003CF120 /* Release */, + FACBE8AE2E21D804006C501A /* ReleaseV9 */, D84DAD572B17428D003CF120 /* ReleaseWithoutUIKit */, ); defaultConfigurationIsVisible = 0; diff --git a/SentryPrivate.podspec b/SentryPrivate.podspec index f8d58d6508a..5bdc28a2f8c 100644 --- a/SentryPrivate.podspec +++ b/SentryPrivate.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "SentryPrivate" - s.version = "8.53.2" + s.version = "8.56.0" s.summary = "Sentry Private Library." s.homepage = "https://github.com/getsentry/sentry-cocoa" s.license = "mit" diff --git a/SentrySwiftUI.podspec b/SentrySwiftUI.podspec index 4367ae56680..51a6100e7b1 100644 --- a/SentrySwiftUI.podspec +++ b/SentrySwiftUI.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "SentrySwiftUI" - s.version = "8.53.2" + s.version = "8.56.0" s.summary = "Sentry client for SwiftUI" s.homepage = "https://github.com/getsentry/sentry-cocoa" s.license = "mit" @@ -19,5 +19,5 @@ Pod::Spec.new do |s| s.watchos.framework = 'WatchKit' s.source_files = "Sources/SentrySwiftUI/**/*.{swift,h,m}" - s.dependency 'Sentry/HybridSDK', "8.53.2" + s.dependency 'Sentry/HybridSDK', "8.56.0" end diff --git a/SentryTestUtils/ClearTestState.swift b/SentryTestUtils/ClearTestState.swift index 3daf1e9b25c..cfcf7b69662 100644 --- a/SentryTestUtils/ClearTestState.swift +++ b/SentryTestUtils/ClearTestState.swift @@ -23,11 +23,11 @@ class TestCleanup: NSObject { assert(Thread.isMainThread, "You must call clearTestState on the main thread.") SentrySDK.close() - SentrySDK.setCurrentHub(nil) - SentrySDK.crashedLastRunCalled = false - SentrySDK.startInvocations = 0 - SentrySDK.setDetectedStartUpCrash(false) - SentrySDK.setStart(nil) + SentrySDKInternal.setCurrentHub(nil) + SentrySDKInternal.crashedLastRunCalled = false + SentrySDKInternal.startInvocations = 0 + SentrySDKInternal.setDetectedStartUpCrash(false) + SentrySDKInternal.setStart(with: nil) PrivateSentrySDKOnly.appStartMeasurementHybridSDKMode = false SentryNetworkTracker.sharedInstance.disable() @@ -53,8 +53,8 @@ class TestCleanup: NSObject { SentryTraceProfiler.getCurrentProfiler()?.stop(for: SentryProfilerTruncationReason.normal) SentryTraceProfiler.resetConcurrencyTracking() removeAppLaunchProfilingConfigFile() - sentry_stopAndDiscardLaunchProfileTracer() - + sentry_stopAndDiscardLaunchProfileTracer(nil) + if SentryContinuousProfiler.isCurrentlyProfiling() { SentryContinuousProfiler.stopTimerAndCleanup() } @@ -62,7 +62,7 @@ class TestCleanup: NSObject { #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) PrivateSentrySDKOnly.onAppStartMeasurementAvailable = nil - SentrySDK.setAppStartMeasurement(nil) + SentrySDKInternal.setAppStartMeasurement(nil) #endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) sentrycrash_scopesync_reset() diff --git a/SentryTestUtils/SentryFileManager+Test.h b/SentryTestUtils/SentryFileManager+Test.h index 152314d86c6..61c85a7b6b5 100644 --- a/SentryTestUtils/SentryFileManager+Test.h +++ b/SentryTestUtils/SentryFileManager+Test.h @@ -8,7 +8,7 @@ NSString *_Nullable sentryGetScopedCachesDirectory(NSString *cachesDirectory); NSString *_Nullable sentryBuildScopedCachesDirectoryPath(NSString *cachesDirectory, BOOL isSandboxed, NSString *_Nullable bundleIdentifier, NSString *_Nullable lastPathComponent); -SENTRY_EXTERN NSURL *launchProfileConfigFileURL(void); +SENTRY_EXTERN NSURL *_Nullable launchProfileConfigFileURL(void); SENTRY_EXTERN NSURL *_Nullable sentryLaunchConfigFileURL; @interface SentryFileManager () diff --git a/SentryTestUtils/SentryLaunchProfiling+Tests.h b/SentryTestUtils/SentryLaunchProfiling+Tests.h index 5ced9adc994..278aa22967b 100644 --- a/SentryTestUtils/SentryLaunchProfiling+Tests.h +++ b/SentryTestUtils/SentryLaunchProfiling+Tests.h @@ -3,23 +3,13 @@ #if SENTRY_TARGET_PROFILING_SUPPORTED # import "SentryDefines.h" +# import "SentryProfiler+Private.h" @class SentryOptions; @class SentrySamplerDecision; -@class SentryTracer; NS_ASSUME_NONNULL_BEGIN -typedef struct { - BOOL shouldProfile; - SentrySamplerDecision *_Nullable tracesDecision; - SentrySamplerDecision *_Nullable profilesDecision; -} SentryLaunchProfileConfig; - -SENTRY_EXTERN SentryTracer *_Nullable sentry_launchTracer; - -SentryLaunchProfileConfig sentry_shouldProfileNextLaunch(SentryOptions *options); - /** * `sentry_shouldProfileNextLaunch` cannot be exposed to Swift tests because its return type is not * expressible in Swift. This wraps it and only returns the `BOOL shouldProfile` value in the diff --git a/SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h b/SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h index d99c7355b94..4897c2a9334 100644 --- a/SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h +++ b/SentryTestUtils/SentryTestUtils-ObjC-BridgingHeader.h @@ -10,7 +10,6 @@ # import "SentryAppStartTracker.h" # import "SentryDisplayLinkWrapper.h" # import "SentryFramesTracker+TestInit.h" -# import "SentryUIDeviceWrapper.h" # import "SentryUIViewControllerPerformanceTracker.h" #endif // SENTRY_HAS_UIKIT @@ -26,33 +25,26 @@ #import "PrivateSentrySDKOnly.h" #import "SentryAppStartMeasurement.h" -#import "SentryAppState.h" -#import "SentryBinaryImageCache.h" #import "SentryClient+Private.h" #import "SentryClient+TestInit.h" #import "SentryCrash+Test.h" #import "SentryCrashCachedData.h" #import "SentryCrashInstallation+Private.h" #import "SentryCrashMonitor_MachException.h" -#import "SentryCrashWrapper.h" #import "SentryDebugImageProvider+HybridSDKs.h" #import "SentryDependencyContainer.h" #import "SentryDispatchFactory.h" #import "SentryDispatchSourceWrapper.h" -#import "SentryEnvelope.h" #import "SentryFileManager+Test.h" #import "SentryGlobalEventProcessor.h" #import "SentryHub+Private.h" #import "SentryHub+Test.h" #import "SentryLogC.h" -#import "SentryNSNotificationCenterWrapper.h" -#import "SentryNSProcessInfoWrapper.h" -#import "SentryNSTimerFactory.h" #import "SentryNetworkTracker.h" #import "SentryPerformanceTracker+Testing.h" #import "SentryReachability.h" #import "SentrySDK+Private.h" -#import "SentrySDK+Tests.h" +#import "SentrySDKInternal+Tests.h" #import "SentryScopeSyncC.h" #import "SentrySwizzleWrapper.h" #import "SentrySystemWrapper.h" diff --git a/SentryTestUtils/TestClient.swift b/SentryTestUtils/TestClient.swift index fcb4f444d7b..3ee5f461812 100644 --- a/SentryTestUtils/TestClient.swift +++ b/SentryTestUtils/TestClient.swift @@ -1,9 +1,19 @@ import _SentryPrivate import Foundation +@_spi(Private) import Sentry public class TestClient: SentryClient { public override init?(options: Options) { - super.init(options: options, fileManager: try! TestFileManager(options: options), deleteOldEnvelopeItems: false, transportAdapter: TestTransportAdapter(transports: [TestTransport()], options: options)) + super.init( + options: options, + fileManager: try! TestFileManager( + options: options, + dateProvider: TestCurrentDateProvider(), + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ), + deleteOldEnvelopeItems: false, + transportAdapter: TestTransportAdapter(transports: [TestTransport()], options: options) + ) } public override init?(options: Options, fileManager: SentryFileManager, deleteOldEnvelopeItems: Bool) { @@ -16,7 +26,7 @@ public class TestClient: SentryClient { // Without this override we get a fatal error: use of unimplemented initializer // see https://stackoverflow.com/questions/28187261/ios-swift-fatal-error-use-of-unimplemented-initializer-init - public override init(options: Options, transportAdapter: SentryTransportAdapter, fileManager: SentryFileManager, deleteOldEnvelopeItems: Bool, threadInspector: SentryThreadInspector, debugImageProvider: SentryDebugImageProvider, random: SentryRandomProtocol, locale: Locale, timezone: TimeZone) { + @_spi(Private) public override init(options: Options, transportAdapter: SentryTransportAdapter, fileManager: SentryFileManager, deleteOldEnvelopeItems: Bool, threadInspector: SentryThreadInspector, debugImageProvider: SentryDebugImageProvider, random: SentryRandomProtocol, locale: Locale, timezone: TimeZone) { super.init( options: options, transportAdapter: transportAdapter, @@ -30,7 +40,9 @@ public class TestClient: SentryClient { ) } + @_spi(Private) public var captureSessionInvocations = Invocations() + @_spi(Private) public override func capture(session: SentrySession) { captureSessionInvocations.record(session) } @@ -41,8 +53,8 @@ public class TestClient: SentryClient { return event.eventId } - public var captureEventWithScopeInvocations = Invocations<(event: Event, scope: Scope, additionalEnvelopeItems: [SentryEnvelopeItem])>() - public override func capture(event: Event, scope: Scope, additionalEnvelopeItems: [SentryEnvelopeItem]) -> SentryId { + @_spi(Private) public var captureEventWithScopeInvocations = Invocations<(event: Event, scope: Scope, additionalEnvelopeItems: [SentryEnvelopeItem])>() + @_spi(Private) public override func capture(event: Event, scope: Scope, additionalEnvelopeItems: [SentryEnvelopeItem]) -> SentryId { captureEventWithScopeInvocations.record((event, scope, additionalEnvelopeItems)) return event.eventId } @@ -84,13 +96,17 @@ public class TestClient: SentryClient { } public var callSessionBlockWithIncrementSessionErrors = true + @_spi(Private) public var captureErrorWithSessionInvocations = Invocations<(error: Error, session: SentrySession?, scope: Scope)>() + @_spi(Private) public override func captureError(_ error: Error, with scope: Scope, incrementSessionErrors sessionBlock: @escaping () -> SentrySession) -> SentryId { captureErrorWithSessionInvocations.record((error, callSessionBlockWithIncrementSessionErrors ? sessionBlock() : nil, scope)) return SentryId() } + @_spi(Private) public var captureExceptionWithSessionInvocations = Invocations<(exception: NSException, session: SentrySession?, scope: Scope)>() + @_spi(Private) public override func capture(_ exception: NSException, with scope: Scope, incrementSessionErrors sessionBlock: @escaping () -> SentrySession) -> SentryId { captureExceptionWithSessionInvocations.record((exception, callSessionBlockWithIncrementSessionErrors ? sessionBlock() : nil, scope)) return SentryId() @@ -102,7 +118,9 @@ public class TestClient: SentryClient { return SentryId() } + @_spi(Private) public var captureFatalEventWithSessionInvocations = Invocations<(event: Event, session: SentrySession, scope: Scope)>() + @_spi(Private) public override func captureFatalEvent(_ event: Event, with session: SentrySession, with scope: Scope) -> SentryId { captureFatalEventWithSessionInvocations.record((event, session, scope)) return SentryId() @@ -125,13 +143,18 @@ public class TestClient: SentryClient { captureFeedbackInvocations.record((feedback, scope)) } - public var captureEnvelopeInvocations = Invocations() - public override func capture(_ envelope: SentryEnvelope) { + public var captureSerializedFeedbackInvocations = Invocations<(String, Scope)>() + public override func captureSerializedFeedback(_ serializedFeedback: [AnyHashable: Any], withEventId feedbackEventId: String, attachments: [Attachment], scope: Scope) { + captureSerializedFeedbackInvocations.record((feedbackEventId, scope)) + } + + @_spi(Private) public var captureEnvelopeInvocations = Invocations() + @_spi(Private) public override func capture(_ envelope: SentryEnvelope) { captureEnvelopeInvocations.record(envelope) } - public var storedEnvelopeInvocations = Invocations() - public override func store(_ envelope: SentryEnvelope) { + @_spi(Private) public var storedEnvelopeInvocations = Invocations() + @_spi(Private) public override func store(_ envelope: SentryEnvelope) { storedEnvelopeInvocations.record(envelope) } @@ -149,4 +172,9 @@ public class TestClient: SentryClient { public override func flush(timeout: TimeInterval) { flushInvocations.record(timeout) } + + public var captureLogsDataInvocations = Invocations<(data: Data, count: NSNumber)>() + public override func captureLogsData(_ data: Data, with count: NSNumber) { + captureLogsDataInvocations.record((data, count)) + } } diff --git a/SentryTestUtils/TestConstants.swift b/SentryTestUtils/TestConstants.swift index 27f28d3ab78..e1a4e125487 100644 --- a/SentryTestUtils/TestConstants.swift +++ b/SentryTestUtils/TestConstants.swift @@ -1,3 +1,5 @@ +@_spi(Private) import Sentry + public struct TestConstants { /** @@ -29,7 +31,8 @@ public struct TestConstants { return event } - public static var envelope: SentryEnvelope { + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + @_spi(Private) public static var envelope: SentryEnvelope { let event = Event() let envelopeItem = SentryEnvelopeItem(event: event) return SentryEnvelope(id: event.eventId, singleItem: envelopeItem) diff --git a/SentryTestUtils/TestFileManager.swift b/SentryTestUtils/TestFileManager.swift index 2116545eea4..190a63d6d7e 100644 --- a/SentryTestUtils/TestFileManager.swift +++ b/SentryTestUtils/TestFileManager.swift @@ -1,5 +1,6 @@ import _SentryPrivate import Foundation +@_spi(Private) import Sentry public class TestFileManager: SentryFileManager { var timestampLastInForeground: Date? @@ -7,15 +8,11 @@ public class TestFileManager: SentryFileManager { var storeTimestampLastInForegroundInvocations: Int = 0 var deleteTimestampLastInForegroundInvocations: Int = 0 - public var storeEnvelopeInvocations = Invocations() + @_spi(Private) public var storeEnvelopeInvocations = Invocations() public var storeEnvelopePath: String? public var storeEnvelopePathNil: Bool = false - - public init(options: Options) throws { - try super.init(options: options, dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) - } - - public override func store(_ envelope: SentryEnvelope) -> String? { + + @_spi(Private) public override func store(_ envelope: SentryEnvelope) -> String? { storeEnvelopeInvocations.record(envelope) if storeEnvelopePathNil { return nil @@ -45,14 +42,14 @@ public class TestFileManager: SentryFileManager { } var readAppStateInvocations = Invocations() - public override func readAppState() -> SentryAppState? { + @_spi(Private) public override func readAppState() -> SentryAppState? { readAppStateInvocations.record(Void()) return nil } var appState: SentryAppState? public var readPreviousAppStateInvocations = Invocations() - public override func readPreviousAppState() -> SentryAppState? { + @_spi(Private) public override func readPreviousAppState() -> SentryAppState? { readPreviousAppStateInvocations.record(Void()) return appState } diff --git a/SentryTestUtils/TestHub.swift b/SentryTestUtils/TestHub.swift index fd6b53c5c97..eb5e7b32957 100644 --- a/SentryTestUtils/TestHub.swift +++ b/SentryTestUtils/TestHub.swift @@ -36,8 +36,8 @@ public class TestHub: SentryHub { sentFatalEventsWithScope.record((event, scope)) } - public var capturedEventsWithScopes = Invocations<(event: Event, scope: Scope, additionalEnvelopeItems: [SentryEnvelopeItem])>() - public override func capture(event: Event, scope: Scope, additionalEnvelopeItems: [SentryEnvelopeItem]) -> SentryId { + @_spi(Private) public var capturedEventsWithScopes = Invocations<(event: Event, scope: Scope, additionalEnvelopeItems: [SentryEnvelopeItem])>() + @_spi(Private) public override func capture(event: Event, scope: Scope, additionalEnvelopeItems: [SentryEnvelopeItem]) -> SentryId { self.capturedEventsWithScopes.record((event, scope, additionalEnvelopeItems)) diff --git a/SentryTestUtils/TestNSNotificationCenterWrapper.swift b/SentryTestUtils/TestNSNotificationCenterWrapper.swift index e0bf55711d8..5a920501d08 100644 --- a/SentryTestUtils/TestNSNotificationCenterWrapper.swift +++ b/SentryTestUtils/TestNSNotificationCenterWrapper.swift @@ -1,5 +1,5 @@ import Foundation -import Sentry +@_spi(Private) import Sentry #if canImport(UIKit) public typealias CrossPlatformApplication = UIApplication @@ -7,10 +7,9 @@ public typealias CrossPlatformApplication = UIApplication public typealias CrossPlatformApplication = NSApplication #endif -@objcMembers public class TestNSNotificationCenterWrapper: SentryNSNotificationCenterWrapper { +@objcMembers public class TestNSNotificationCenterWrapper: NSObject { private enum Observer { - case observer(WeakReference, Selector, NSNotification.Name) - case observerWithObject(WeakReference, Selector, NSNotification.Name, Any?) + case observerWithObject(WeakReference, Selector, NSNotification.Name?, Any?) case observerForKeyPath(WeakReference, String, NSKeyValueObservingOptions, UnsafeMutableRawPointer?) case observerWithBlock(WeakReference, NSNotification.Name?, (Notification) -> Void) } @@ -20,37 +19,21 @@ public typealias CrossPlatformApplication = NSApplication private var observers: [Observer] = [] - public var addObserverInvocations = Invocations<( - observer: WeakReference, - selector: Selector, - name: NSNotification.Name - )>() - public override func addObserver( - _ observer: NSObject, - selector aSelector: Selector, - name aName: NSNotification.Name - ) { - if ignoreAddObserver == false { - addObserverInvocations.record((WeakReference(value: observer), aSelector, aName)) - observers.append(.observer(WeakReference(value: observer), aSelector, aName)) - } - } - public var addObserverWithObjectInvocations = Invocations<( observer: WeakReference, selector: Selector, - name: NSNotification.Name, + name: NSNotification.Name?, object: Any? )>() - public override func addObserver( - _ observer: NSObject, + public func addObserver( + _ observer: Any, selector aSelector: Selector, - name aName: NSNotification.Name, - object anObject: Any? + name aName: NSNotification.Name?, + object anObject: Any? = nil ) { if ignoreAddObserver == false { - addObserverWithObjectInvocations.record((WeakReference(value: observer), aSelector, aName, anObject)) - observers.append(.observerWithObject(WeakReference(value: observer), aSelector, aName, anObject)) + addObserverWithObjectInvocations.record((WeakReference(value: observer as! NSObject), aSelector, aName, anObject)) + observers.append(.observerWithObject(WeakReference(value: observer as! NSObject), aSelector, aName, anObject)) } } @@ -73,7 +56,7 @@ public typealias CrossPlatformApplication = NSApplication } public var addObserverWithBlockInvocations = Invocations<(observer: WeakReference, name: NSNotification.Name?, block: (Notification) -> Void)>() - public override func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> any NSObjectProtocol { + public func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> any NSObjectProtocol { if ignoreAddObserver == false { let observer = NSObject() addObserverWithBlockInvocations.record((WeakReference(value: observer), name, block)) @@ -83,59 +66,19 @@ public typealias CrossPlatformApplication = NSApplication return NSObject() } - public var removeObserverWithNameInvocations = Invocations() - public override func removeObserver(_ observer: any NSObjectProtocol, name aName: NSNotification.Name) { - if ignoreRemoveObserver == false { - removeObserverWithNameInvocations.record(aName) - observers.removeAll { item in - switch item { - case .observer(let weakObserver, _, let name): - return (weakObserver.value === observer as? NSObject) || name == aName - case .observerWithObject(let weakObserver, _, let name, _): - return (weakObserver.value === observer as? NSObject) || name == aName - case .observerWithBlock(let weakObserver, let name, _): - return (weakObserver.value === observer as? NSObject) || name == aName - default: - return false - } - } - } - } - /// We don't keep track of the actual objects, because removeObserver /// gets often called in dealloc, and we don't want to store an object about to be deallocated /// in an array. - public var removeObserverInvocations = Invocations() - public override func removeObserver(_ observer: any NSObjectProtocol) { - if ignoreRemoveObserver == false { - removeObserverInvocations.record(Void()) - observers.removeAll { item in - switch item { - case .observer(let weakObserver, _, _): - return weakObserver.value === observer as? NSObject - case .observerWithObject(let weakObserver, _, _, _): - return weakObserver.value === observer as? NSObject - case .observerWithBlock(let weakObserver, _, _): - return weakObserver.value === observer as? NSObject - case .observerForKeyPath(let weakObserver, _, _, _): - return weakObserver.value === observer as? NSObject - } - } - } - } - - public var removeObserverWithNameAndObjectInvocations = Invocations<(name: NSNotification.Name, object: Any?)>() - public override func removeObserver( - _ observer: any NSObjectProtocol, - name aName: NSNotification.Name, - object anObject: Any? + public var removeObserverWithNameAndObjectInvocations = Invocations<(name: NSNotification.Name?, object: Any?)>() + public func removeObserver( + _ observer: Any, + name aName: NSNotification.Name? = nil, + object anObject: Any? = nil ) { if ignoreRemoveObserver == false { removeObserverWithNameAndObjectInvocations.record((aName, anObject)) observers.removeAll { item in switch item { - case .observer(let weakObserver, _, let name): - return (weakObserver.value === observer as? NSObject) || name == aName case .observerWithObject(let weakObserver, _, let name, let object): return (weakObserver.value === observer as? NSObject) || (name == aName && ((object == nil && anObject == nil) || (object as AnyObject === anObject as AnyObject))) @@ -148,21 +91,6 @@ public typealias CrossPlatformApplication = NSApplication } } - public var removeObserverForKeyPathInvocations = Invocations() - public override func removeObserver(_ observer: NSObject, forKeyPath keyPath: String) { - if ignoreRemoveObserver == false { - removeObserverForKeyPathInvocations.record(keyPath) - observers.removeAll { item in - switch item { - case .observerForKeyPath(let weakObserver, let path, _, _): - return (weakObserver.value === observer) || path == keyPath - default: - return false - } - } - } - } - public var removeObserverForKeyPathWithContextInvocations = Invocations<(keyPath: String, context: UnsafeMutableRawPointer?)>() public override func removeObserver( _ observer: NSObject, @@ -183,13 +111,16 @@ public typealias CrossPlatformApplication = NSApplication } } - public override func post(_ notification: Notification) { + public override func removeObserver( + _ observer: NSObject, + forKeyPath keyPath: String + ) { + removeObserver(observer, forKeyPath: keyPath, context: nil) + } + + public func post(_ notification: Notification) { observers.forEach { observer in switch observer { - case .observer(let weakObserver, let selector, let name): - if name == notification.name { - _ = weakObserver.value?.perform(selector, with: notification) - } case .observerWithObject(let weakObserver, let selector, let name, let object): if name == notification.name { let objectsMatch = (object == nil && notification.object == nil) || @@ -214,14 +145,10 @@ public typealias CrossPlatformApplication = NSApplication /// Helper method to clear all observers (useful for testing) public func clearAllObservers() { observers.removeAll() - addObserverInvocations.removeAll() addObserverWithObjectInvocations.removeAll() addObserverForKeyPathWithContextInvocations.removeAll() addObserverWithBlockInvocations.removeAll() - removeObserverInvocations.removeAll() - removeObserverWithNameInvocations.removeAll() removeObserverWithNameAndObjectInvocations.removeAll() - removeObserverForKeyPathInvocations.removeAll() removeObserverForKeyPathWithContextInvocations.removeAll() } @@ -230,3 +157,6 @@ public typealias CrossPlatformApplication = NSApplication return observers.count } } + +@_spi(Private) extension TestNSNotificationCenterWrapper: SentryNSNotificationCenterWrapper { +} diff --git a/SentryTestUtils/TestOptions.swift b/SentryTestUtils/TestOptions.swift index c61d352a8f8..7714f456198 100644 --- a/SentryTestUtils/TestOptions.swift +++ b/SentryTestUtils/TestOptions.swift @@ -2,16 +2,19 @@ import Foundation import Sentry public extension Options { + @available(*, deprecated) func setIntegrations(_ integrations: [AnyClass]) { self.integrations = integrations.map { NSStringFromClass($0) } } + @available(*, deprecated) func removeAllIntegrations() { self.integrations = [] } + @available(*, deprecated) static func noIntegrations() -> Options { let options = Options() options.removeAllIntegrations() diff --git a/SentryTestUtils/TestRandom.swift b/SentryTestUtils/TestRandom.swift index 33f79e6dc52..d034b94a0e2 100644 --- a/SentryTestUtils/TestRandom.swift +++ b/SentryTestUtils/TestRandom.swift @@ -1,7 +1,8 @@ import _SentryPrivate import Foundation +@_spi(Private) @testable import Sentry -public class TestRandom: SentryRandomProtocol { +@_spi(Private) public class TestRandom: SentryRandomProtocol { public var value: Double diff --git a/SentryTestUtils/TestSentryDispatchQueueWrapper.swift b/SentryTestUtils/TestSentryDispatchQueueWrapper.swift index 5f1788447c0..6417d11566a 100644 --- a/SentryTestUtils/TestSentryDispatchQueueWrapper.swift +++ b/SentryTestUtils/TestSentryDispatchQueueWrapper.swift @@ -62,6 +62,20 @@ import Foundation dispatchAfterInvocations.invocations.last?.block() } + public var dispatchAfterWorkItemInvocations = Invocations<(interval: TimeInterval, workItem: DispatchWorkItem)>() + public override func dispatch(after interval: TimeInterval, workItem: DispatchWorkItem) { + dispatchAfterWorkItemInvocations.record((interval, workItem)) + if blockBeforeMainBlock() { + if dispatchAfterExecutesBlock { + workItem.perform() + } + } + } + + public func invokeLastDispatchAfterWorkItem() { + dispatchAfterWorkItemInvocations.invocations.last?.workItem.perform() + } + public var dispatchCancelInvocations = 0 public override var shouldDispatchCancel: Bool { dispatchCancelInvocations += 1 diff --git a/SentryTestUtils/TestSentryNSProcessInfoWrapper.swift b/SentryTestUtils/TestSentryNSProcessInfoWrapper.swift index 270de5df246..c28f8d73112 100644 --- a/SentryTestUtils/TestSentryNSProcessInfoWrapper.swift +++ b/SentryTestUtils/TestSentryNSProcessInfoWrapper.swift @@ -1,28 +1,48 @@ -import Sentry +@_spi(Private) import Sentry -public class TestSentryNSProcessInfoWrapper: SentryNSProcessInfoWrapper { +@_spi(Private) public final class MockSentryProcessInfo: SentryProcessInfoSource { + + public init() { } + public struct Override { - public var processorCount: UInt? + public var processorCount: Int? public var processDirectoryPath: String? + public var processPath: String? public var thermalState: ProcessInfo.ThermalState? public var environment: [String: String]? + public var isiOSAppOnMac: Bool? + public var isMacCatalystApp: Bool? } public var overrides = Override() - public override var processorCount: UInt { - overrides.processorCount ?? super.processorCount + public var processorCount: Int { + overrides.processorCount ?? ProcessInfo.processInfo.processorCount } - public override var processDirectoryPath: String { - overrides.processDirectoryPath ?? super.processDirectoryPath + public var processDirectoryPath: String { + overrides.processDirectoryPath ?? ProcessInfo.processInfo.processDirectoryPath + } + + public var processPath: String? { + overrides.processPath ?? ProcessInfo.processInfo.processPath } - public override var thermalState: ProcessInfo.ThermalState { - overrides.thermalState ?? super.thermalState + public var thermalState: ProcessInfo.ThermalState { + overrides.thermalState ?? ProcessInfo.processInfo.thermalState } - public override var environment: [String: String] { - overrides.environment ?? super.environment + public var environment: [String: String] { + overrides.environment ?? ProcessInfo.processInfo.environment + } + + @available(iOS 14.0, macOS 11.0, tvOS 14.0, *) + public var isiOSAppOnMac: Bool { + return overrides.isiOSAppOnMac ?? ProcessInfo.processInfo.isiOSAppOnMac + } + + @available(iOS 13.0, macOS 10.15, tvOS 13.0, *) + public var isMacCatalystApp: Bool { + return overrides.isMacCatalystApp ?? ProcessInfo.processInfo.isMacCatalystApp } } diff --git a/SentryTestUtils/TestSentryNSTimerFactory.swift b/SentryTestUtils/TestSentryNSTimerFactory.swift index 477338342bf..311480083c7 100644 --- a/SentryTestUtils/TestSentryNSTimerFactory.swift +++ b/SentryTestUtils/TestSentryNSTimerFactory.swift @@ -3,7 +3,7 @@ import Foundation // We must not subclass NSTimer, see https://developer.apple.com/documentation/foundation/nstimer#1770465. // Therefore we return a NSTimer instance here with TimeInterval.infinity. -public class TestSentryNSTimerFactory: SentryNSTimerFactory { +@_spi(Private) public class TestSentryNSTimerFactory: SentryNSTimerFactory { public struct Overrides { private var _interval: TimeInterval? @@ -44,17 +44,16 @@ public class TestSentryNSTimerFactory: SentryNSTimerFactory { self.currentDateProvider = currentDateProvider super.init() } -} -// MARK: Superclass overrides -public extension TestSentryNSTimerFactory { - override func scheduledTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Void) -> Timer { + @objc + public override func scheduledTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Void) -> Timer { let timer = Timer.scheduledTimer(withTimeInterval: TimeInterval.infinity, repeats: repeats, block: block) overrides = Overrides(timer: timer, interval: interval, block: block, lastFireDate: currentDateProvider.date()) return timer } - override func scheduledTimer(withTimeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer { + @objc + public override func scheduledTimer(withTimeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer { let timer = Timer.scheduledTimer(timeInterval: ti, target: aTarget, selector: aSelector, userInfo: userInfo, repeats: yesOrNo) //swiftlint:disable force_cast let invocationInfo = Overrides.InvocationInfo(target: aTarget as! NSObject, selector: aSelector) diff --git a/SentryTestUtils/TestSentrySystemWrapper.swift b/SentryTestUtils/TestSentrySystemWrapper.swift index 37f1fd0c8ff..004ea09044f 100644 --- a/SentryTestUtils/TestSentrySystemWrapper.swift +++ b/SentryTestUtils/TestSentrySystemWrapper.swift @@ -1,5 +1,7 @@ import Sentry +#if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) + public class TestSentrySystemWrapper: SentrySystemWrapper { public struct Override { public var memoryFootprintError: NSError? @@ -29,10 +31,13 @@ public class TestSentrySystemWrapper: SentrySystemWrapper { return try overrides.cpuUsage ?? super.cpuUsage() } +#if arch(arm) || arch(arm64) public override func cpuEnergyUsage() throws -> NSNumber { if let errorOverride = overrides.cpuEnergyUsageError { throw errorOverride } return try overrides.cpuEnergyUsage ?? super.cpuEnergyUsage() } +#endif } +#endif // os(iOS) || os(macOS) || targetEnvironment(macCatalyst) diff --git a/SentryTestUtils/TestSentryViewPhotographer.swift b/SentryTestUtils/TestSentryViewPhotographer.swift new file mode 100644 index 00000000000..f9672be7055 --- /dev/null +++ b/SentryTestUtils/TestSentryViewPhotographer.swift @@ -0,0 +1,18 @@ +#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) + +@_spi(Private) @testable import Sentry + +@_spi(Private) public class TestSentryViewPhotographer: SentryViewPhotographer { + public override init( + renderer: SentryViewRenderer, + redactOptions: any SentryRedactOptions, + enableMaskRendererV2: Bool = false + ) { + super.init( + renderer: renderer, + redactOptions: redactOptions, + enableMaskRendererV2: enableMaskRendererV2 + ) + } +} +#endif diff --git a/SentryTestUtils/TestSentryViewRenderer.swift b/SentryTestUtils/TestSentryViewRenderer.swift new file mode 100644 index 00000000000..06e0a0f14fb --- /dev/null +++ b/SentryTestUtils/TestSentryViewRenderer.swift @@ -0,0 +1,30 @@ +#if canImport(UIKit) && !SENTRY_NO_UIKIT +#if os(iOS) || os(tvOS) + +@_spi(Private) @testable import Sentry +import UIKit + +@_spi(Private) public class TestSentryViewRenderer: NSObject, SentryViewRenderer { + /// Records invocations of `render(view:)`. + public let renderInvocations: Invocations> = Invocations() + + /// The value to be returned by `render(view:)`. If `nil`, `render(view:)` will fail with a precondition failure. + public var mockedReturnValue: UIImage? + + /// An optional closure that gets called when `render(view:)` is invoked. + /// + /// Can be used to inspect the view passed to `render(view:)`. + public var onRender: ((UIView) -> Void)? + + public func render(view: UIView) -> UIImage { + renderInvocations.record(WeakReference(value: view)) + onRender?(view) + guard let mockedReturnValue = mockedReturnValue else { + preconditionFailure("TestSentryViewRendererV2: No mocked return value set for render(view:)") + } + return mockedReturnValue + } +} + +#endif // os(iOS) || os(tvOS) +#endif // canImport(UIKit) && !SENTRY_NO_UIKIT diff --git a/SentryTestUtils/TestTransport.swift b/SentryTestUtils/TestTransport.swift index 145dbef2517..332fd5d44a0 100644 --- a/SentryTestUtils/TestTransport.swift +++ b/SentryTestUtils/TestTransport.swift @@ -3,13 +3,13 @@ import Foundation public class TestTransport: NSObject, Transport { - public var sentEnvelopes = Invocations() - public func send(envelope: SentryEnvelope) { + @_spi(Private) public var sentEnvelopes = Invocations() + @_spi(Private) public func send(envelope: SentryEnvelope) { sentEnvelopes.record(envelope) } - public var storedEnvelopes = Invocations() - public func store(_ envelope: SentryEnvelope) { + @_spi(Private) public var storedEnvelopes = Invocations() + @_spi(Private) public func store(_ envelope: SentryEnvelope) { storedEnvelopes.record(envelope) } diff --git a/SentryTestUtils/TestTransportAdapter.swift b/SentryTestUtils/TestTransportAdapter.swift index ed3d0bc7fce..8b0d21ad1d8 100644 --- a/SentryTestUtils/TestTransportAdapter.swift +++ b/SentryTestUtils/TestTransportAdapter.swift @@ -1,18 +1,21 @@ import _SentryPrivate import Foundation +@_spi(Private) import Sentry -public class TestTransportAdapter: SentryTransportAdapter { +@_spi(Private) public class TestTransportAdapter: SentryTransportAdapter { + @_spi(Private) public var sentEventsWithSessionTraceState = Invocations<(event: Event, session: SentrySession, traceContext: TraceContext?, attachments: [Attachment])>() + @_spi(Private) public override func send(_ event: Event, with session: SentrySession, traceContext: TraceContext?, attachments: [Attachment]) { sentEventsWithSessionTraceState.record((event, session, traceContext, attachments)) } - public var sendEventWithTraceStateInvocations = Invocations<(event: Event, traceContext: TraceContext?, attachments: [Attachment], additionalEnvelopeItems: [SentryEnvelopeItem])>() + @_spi(Private) public var sendEventWithTraceStateInvocations = Invocations<(event: Event, traceContext: TraceContext?, attachments: [Attachment], additionalEnvelopeItems: [SentryEnvelopeItem])>() public override func send(event: Event, traceContext: TraceContext?, attachments: [Attachment]) { sendEventWithTraceStateInvocations.record((event, traceContext, attachments, [])) } - public override func send(event: Event, traceContext: TraceContext?, attachments: [Attachment], additionalEnvelopeItems: [SentryEnvelopeItem]) { + @_spi(Private) public override func send(event: Event, traceContext: TraceContext?, attachments: [Attachment], additionalEnvelopeItems: [SentryEnvelopeItem]) { sendEventWithTraceStateInvocations.record((event, traceContext, attachments, additionalEnvelopeItems)) } diff --git a/SentryTestUtils/WeakReference.swift b/SentryTestUtils/WeakReference.swift index fb0ccb2a841..06ddf9b74b6 100644 --- a/SentryTestUtils/WeakReference.swift +++ b/SentryTestUtils/WeakReference.swift @@ -5,8 +5,9 @@ import Foundation /// keeps track of method invocation arguments. You can use this class if /// you don't want the invocations class to retain objects. public class WeakReference { - weak var value: T? - init (value: T) { - self.value = value - } + public weak var value: T? + + public init (value: T) { + self.value = value + } } diff --git a/SentryTestUtilsTests/TestConstantTests.swift b/SentryTestUtilsTests/TestConstantTests.swift index 86603b4b3b5..73b6f5d03b0 100644 --- a/SentryTestUtilsTests/TestConstantTests.swift +++ b/SentryTestUtilsTests/TestConstantTests.swift @@ -1,4 +1,5 @@ import Foundation +@_spi(Private) import Sentry @_spi(Private) @testable import SentryTestUtils import XCTest @@ -97,6 +98,7 @@ class TestConstantTests: XCTestCase { XCTAssertEqual(sdkEvent.timestamp, date) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testEnvelope_shouldReturnValidEnvelopeWithOneItem() throws { // -- Act -- let envelope = TestConstants.envelope diff --git a/SentryTestUtilsTests/TestFileManagerTests.swift b/SentryTestUtilsTests/TestFileManagerTests.swift index 0491922ffc2..459b380aa0b 100644 --- a/SentryTestUtilsTests/TestFileManagerTests.swift +++ b/SentryTestUtilsTests/TestFileManagerTests.swift @@ -1,3 +1,4 @@ +@_spi(Private) import Sentry @_spi(Private) @testable import SentryTestUtils import XCTest @@ -5,6 +6,7 @@ class TestFileManagerTests: XCTestCase { private class Fixture { fileprivate var dateProvider = TestCurrentDateProvider() + fileprivate var dispatchQueueWrapper = TestSentryDispatchQueueWrapper() fileprivate var options: Options! init(testName: String) { @@ -17,11 +19,19 @@ class TestFileManagerTests: XCTestCase { } func getSut() throws -> TestFileManager { - return try TestFileManager(options: options) + return try TestFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: dispatchQueueWrapper + ) } func getActualFileManagerSut() throws -> SentryFileManager { - return try SentryFileManager(options: options) + return try SentryFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: dispatchQueueWrapper + ) } } @@ -35,6 +45,7 @@ class TestFileManagerTests: XCTestCase { sut = try fixture.getSut() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testStore_whenStoreEnvelopePathNilIsTrue_shouldRecordInvocationAndReturnNil() { // -- Arrange -- let envelope = TestConstants.envelope @@ -52,6 +63,7 @@ class TestFileManagerTests: XCTestCase { XCTAssertEqual(sut.storeEnvelopeInvocations.invocations.element(at: 1), envelope) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testStore_whenStoreEnvelopePathNilIsFalse_whenMockPathIsDefined_shouldRecordInvocationAndReturnMockPath() { // -- Arrange -- let envelope = TestConstants.envelope @@ -70,6 +82,7 @@ class TestFileManagerTests: XCTestCase { XCTAssertEqual(sut.storeEnvelopeInvocations.invocations.element(at: 1), envelope) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testStore_whenStoreEnvelopePathNilIsFalse_whenMockPathIsNotDefined_shouldRecordInvocationAndReturnActualPath() throws { // -- Arrange -- let envelope = TestConstants.envelope @@ -88,8 +101,8 @@ class TestFileManagerTests: XCTestCase { // -- Assert -- // The paths are ending in a unique UUID, so we can only compare the prefix excluding the last 32 random characters and the `.json` extension - XCTAssertTrue(result1.hasPrefix(trimmedActualPath1) == true) - XCTAssertTrue(result2.hasPrefix(trimmedActualPath2) == true) + XCTAssertTrue(result1.hasPrefix(trimmedActualPath1) == true, "'\(result1)' does not have prefix '\(trimmedActualPath1)'") + XCTAssertTrue(result2.hasPrefix(trimmedActualPath2) == true, "'\(result2)' does not have prefix '\(trimmedActualPath2)'") XCTAssertEqual(sut.storeEnvelopeInvocations.count, 2) XCTAssertEqual(sut.storeEnvelopeInvocations.invocations.element(at: 0), envelope) XCTAssertEqual(sut.storeEnvelopeInvocations.invocations.element(at: 1), envelope) diff --git a/SentryTestUtilsTests/TestNSNotificationCenterWrapperTests.swift b/SentryTestUtilsTests/TestNSNotificationCenterWrapperTests.swift index 98ee3dac7e7..af9b9cf882d 100644 --- a/SentryTestUtilsTests/TestNSNotificationCenterWrapperTests.swift +++ b/SentryTestUtilsTests/TestNSNotificationCenterWrapperTests.swift @@ -25,7 +25,7 @@ class TestNSNotificationCenterWrapperTests: XCTestCase { sut.addObserver(self, selector: dummySelector, name: notificationName) // -- Assert -- - let invocations = sut.addObserverInvocations + let invocations = sut.addObserverWithObjectInvocations XCTAssertEqual(invocations.count, 1) let invocation = try XCTUnwrap(invocations.invocations.first) XCTAssertIdentical(invocation.observer.value, self) @@ -41,7 +41,7 @@ class TestNSNotificationCenterWrapperTests: XCTestCase { sut.addObserver(self, selector: dummySelector, name: notificationName) // -- Assert -- - XCTAssertEqual(sut.addObserverInvocations.count, 0) + XCTAssertEqual(sut.addObserverWithObjectInvocations.count, 0) } func testAddObserverWithObject_whenIgnoreAddObserverIsFalse_shouldRecordObserver() throws { @@ -95,9 +95,9 @@ class TestNSNotificationCenterWrapperTests: XCTestCase { sut.removeObserver(self, name: notificationName) // -- Assert -- - XCTAssertEqual(sut.removeObserverWithNameInvocations.count, 1) - let invocation = try XCTUnwrap(sut.removeObserverWithNameInvocations.invocations.first) - XCTAssertEqual(invocation, notificationName) + XCTAssertEqual(sut.removeObserverWithNameAndObjectInvocations.count, 1) + let invocation = try XCTUnwrap(sut.removeObserverWithNameAndObjectInvocations.invocations.first) + XCTAssertEqual(invocation.name, notificationName) } func testRemoveObserver_whenIgnoreRemoveObserverIsFalse_shouldRecordRemoval() throws { @@ -108,7 +108,7 @@ class TestNSNotificationCenterWrapperTests: XCTestCase { sut.removeObserver(self) // -- Assert -- - XCTAssertEqual(sut.removeObserverInvocations.count, 1) + XCTAssertEqual(sut.removeObserverWithNameAndObjectInvocations.count, 1) } func testRemoveObserver_whenIgnoreRemoveObserverIsTrue_shouldNotRecordRemoval() { @@ -119,7 +119,7 @@ class TestNSNotificationCenterWrapperTests: XCTestCase { sut.removeObserver(self) // -- Assert -- - XCTAssertEqual(sut.removeObserverInvocations.count, 0) + XCTAssertEqual(sut.removeObserverWithNameAndObjectInvocations.count, 0) } func testPost_whenObserverAdded_shouldPerformSelectorOnObserverObject() { @@ -189,9 +189,9 @@ class TestNSNotificationCenterWrapperTests: XCTestCase { sut.removeObserver(self, forKeyPath: keyPath) // -- Assert -- - XCTAssertEqual(sut.removeObserverForKeyPathInvocations.count, 1) - let invocation = try XCTUnwrap(sut.removeObserverForKeyPathInvocations.invocations.first) - XCTAssertEqual(invocation, keyPath) + XCTAssertEqual(sut.removeObserverForKeyPathWithContextInvocations.count, 1) + let invocation = try XCTUnwrap(sut.removeObserverForKeyPathWithContextInvocations.invocations.first) + XCTAssertEqual(invocation.keyPath, keyPath) } func testRemoveObserverForKeyPath_whenIgnoreRemoveObserverIsTrue_shouldNotRecordRemoval() { @@ -202,7 +202,7 @@ class TestNSNotificationCenterWrapperTests: XCTestCase { sut.removeObserver(self, forKeyPath: keyPath) // -- Assert -- - XCTAssertEqual(sut.removeObserverForKeyPathInvocations.count, 0) + XCTAssertEqual(sut.removeObserverForKeyPathWithContextInvocations.count, 0) } func testRemoveObserverForKeyPathWithContext_whenIgnoreRemoveObserverIsFalse_shouldRecordRemoval() throws { @@ -492,21 +492,20 @@ class TestNSNotificationCenterWrapperTests: XCTestCase { // Verify we have observers and invocations before clearing XCTAssertEqual(sut.observerCount, 3) - XCTAssertEqual(sut.addObserverInvocations.count, 1) - XCTAssertEqual(sut.addObserverWithObjectInvocations.count, 1) + XCTAssertEqual(sut.addObserverWithObjectInvocations.count, 2) XCTAssertEqual(sut.addObserverForKeyPathWithContextInvocations.count, 1) - XCTAssertEqual(sut.removeObserverInvocations.count, 1) + XCTAssertEqual(sut.removeObserverWithNameAndObjectInvocations.count, 1) // -- Act -- sut.clearAllObservers() // -- Assert -- XCTAssertEqual(sut.observerCount, 0) - XCTAssertEqual(sut.addObserverInvocations.count, 0) + XCTAssertEqual(sut.addObserverWithObjectInvocations.count, 0) XCTAssertEqual(sut.addObserverWithObjectInvocations.count, 0) XCTAssertEqual(sut.addObserverForKeyPathWithContextInvocations.count, 0) XCTAssertEqual(sut.addObserverWithBlockInvocations.count, 0) - XCTAssertEqual(sut.removeObserverInvocations.count, 0) + XCTAssertEqual(sut.removeObserverWithNameAndObjectInvocations.count, 0) } func testIgnoreFlags_whenSet_shouldPreventOperations() { @@ -520,8 +519,8 @@ class TestNSNotificationCenterWrapperTests: XCTestCase { // -- Assert -- XCTAssertEqual(sut.observerCount, 0) - XCTAssertEqual(sut.addObserverInvocations.count, 0) - XCTAssertEqual(sut.removeObserverInvocations.count, 0) + XCTAssertEqual(sut.addObserverWithObjectInvocations.count, 0) + XCTAssertEqual(sut.removeObserverWithNameAndObjectInvocations.count, 0) } // MARK: - Helpers diff --git a/Sources/Configuration/DeploymentTargets.xcconfig b/Sources/Configuration/DeploymentTargets.xcconfig index cc7e4588e89..9184db22ccd 100644 --- a/Sources/Configuration/DeploymentTargets.xcconfig +++ b/Sources/Configuration/DeploymentTargets.xcconfig @@ -1,4 +1,5 @@ MAJOR_VERSION_DebugV9 = 9 +MAJOR_VERSION_ReleaseV9 = 9 MAJOR_VERSION=$(MAJOR_VERSION_$(CONFIGURATION)) // Defaults when no version is specified @@ -10,19 +11,11 @@ WATCHOS_DEPLOYMENT_TARGET_V = 4.0 // SDK v9 versions MACOSX_DEPLOYMENT_TARGET_V9 = 10.14 IPHONEOS_DEPLOYMENT_TARGET_V9 = 12.0 +TVOS_DEPLOYMENT_TARGET_V9 = 12.0 WATCHOS_DEPLOYMENT_TARGET_V9 = 5.0 -TVOS_DEPLOYMENT_TARGET_V9 = 11.0 MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_V$(MAJOR_VERSION)) IPHONEOS_DEPLOYMENT_TARGET = $(IPHONEOS_DEPLOYMENT_TARGET_V$(MAJOR_VERSION)) WATCHOS_DEPLOYMENT_TARGET = $(WATCHOS_DEPLOYMENT_TARGET_V$(MAJOR_VERSION)) TVOS_DEPLOYMENT_TARGET = $(TVOS_DEPLOYMENT_TARGET_V$(MAJOR_VERSION)) XROS_DEPLOYMENT_TARGET = 1.0 - -GCC_PREPROCESSOR_DEFINITIONS_V9 = $(GCC_PREPROCESSOR_DEFINITIONS) SDK_V$(MAJOR_VERSION) -GCC_PREPROCESSOR_DEFINITIONS_V = $(GCC_PREPROCESSOR_DEFINITIONS) -GCC_PREPROCESSOR_DEFINITIONS = $(GCC_PREPROCESSOR_DEFINITIONS_V$(MAJOR_VERSION)) - -SWIFT_ACTIVE_COMPILATION_CONDITIONS_V9 = $(SWIFT_ACTIVE_COMPILATION_CONDITIONS) SDK_V$(MAJOR_VERSION) -SWIFT_ACTIVE_COMPILATION_CONDITIONS_V = $(SWIFT_ACTIVE_COMPILATION_CONDITIONS) -SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(SWIFT_ACTIVE_COMPILATION_CONDITIONS_V$(MAJOR_VERSION)) diff --git a/Sources/Configuration/SDK.xcconfig b/Sources/Configuration/SDK.xcconfig index 0d6018772ab..5016ff25399 100644 --- a/Sources/Configuration/SDK.xcconfig +++ b/Sources/Configuration/SDK.xcconfig @@ -10,7 +10,7 @@ DYLIB_INSTALL_NAME_BASE = @rpath MACH_O_TYPE = mh_dylib FRAMEWORK_VERSION = A -CURRENT_PROJECT_VERSION = 8.53.2 +CURRENT_PROJECT_VERSION = 8.56.0 ALWAYS_SEARCH_USER_PATHS = NO CLANG_ENABLE_OBJC_ARC = YES @@ -18,6 +18,7 @@ CLANG_ENABLE_MODULES = YES //OTHER_CFLAGS = -Wall -Wextra -Wpedantic -Wno-gnu-conditional-omitted-operand GCC_OPTIMIZATION_LEVEL_Debug = 0 +GCC_OPTIMIZATION_LEVEL_DebugV9 = 0 GCC_OPTIMIZATION_LEVEL_DebugWithoutUIKit = 0 GCC_OPTIMIZATION_LEVEL_Release = s GCC_OPTIMIZATION_LEVEL_ReleaseWithoutUIKit = s @@ -26,6 +27,7 @@ GCC_OPTIMIZATION_LEVEL_TestCI = 0 GCC_OPTIMIZATION_LEVEL = $(GCC_OPTIMIZATION_LEVEL_$(CONFIGURATION)) COPY_PHASE_STRIP_Debug = NO +COPY_PHASE_STRIP_DebugV9 = NO COPY_PHASE_STRIP_DebugWithoutUIKit = YES COPY_PHASE_STRIP_Release = YES COPY_PHASE_STRIP_ReleaseWithoutUIKit = YES @@ -46,27 +48,32 @@ CLANG_CXX_LIBRARY = libc++ HEADER_SEARCH_PATHS = $(SRCROOT)/Sources/Sentry/include/** SWIFT_ACTIVE_COMPILATION_CONDITIONS_Debug = DEBUG +SWIFT_ACTIVE_COMPILATION_CONDITIONS_DebugV9 = SDK_V9 DEBUG SWIFT_ACTIVE_COMPILATION_CONDITIONS_DebugWithoutUIKit = DEBUG SENTRY_NO_UIKIT SWIFT_ACTIVE_COMPILATION_CONDITIONS_Test = SENTRY_TEST SWIFT_ACTIVE_COMPILATION_CONDITIONS_TestCI = SENTRY_TEST_CI SWIFT_ACTIVE_COMPILATION_CONDITIONS_Release = +SWIFT_ACTIVE_COMPILATION_CONDITIONS_ReleaseV9 = SDK_V9 SWIFT_ACTIVE_COMPILATION_CONDITIONS_ReleaseWithoutUIKit = SENTRY_NO_UIKIT SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(SWIFT_ACTIVE_COMPILATION_CONDITIONS_$(CONFIGURATION)) GCC_PREPROCESSOR_DEFINITIONS_Debug = DEBUG=1 +GCC_PREPROCESSOR_DEFINITIONS_DebugV9 = SDK_V9=1 DEBUG=1 GCC_PREPROCESSOR_DEFINITIONS_DebugWithoutUIKit = DEBUG=1 SENTRY_NO_UIKIT=1 GCC_PREPROCESSOR_DEFINITIONS_Test = DEBUG=1 SENTRY_TEST=1 GCC_PREPROCESSOR_DEFINITIONS_TestCI = DEBUG=1 SENTRY_TEST=1 SENTRY_TEST_CI=1 GCC_PREPROCESSOR_DEFINITIONS_Release = RELEASE=1 +GCC_PREPROCESSOR_DEFINITIONS_ReleaseV9 = SDK_V9=1 RELEASE=1 GCC_PREPROCESSOR_DEFINITIONS_ReleaseWithoutUIKit = RELEASE=1 SENTRY_NO_UIKIT=1 GCC_PREPROCESSOR_DEFINITIONS = $(GCC_PREPROCESSOR_DEFINITIONS_$(CONFIGURATION)) -SWIFT_OBJC_INTEROP_MODE[sdk=xr*]=objcxx CODE_SIGN_IDENTITY = iPhone Developer ONLY_ACTIVE_ARCH_Debug = YES +ONLY_ACTIVE_ARCH_DebugV9 = YES ONLY_ACTIVE_ARCH_DebugWithoutUIKit = YES ONLY_ACTIVE_ARCH_Release = NO +ONLY_ACTIVE_ARCH_ReleaseV9 = NO ONLY_ACTIVE_ARCH_ReleaseWithoutUIKit = NO ONLY_ACTIVE_ARCH_Test = YES ONLY_ACTIVE_ARCH_TestCI = YES @@ -75,22 +82,27 @@ ONLY_ACTIVE_ARCH = $(ONLY_ACTIVE_ARCH_$(CONFIGURATION)) GCC_NO_COMMON_BLOCKS = YES DEBUG_INFORMATION_FORMAT_Debug = dwarf +DEBUG_INFORMATION_FORMAT_DebugV9 = dwarf DEBUG_INFORMATION_FORMAT_DebugWithoutUIKit = dwarf DEBUG_INFORMATION_FORMAT_Release = dwarf-with-dsym +DEBUG_INFORMATION_FORMAT_ReleaseV9 = dwarf-with-dsym DEBUG_INFORMATION_FORMAT_ReleaseWithoutUIKit = dwarf-with-dsym DEBUG_INFORMATION_FORMAT_Test = dwarf DEBUG_INFORMATION_FORMAT_TestCI = dwarf DEBUG_INFORMATION_FORMAT = $(DEBUG_INFORMATION_FORMAT_$(CONFIGURATION)) ENABLE_TESTABILITY_Debug = YES +ENABLE_TESTABILITY_DebugV9 = YES ENABLE_TESTABILITY_DebugWithoutUIKit = YES ENABLE_TESTABILITY_Release = NO +ENABLE_TESTABILITY_ReleaseV9 = NO ENABLE_TESTABILITY_ReleaseWithotuUIKit = NO ENABLE_TESTABILITY_Test = YES ENABLE_TESTABILITY_TestCI = YES ENABLE_TESTABILITY = $(ENABLE_TESTABILITY_$(CONFIGURATION)) VALIDATE_PRODUCT_Release = YES +VALIDATE_PRODUCT_ReleaseV9 = YES VALIDATE_PRODUCT_ReleaseWithoutUIKit = YES VALIDATE_PRODUCT_Debug = NO VALIDATE_PRODUCT_DebugWithoutUIKit = NO @@ -102,7 +114,9 @@ CODE_SIGN_IDENTITY[sdk=iphoneos*] = iPhone Developer GCC_C_LANGUAGE_STANDARD = gnu99 CLANG_MODULES_AUTOLINK_Debug = YES +CLANG_MODULES_AUTOLINK_DebugV9 = YES CLANG_MODULES_AUTOLINK_Release = YES +CLANG_MODULES_AUTOLINK_ReleaseV9 = YES CLANG_MODULES_AUTOLINK_Test = YES CLANG_MODULES_AUTOLINK_TestCI = YES CLANG_MODULES_AUTOLINK_DebugWithoutUIKit = NO @@ -111,9 +125,11 @@ CLANG_MODULES_AUTOLINK = $(CLANG_MODULES_AUTOLINK_$(CONFIGURATION)) ENABLE_NS_ASSERTIONS_DebugWithoutUIKit = YES ENABLE_NS_ASSERTIONS_Debug = YES +ENABLE_NS_ASSERTIONS_DebugV9 = YES ENABLE_NS_ASSERTIONS_Test = YES ENABLE_NS_ASSERTIONS_TestCI = YES ENABLE_NS_ASSERTIONS_Release = NO +ENABLE_NS_ASSERTIONS_ReleaseV9 = NO ENABLE_NS_ASSERTIONS_ReleaseWithoutUIKit = NO ENABLE_NS_ASSERTIONS = $(ENABLE_NS_ASSERTIONS_$(CONFIGURATION)) @@ -149,16 +165,20 @@ CLANG_ANALYZER_NONNULL = YES SWIFT_COMPILATION_MODE_DebugWithoutUIKit = singlefile SWIFT_COMPILATION_MODE_Debug = singlefile +SWIFT_COMPILATION_MODE_DebugV9 = singlefile SWIFT_COMPILATION_MODE_Test = singlefile SWIFT_COMPILATION_MODE_TestCI = singlefile SWIFT_COMPILATION_MODE_Release = wholemodule +SWIFT_COMPILATION_MODE_ReleaseV9 = wholemodule SWIFT_COMPILATION_MODE_ReleaseWithoutUIKit = wholemodule SWIFT_COMPILATION_MODE = $(SWIFT_COMPILATION_MODE_$(CONFIGURATION)) SWIFT_OPTIMIZATION_LEVEL_Debug = -Onone +SWIFT_OPTIMIZATION_LEVEL_DebugV9 = -Onone SWIFT_OPTIMIZATION_LEVEL_DebugWithoutUIKit = -Onone -SWIFT_OPTIMIZATION_LEVEL_Release = -O -SWIFT_OPTIMIZATION_LEVEL_ReleaseWithoutUIKit = -O +SWIFT_OPTIMIZATION_LEVEL_Release = -Osize +SWIFT_OPTIMIZATION_LEVEL_ReleaseV9 = -Osize +SWIFT_OPTIMIZATION_LEVEL_ReleaseWithoutUIKit = -Osize SWIFT_OPTIMIZATION_LEVEL_Test = -Onone SWIFT_OPTIMIZATION_LEVEL_TestCI = -Onone SWIFT_OPTIMIZATION_LEVEL = $(SWIFT_OPTIMIZATION_LEVEL_$(CONFIGURATION)) @@ -166,8 +186,10 @@ SWIFT_OPTIMIZATION_LEVEL = $(SWIFT_OPTIMIZATION_LEVEL_$(CONFIGURATION)) SWIFT_TREAT_WARNINGS_AS_ERRORS = YES MTL_ENABLE_DEBUG_INFO_Debug = YES +MTL_ENABLE_DEBUG_INFO_DebugV9 = YES MTL_ENABLE_DEBUG_INFO_DebugWithoutUIKit = YES MTL_ENABLE_DEBUG_INFO_Release = NO +MTL_ENABLE_DEBUG_INFO_ReleaseV9 = NO MTL_ENABLE_DEBUG_INFO_ReleaseWithoutUIKit = NO MTL_ENABLE_DEBUG_INFO_Test = YES MTL_ENABLE_DEBUG_INFO_TestCI = YES diff --git a/Sources/Configuration/Sentry.xcconfig b/Sources/Configuration/Sentry.xcconfig index 46657682cd4..1d91bccc0f3 100644 --- a/Sources/Configuration/Sentry.xcconfig +++ b/Sources/Configuration/Sentry.xcconfig @@ -15,6 +15,7 @@ PRODUCT_MODULE_NAME_DebugWithoutUIKit = $(SENTRY_WITHOUT_UIKIT_MODULE_NAME) PRODUCT_MODULE_NAME_Test = $(SENTRY_MODULE_NAME) PRODUCT_MODULE_NAME_TestCI = $(SENTRY_MODULE_NAME) PRODUCT_MODULE_NAME_Release = $(SENTRY_MODULE_NAME) +PRODUCT_MODULE_NAME_ReleaseV9 = $(SENTRY_MODULE_NAME) PRODUCT_MODULE_NAME_ReleaseWithoutUIKit = $(SENTRY_WITHOUT_UIKIT_MODULE_NAME) PRODUCT_MODULE_NAME = $(PRODUCT_MODULE_NAME_$(CONFIGURATION)) diff --git a/Sources/Configuration/SentrySwiftUI.xcconfig b/Sources/Configuration/SentrySwiftUI.xcconfig index f512151c4c9..0c06abceb79 100644 --- a/Sources/Configuration/SentrySwiftUI.xcconfig +++ b/Sources/Configuration/SentrySwiftUI.xcconfig @@ -1,5 +1,5 @@ PRODUCT_NAME = SentrySwiftUI -CURRENT_PROJECT_VERSION = 8.53.2 +CURRENT_PROJECT_VERSION = 8.56.0 MACOSX_DEPLOYMENT_TARGET = 10.15 IPHONEOS_DEPLOYMENT_TARGET = 13.0 diff --git a/Sources/Configuration/Versioning.xcconfig b/Sources/Configuration/Versioning.xcconfig index e414e0be6ca..fb068963b34 100644 --- a/Sources/Configuration/Versioning.xcconfig +++ b/Sources/Configuration/Versioning.xcconfig @@ -1,2 +1,2 @@ CURRENT_PROJECT_VERSION = 1 -MARKETING_VERSION = 8.53.2 +MARKETING_VERSION = 8.56.0 diff --git a/Sources/Resources/Sentry.modulemap b/Sources/Resources/Sentry.modulemap index 9b217fc516f..3f474c69cca 100644 --- a/Sources/Resources/Sentry.modulemap +++ b/Sources/Resources/Sentry.modulemap @@ -9,15 +9,12 @@ framework module Sentry { header "PrivateSentrySDKOnly.h" header "PrivatesHeader.h" header "SentryAppStartMeasurement.h" - header "SentryBinaryImageCache.h" header "SentryBreadcrumb+Private.h" header "SentryDebugImageProvider+HybridSDKs.h" header "SentryDependencyContainer.h" - header "SentryEnvelope.h" - header "SentryEnvelopeItemType.h" header "SentryFormatter.h" header "SentryFramesTracker.h" - header "SentryOptions+HybridSDKs.h" + header "SentryOptionsInternal.h" header "SentryScreenFrames.h" header "SentrySwizzle.h" header "SentryUser+Private.h" @@ -26,7 +23,6 @@ framework module Sentry { header "SentrySessionReplayIntegration.h" header "SentrySessionReplayIntegration-Hybrid.h" - header "SentrySdkInfo.h" header "SentryInternalSerializable.h" export * diff --git a/Sources/Sentry/PrivateSentrySDKOnly.m b/Sources/Sentry/PrivateSentrySDKOnly.m index 8da3583773e..012ff3f554b 100644 --- a/Sources/Sentry/PrivateSentrySDKOnly.m +++ b/Sources/Sentry/PrivateSentrySDKOnly.m @@ -2,6 +2,7 @@ #import "SentryAppStartMeasurement.h" #import "SentryBreadcrumb+Private.h" #import "SentryClient.h" +#import "SentryDebugImageProvider+HybridSDKs.h" #import "SentryDebugImageProvider.h" #import "SentryExtraContextProvider.h" #import "SentryHub+Private.h" @@ -39,12 +40,12 @@ @implementation PrivateSentrySDKOnly + (void)storeEnvelope:(SentryEnvelope *)envelope { - [SentrySDK storeEnvelope:envelope]; + [SentrySDKInternal storeEnvelope:envelope]; } + (void)captureEnvelope:(SentryEnvelope *)envelope { - [SentrySDK captureEnvelope:envelope]; + [SentrySDKInternal captureEnvelope:envelope]; } + (nullable SentryEnvelope *)envelopeWithData:(NSData *)data @@ -52,6 +53,7 @@ + (nullable SentryEnvelope *)envelopeWithData:(NSData *)data return [SentrySerialization envelopeWithData:data]; } +#if !SDK_V9 + (NSArray *)getDebugImages { // maintains previous behavior for the same method call by also trying to gather crash info @@ -60,22 +62,23 @@ + (nullable SentryEnvelope *)envelopeWithData:(NSData *)data + (NSArray *)getDebugImagesCrashed:(BOOL)isCrash { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" return [[SentryDependencyContainer sharedInstance].debugImageProvider getDebugImagesCrashed:isCrash]; -#pragma clang diagnostic pop +# pragma clang diagnostic pop } +#endif // !SDK_V9 + (nullable SentryAppStartMeasurement *)appStartMeasurement { - return [SentrySDK getAppStartMeasurement]; + return [SentrySDKInternal getAppStartMeasurement]; } + (nullable NSDictionary *)appStartMeasurementWithSpans { #if SENTRY_HAS_UIKIT - SentryAppStartMeasurement *measurement = [SentrySDK getAppStartMeasurement]; + SentryAppStartMeasurement *measurement = [SentrySDKInternal getAppStartMeasurement]; if (measurement == nil) { return nil; } @@ -139,7 +142,7 @@ + (NSString *)installationID + (SentryOptions *)options { - SentryOptions *options = [[SentrySDK currentHub] client].options; + SentryOptions *options = [[SentrySDKInternal currentHub] client].options; if (options != nil) { return options; } @@ -200,7 +203,7 @@ + (NSDictionary *)getExtraContext + (void)setTrace:(SentryId *)traceId spanId:(SentrySpanId *)spanId { - [SentrySDK.currentHub configureScope:^(SentryScope *scope) { + [SentrySDKInternal.currentHub configureScope:^(SentryScope *scope) { scope.propagationContext = [[SentryPropagationContext alloc] initWithTraceId:traceId spanId:spanId]; }]; @@ -224,7 +227,7 @@ + (uint64_t)startProfilerForTrace:(SentryId *)traceId; + (void)discardProfilerForTrace:(SentryId *)traceId; { - sentry_discardProfilerCorrelatedToTrace(traceId, SentrySDK.currentHub); + sentry_discardProfilerCorrelatedToTrace(traceId, SentrySDKInternal.currentHub); } #endif // SENTRY_TARGET_PROFILING_SUPPORTED @@ -279,7 +282,11 @@ + (SentryScreenFrames *)currentScreenFrames + (NSArray *)captureScreenshots { #if SENTRY_TARGET_REPLAY_SUPPORTED - return [SentryDependencyContainer.sharedInstance.screenshot appScreenshotsData]; + // As the options are not passed in by the hybrid SDK, we need to use the options from the + // current hub. + SentryScreenshotSource *_Nonnull screenshotSource + = SentryDependencyContainer.sharedInstance.screenshotSource; + return [screenshotSource appScreenshotsData]; #else SENTRY_LOG_DEBUG( @"PrivateSentrySDKOnly.captureScreenshots only works with UIKit enabled. Ensure you're " @@ -289,9 +296,9 @@ + (SentryScreenFrames *)currentScreenFrames } #if SENTRY_UIKIT_AVAILABLE -+ (void)setCurrentScreen:(NSString *)screenName ++ (void)setCurrentScreen:(NSString *_Nullable)screenName { - [SentrySDK.currentHub + [SentrySDKInternal.currentHub configureScope:^(SentryScope *scope) { scope.currentScreen = screenName; }]; } #endif // SENTRY_HAS_UIKIT @@ -328,7 +335,7 @@ + (UIView *)sessionReplayMaskingOverlay:(id)options + (nullable SentrySessionReplayIntegration *)getReplayIntegration { - NSArray *integrations = [[SentrySDK currentHub] installedIntegrations]; + NSArray *integrations = [[SentrySDKInternal currentHub] installedIntegrations]; SentrySessionReplayIntegration *replayIntegration; for (id obj in integrations) { if ([obj isKindOfClass:[SentrySessionReplayIntegration class]]) { diff --git a/Sources/Sentry/Processors/SentryWatchdogTerminationBreadcrumbProcessor.m b/Sources/Sentry/Processors/SentryWatchdogTerminationBreadcrumbProcessor.m index ecf87e4e06e..c1c2a31dd3a 100644 --- a/Sources/Sentry/Processors/SentryWatchdogTerminationBreadcrumbProcessor.m +++ b/Sources/Sentry/Processors/SentryWatchdogTerminationBreadcrumbProcessor.m @@ -1,5 +1,6 @@ #import "SentryWatchdogTerminationBreadcrumbProcessor.h" #import "SentryFileManager.h" +#import "SentryInternalDefines.h" #import "SentryLogC.h" #import "SentrySerialization.h" @@ -44,7 +45,7 @@ - (void)addSerializedBreadcrumb:(NSDictionary *)crumb SENTRY_LOG_ERROR(@"Error serializing breadcrumb to JSON"); return; } - [self storeBreadcrumb:jsonData]; + [self storeBreadcrumb:SENTRY_UNWRAP_NULLABLE(NSData, jsonData)]; } - (void)clear @@ -103,7 +104,8 @@ - (void)storeBreadcrumb:(NSData *_Nonnull)data fileSize = [self.fileHandle seekToEndOfFile]; [self.fileHandle writeData:data]; - [self.fileHandle writeData:[@"\n" dataUsingEncoding:NSASCIIStringEncoding]]; + NSData *_Nonnull const newLineData = [NSData dataWithBytes:"\n" length:1]; + [self.fileHandle writeData:newLineData]; self.breadcrumbCounter += 1; } @catch (NSException *exception) { diff --git a/Sources/Sentry/Profiling/SentryContinuousProfiler.mm b/Sources/Sentry/Profiling/SentryContinuousProfiler.mm index c01fc2bc0ac..e621673577c 100644 --- a/Sources/Sentry/Profiling/SentryContinuousProfiler.mm +++ b/Sources/Sentry/Profiling/SentryContinuousProfiler.mm @@ -5,14 +5,12 @@ # import "SentryDependencyContainer.h" # import "SentryLogC.h" # import "SentryMetricProfiler.h" -# import "SentryNSNotificationCenterWrapper.h" -# import "SentryNSTimerFactory.h" # import "SentryProfiler+Private.h" # import "SentryProfilerSerialization.h" # import "SentryProfilerState.h" +# import "SentryProfilingSwiftHelpers.h" # import "SentrySDK+Private.h" # import "SentrySample.h" -# import "SentrySwift.h" # include # if SENTRY_HAS_UIKIT @@ -62,7 +60,7 @@ [profiler.state clear]; // !!!: profile this to see if it takes longer than one sample duration // length: ~9ms - const auto metricProfilerState = [profiler.metricProfiler serializeContinuousProfileMetrics]; + const auto metricProfilerState = [profiler.metricProfiler copyMetricProfilerData]; [profiler.metricProfiler clear]; # if SENTRY_HAS_UIKIT @@ -71,14 +69,22 @@ [framesTracker resetProfilingTimestamps]; # endif // SENTRY_HAS_UIKIT - const auto envelope = sentry_continuousProfileChunkEnvelope( - profiler.profilerId, profilerState, metricProfilerState + // Capture profiler ID on main thread since we need it for the background work + const auto profilerID = profiler.profilerId; + + // Move the serialization work to a background queue to avoid potentially + // blocking the main thread. The serialization can take several milliseconds. + sentry_dispatchAsync(SentryDependencyContainer.sharedInstance.dispatchQueueWrapper, ^{ + const auto serializedMetrics = serializeContinuousProfileMetrics(metricProfilerState); + const auto envelope + = sentry_continuousProfileChunkEnvelope(profilerID, profilerState, serializedMetrics # if SENTRY_HAS_UIKIT - , - screenFrameData + , + screenFrameData # endif // SENTRY_HAS_UIKIT - ); - [SentrySDK captureEnvelope:envelope]; + ); + [SentrySDKInternal captureEnvelope:envelope]; + }); } void @@ -114,27 +120,20 @@ + (void)start } static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ _profileSessionID = [[SentryId alloc] init]; }); + dispatch_once(&onceToken, ^{ _profileSessionID = sentry_getSentryId(); }); _threadUnsafe_gContinuousCurrentProfiler.profilerId = _profileSessionID; } - - [SentryDependencyContainer.sharedInstance.notificationCenterWrapper - postNotification:[[NSNotification alloc] - initWithName:kSentryNotificationContinuousProfileStarted - object:nil - userInfo:nil]]; + sentry_postNotification( + [[NSNotification alloc] initWithName:kSentryNotificationContinuousProfileStarted + object:nil + userInfo:nil]); [self scheduleTimer]; # if SENTRY_HAS_UIKIT - _observerToken = [SentryDependencyContainer.sharedInstance.notificationCenterWrapper - addObserverForName:UIApplicationWillResignActiveNotification - object:nil - queue:nil - usingBlock:^(NSNotification *_Nonnull notification) { - [SentryDependencyContainer.sharedInstance.notificationCenterWrapper - removeObserver:_observerToken]; - [self stopTimerAndCleanup]; - }]; + _observerToken = sentry_addObserverForName(UIApplicationWillResignActiveNotification, ^{ + sentry_removeObserver(_observerToken); + [self stopTimerAndCleanup]; + }); # endif // SENTRY_HAS_UIKIT } @@ -160,7 +159,7 @@ + (void)stop // https://github.com/getsentry/sentry-cocoa/pull/4214). we just want to look in its samples // for a call to main() if ([NSProcessInfo.processInfo.arguments - containsObject:@"--io.sentry.continuous-profiler-immediate-stop"]) { + containsObject:@"--io.sentry.profiling.continuous-profiler-immediate-stop"]) { _sentry_threadUnsafe_transmitChunkEnvelope(); _sentry_unsafe_stopTimerAndCleanup(); return; @@ -185,7 +184,7 @@ + (nullable SentryId *)currentProfilerID */ + (void)scheduleTimer { - [SentryDependencyContainer.sharedInstance.dispatchQueueWrapper dispatchAsyncOnMainQueue:^{ + sentry_dispatchAsyncOnMain(SentryDependencyContainer.sharedInstance.dispatchQueueWrapper, ^{ std::lock_guard l(_threadUnsafe_gContinuousProfilerLock); if (_chunkTimer != nil) { SENTRY_LOG_WARN(@"There was already a timer in flight, but this codepath shouldn't be " @@ -193,13 +192,9 @@ + (void)scheduleTimer return; } - _chunkTimer = [SentryDependencyContainer.sharedInstance.timerFactory - scheduledTimerWithTimeInterval:kSentryProfilerChunkExpirationInterval - target:self - selector:@selector(timerExpired) - userInfo:nil - repeats:YES]; - }]; + _chunkTimer = sentry_scheduledTimerWithTarget( + kSentryProfilerChunkExpirationInterval, self, @selector(timerExpired), nil, YES); + }); } + (void)timerExpired @@ -224,8 +219,7 @@ + (void)timerExpired # if SENTRY_HAS_UIKIT if (_observerToken != nil) { - [SentryDependencyContainer.sharedInstance.notificationCenterWrapper - removeObserver:_observerToken]; + sentry_removeObserver(_observerToken); } # endif // SENTRY_HAS_UIKIT diff --git a/Sources/Sentry/Profiling/SentryLaunchProfiling.m b/Sources/Sentry/Profiling/SentryLaunchProfiling.m index 911b127970e..43944238abf 100644 --- a/Sources/Sentry/Profiling/SentryLaunchProfiling.m +++ b/Sources/Sentry/Profiling/SentryLaunchProfiling.m @@ -9,8 +9,8 @@ # import "SentryLaunchProfiling.h" # import "SentryLogC.h" # import "SentryOptions+Private.h" +# import "SentryProfileConfiguration.h" # import "SentryProfiler+Private.h" -# import "SentryRandom.h" # import "SentrySamplerDecision.h" # import "SentrySampling.h" # import "SentrySamplingContext.h" @@ -18,65 +18,165 @@ # import "SentrySwift.h" # import "SentryTime.h" # import "SentryTraceOrigin.h" +# import "SentryTraceProfiler.h" # import "SentryTracer+Private.h" # import "SentryTracerConfiguration.h" # import "SentryTransactionContext+Private.h" NS_ASSUME_NONNULL_BEGIN -BOOL isProfilingAppLaunch; NSString *const kSentryLaunchProfileConfigKeyTracesSampleRate = @"traces"; NSString *const kSentryLaunchProfileConfigKeyTracesSampleRand = @"traces.sample_rand"; NSString *const kSentryLaunchProfileConfigKeyProfilesSampleRate = @"profiles"; NSString *const kSentryLaunchProfileConfigKeyProfilesSampleRand = @"profiles.sample_rand"; +# if !SDK_V9 NSString *const kSentryLaunchProfileConfigKeyContinuousProfiling = @"continuous-profiling"; +# endif // !SDK_V9 NSString *const kSentryLaunchProfileConfigKeyContinuousProfilingV2 = @"continuous-profiling-v2-enabled"; NSString *const kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle = @"continuous-profiling-v2-lifecycle"; -static SentryTracer *_Nullable launchTracer; +NSString *const kSentryLaunchProfileConfigKeyWaitForFullDisplay + = @"launch-profile.wait-for-full-display"; + +SentryTracer *_Nullable sentry_launchTracer; # pragma mark - Private -SentryTracer *_Nullable sentry_launchTracer; +SentrySamplerDecision *_Nullable _sentry_profileSampleDecision( + NSDictionary *launchConfigDict) +{ + NSNumber *profilesRand = launchConfigDict[kSentryLaunchProfileConfigKeyProfilesSampleRand]; + if (profilesRand == nil) { + SENTRY_LOG_DEBUG(@"Received a nil configured launch profile sample rand, will not " + @"start trace profiler for launch."); + return nil; + } + + NSNumber *profilesRate = launchConfigDict[kSentryLaunchProfileConfigKeyProfilesSampleRate]; + if (profilesRate == nil) { + SENTRY_LOG_DEBUG( + @"Tried to start a profile with no configured sample rate. Will not run profiler."); + return nil; + } + + return [[SentrySamplerDecision alloc] initWithDecision:kSentrySampleDecisionYes + forSampleRate:profilesRate + withSampleRand:profilesRand]; +} + +/** + * Create a @c SentryLaunchProfileConfiguration , fill in its properties based on the dictionary of + * persisted values loaded from disk, and set the in-memory data structure. + */ +void +_sentry_hydrateV2Options(NSDictionary *launchConfigDict, + SentryProfileOptions *profileOptions, SentrySamplerDecision *samplerDecision, + SentryProfileLifecycle lifecycle, BOOL shouldWaitForFullDisplay) +{ + profileOptions.lifecycle = lifecycle; + profileOptions.profileAppStarts = true; + profileOptions.sessionSampleRate = samplerDecision.sampleRate.floatValue; + + sentry_profileConfiguration = [[SentryProfileConfiguration alloc] + initContinuousProfilingV2WaitingForFullDisplay:shouldWaitForFullDisplay + samplerDecision:samplerDecision + profileOptions:profileOptions]; +} + +void +_sentry_continuousProfilingV1_startLaunchProfile(BOOL shouldWaitForFullDisplay) +{ + sentry_profileConfiguration = + [[SentryProfileConfiguration alloc] initWaitingForFullDisplay:shouldWaitForFullDisplay + continuousV1:YES]; + [SentryContinuousProfiler start]; +} + +/** + * Hydrate any relevant launch profiling options persisted from the previous launch and start a + * trace that will automatically start a manual lifecycle continuous profile (v2) + */ +void +_sentry_continuousProfilingV2_startManualLaunchProfile( + NSDictionary *launchConfigDict, SentryProfileOptions *profileOptions, + SentrySamplerDecision *decision, BOOL shouldWaitForFullDisplay) +{ + NSNumber *sampleRand = launchConfigDict[kSentryLaunchProfileConfigKeyProfilesSampleRand]; + + if (sampleRand == nil) { + SENTRY_LOG_ERROR(@"Tried to start a continuous profile v2 with no configured sample " + @"rate/rand. Will not run profiler."); + return; + } + + _sentry_hydrateV2Options(launchConfigDict, profileOptions, decision, + SentryProfileLifecycleManual, shouldWaitForFullDisplay); + + [SentryContinuousProfiler start]; +} -SentryTracerConfiguration * -sentry_configForLaunchProfilerForTrace( - NSNumber *profilesRate, NSNumber *profilesRand, SentryProfileOptions *_Nullable profileOptions) +SentryTransactionContext * +sentry_contextForLaunchProfilerForTrace(NSNumber *tracesRate, NSNumber *tracesRand) { - SentryTracerConfiguration *config = [SentryTracerConfiguration defaultConfiguration]; - config.profilesSamplerDecision = - [[SentrySamplerDecision alloc] initWithDecision:kSentrySampleDecisionYes - forSampleRate:profilesRate - withSampleRand:profilesRand]; - config.profileOptions = profileOptions; - return config; + SentryTransactionContext *context = + [[SentryTransactionContext alloc] initWithName:@"launch" + nameSource:kSentryTransactionNameSourceCustom + operation:SentrySpanOperationAppLifecycle + origin:SentryTraceOriginAutoAppStartProfile + sampled:kSentrySampleDecisionYes + sampleRate:tracesRate + sampleRand:tracesRand]; + return context; } -# pragma mark - Package +void +_sentry_startTraceProfiler( + NSDictionary *launchConfigDict, SentrySamplerDecision *decision) +{ + NSNumber *tracesRate = launchConfigDict[kSentryLaunchProfileConfigKeyTracesSampleRate]; + if (tracesRate == nil) { + SENTRY_LOG_DEBUG(@"Received a nil configured launch trace sample rate, will not start " + @"trace profiler for launch."); + return; + } -typedef struct { - BOOL shouldProfile; - /** Only needed for trace launch profiling or continuous profiling v2 with trace lifecycle; - * unused with continuous profiling. */ - SentrySamplerDecision *_Nullable tracesDecision; - SentrySamplerDecision *_Nullable profilesDecision; -} SentryLaunchProfileConfig; + NSNumber *tracesRand = launchConfigDict[kSentryLaunchProfileConfigKeyTracesSampleRand]; + if (tracesRand == nil) { + SENTRY_LOG_DEBUG(@"Received a nil configured launch trace sample rand, will not start " + @"trace profiler for launch."); + return; + } + + SENTRY_LOG_INFO(@"Starting app launch trace profile at %llu.", + [SentryDefaultCurrentDateProvider getAbsoluteTime]); + sentry_isTracingAppLaunch = YES; -SentryLaunchProfileConfig + SentryTracerConfiguration *tracerConfig = [SentryTracerConfiguration defaultConfiguration]; + tracerConfig.profilesSamplerDecision = decision; + + SentryTransactionContext *transactionContext + = sentry_contextForLaunchProfilerForTrace(tracesRate, tracesRand); + sentry_launchTracer = [[SentryTracer alloc] initWithTransactionContext:transactionContext + hub:nil + configuration:tracerConfig]; +} + +# if !SDK_V9 +SentryLaunchProfileDecision sentry_launchShouldHaveTransactionProfiling(SentryOptions *options) { -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" BOOL shouldProfileNextLaunch = options.enableAppLaunchProfiling && options.enableTracing; if (!shouldProfileNextLaunch) { SENTRY_LOG_DEBUG(@"Specified options configuration doesn't enable launch profiling: " @"options.enableAppLaunchProfiling: %d; options.enableTracing: %d; won't " @"profile launch", options.enableAppLaunchProfiling, options.enableTracing); - return (SentryLaunchProfileConfig) { NO, nil, nil }; + return (SentryLaunchProfileDecision) { NO, nil, nil }; } -# pragma clang diagnostic pop +# pragma clang diagnostic pop SentryTransactionContext *transactionContext = [[SentryTransactionContext alloc] initWithName:@"app.launch" operation:@"profile"]; @@ -87,7 +187,7 @@ if (tracesSamplerDecision.decision != kSentrySampleDecisionYes) { SENTRY_LOG_DEBUG( @"Sampling out the launch trace for transaction profiling; won't profile launch."); - return (SentryLaunchProfileConfig) { NO, nil, nil }; + return (SentryLaunchProfileDecision) { NO, nil, nil }; } SentrySamplerDecision *profilesSamplerDecision @@ -95,20 +195,21 @@ if (profilesSamplerDecision.decision != kSentrySampleDecisionYes) { SENTRY_LOG_DEBUG( @"Sampling out the launch profile for transaction profiling; won't profile launch."); - return (SentryLaunchProfileConfig) { NO, nil, nil }; + return (SentryLaunchProfileDecision) { NO, nil, nil }; } SENTRY_LOG_DEBUG(@"Will start transaction profile next launch; will profile launch."); - return (SentryLaunchProfileConfig) { YES, tracesSamplerDecision, profilesSamplerDecision }; + return (SentryLaunchProfileDecision) { YES, tracesSamplerDecision, profilesSamplerDecision }; } +# endif // !SDK_V9 -SentryLaunchProfileConfig +SentryLaunchProfileDecision sentry_launchShouldHaveContinuousProfilingV2(SentryOptions *options) { if (!options.profiling.profileAppStarts) { SENTRY_LOG_DEBUG(@"Continuous profiling v2 enabled but disabled app start profiling, " @"won't profile launch."); - return (SentryLaunchProfileConfig) { NO, nil, nil }; + return (SentryLaunchProfileDecision) { NO, nil, nil }; } if (options.profiling.lifecycle == SentryProfileLifecycleTrace) { if (!options.isTracingEnabled) { @@ -117,7 +218,7 @@ SENTRY_LOG_WARN( @"Tracing must be enabled in order to configure app start profiling with trace " @"lifecycle. See SentryOptions.tracesSampleRate and SentryOptions.tracesSampler."); - return (SentryLaunchProfileConfig) { NO, nil, nil }; + return (SentryLaunchProfileDecision) { NO, nil, nil }; } SentryTransactionContext *transactionContext = @@ -129,7 +230,7 @@ if (tracesSamplerDecision.decision != kSentrySampleDecisionYes) { SENTRY_LOG_DEBUG(@"Sampling out the launch trace for continuous profile v2 trace " @"lifecycle, won't profile launch."); - return (SentryLaunchProfileConfig) { NO, nil, nil }; + return (SentryLaunchProfileDecision) { NO, nil, nil }; } SentrySamplerDecision *profileSamplerDecision @@ -137,52 +238,45 @@ if (profileSamplerDecision.decision != kSentrySampleDecisionYes) { SENTRY_LOG_DEBUG( @"Sampling out continuous v2 trace lifecycle profile, won't profile launch."); - return (SentryLaunchProfileConfig) { NO, nil, nil }; + return (SentryLaunchProfileDecision) { NO, nil, nil }; } SENTRY_LOG_DEBUG( @"Continuous profiling v2 trace lifecycle conditions satisfied, will profile launch."); - return (SentryLaunchProfileConfig) { YES, tracesSamplerDecision, profileSamplerDecision }; + return (SentryLaunchProfileDecision) { YES, tracesSamplerDecision, profileSamplerDecision }; } SentrySamplerDecision *profileSampleDecision = sentry_sampleProfileSession(options.profiling.sessionSampleRate); if (profileSampleDecision.decision != kSentrySampleDecisionYes) { SENTRY_LOG_DEBUG(@"Sampling out continuous v2 profile, won't profile launch."); - return (SentryLaunchProfileConfig) { NO, nil, nil }; + return (SentryLaunchProfileDecision) { NO, nil, nil }; } SENTRY_LOG_DEBUG( @"Continuous profiling v2 manual lifecycle conditions satisfied, will profile launch."); - return (SentryLaunchProfileConfig) { YES, nil, profileSampleDecision }; + return (SentryLaunchProfileDecision) { YES, nil, profileSampleDecision }; } -SentryLaunchProfileConfig +SentryLaunchProfileDecision sentry_shouldProfileNextLaunch(SentryOptions *options) { if ([options isContinuousProfilingV2Enabled]) { return sentry_launchShouldHaveContinuousProfilingV2(options); } +# if SDK_V9 + return (SentryLaunchProfileDecision) { NO, nil, nil }; +# else +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" if ([options isContinuousProfilingEnabled]) { - return (SentryLaunchProfileConfig) { options.enableAppLaunchProfiling, nil, nil }; + return (SentryLaunchProfileDecision) { options.enableAppLaunchProfiling, nil, nil }; } +# pragma clang diagnostic pop return sentry_launchShouldHaveTransactionProfiling(options); -} - -SentryTransactionContext * -sentry_contextForLaunchProfilerForTrace(NSNumber *tracesRate, NSNumber *tracesRand) -{ - SentryTransactionContext *context = - [[SentryTransactionContext alloc] initWithName:@"launch" - nameSource:kSentryTransactionNameSourceCustom - operation:SentrySpanOperationAppLifecycle - origin:SentryTraceOriginAutoAppStartProfile - sampled:kSentrySampleDecisionYes - sampleRate:tracesRate - sampleRand:tracesRand]; - return context; +# endif // SDK_V9 } /** @@ -198,7 +292,7 @@ removeAppLaunchProfilingConfigFile(); } -# pragma mark - Testing only +# pragma mark - Exposed for testing # if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) BOOL @@ -208,8 +302,6 @@ } # endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) -# pragma mark - Exposed only to tests - void _sentry_nondeduplicated_startLaunchProfile(void) { @@ -225,26 +317,57 @@ [SentrySDKLogSupport configure:YES diagnosticLevel:kSentryLevelDebug]; # endif // defined(DEBUG) - NSDictionary *launchConfig = sentry_appLaunchProfileConfiguration(); + NSDictionary *persistedLaunchConfigOptionsDict + = sentry_persistedLaunchProfileConfigurationOptions(); + + BOOL isContinuousV2 = + [persistedLaunchConfigOptionsDict[kSentryLaunchProfileConfigKeyContinuousProfilingV2] + boolValue]; +# if !SDK_V9 + BOOL isContinuousV1 = + [persistedLaunchConfigOptionsDict[kSentryLaunchProfileConfigKeyContinuousProfiling] + boolValue]; + if (isContinuousV1 && isContinuousV2) { + SENTRY_LOG_WARN(@"Launch profile misconfiguration detected."); + _sentry_cleanUpConfigFile(); + return; + } +# else + BOOL isContinuousV1 = false; +# endif // !SDK_V9 + + SentrySamplerDecision *decision + = _sentry_profileSampleDecision(persistedLaunchConfigOptionsDict); + if (!isContinuousV1 && nil == decision) { + SENTRY_LOG_DEBUG(@"Couldn't hydrate the persisted sample decision."); + _sentry_cleanUpConfigFile(); + return; + } - if (launchConfig == nil) { - SENTRY_LOG_DEBUG(@"No launch profile config exists, will not profile launch."); + NSNumber *shouldWaitForFullDisplayValue + = persistedLaunchConfigOptionsDict[kSentryLaunchProfileConfigKeyWaitForFullDisplay]; + if (shouldWaitForFullDisplayValue == nil) { + SENTRY_LOG_DEBUG(@"Received a nil configured launch profile value indicating whether " + @"or not the profile should be finished on full display or SDK start, " + @"cannot know when to stop the profile, will not start this launch."); _sentry_cleanUpConfigFile(); return; } - if ([launchConfig[kSentryLaunchProfileConfigKeyContinuousProfiling] boolValue]) { + BOOL shouldWaitForFullDisplay = shouldWaitForFullDisplayValue.boolValue; + + if (isContinuousV1) { SENTRY_LOG_DEBUG(@"Starting continuous launch profile v1."); - [SentryContinuousProfiler start]; + _sentry_continuousProfilingV1_startLaunchProfile(shouldWaitForFullDisplay); _sentry_cleanUpConfigFile(); return; } SentryProfileOptions *profileOptions = nil; - if ([launchConfig[kSentryLaunchProfileConfigKeyContinuousProfilingV2] boolValue]) { + if (isContinuousV2) { SENTRY_LOG_DEBUG(@"Starting continuous launch profile v2."); - NSNumber *lifecycleValue - = launchConfig[kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle]; + NSNumber *lifecycleValue = persistedLaunchConfigOptionsDict + [kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle]; if (lifecycleValue == nil) { SENTRY_LOG_ERROR( @"Missing expected launch profile config parameter for lifecycle. Will " @@ -253,85 +376,27 @@ return; } + profileOptions = [[SentryProfileOptions alloc] init]; + SentryProfileLifecycle lifecycle = lifecycleValue.intValue; if (lifecycle == SentryProfileLifecycleManual) { - NSNumber *sampleRate = launchConfig[kSentryLaunchProfileConfigKeyProfilesSampleRate]; - NSNumber *sampleRand = launchConfig[kSentryLaunchProfileConfigKeyProfilesSampleRand]; - - if (sampleRate == nil || sampleRand == nil) { - SENTRY_LOG_ERROR( - @"Tried to start a continuous profile v2 with no configured sample " - @"rate/rand. Will not run profiler."); - _sentry_cleanUpConfigFile(); - return; - } - - SentrySamplerDecision *decision = - [[SentrySamplerDecision alloc] initWithDecision:kSentrySampleDecisionYes - forSampleRate:sampleRate - withSampleRand:sampleRand]; - sentry_profilerSessionSampleDecision = decision; - - [SentryContinuousProfiler start]; + _sentry_continuousProfilingV2_startManualLaunchProfile(persistedLaunchConfigOptionsDict, + profileOptions, decision, shouldWaitForFullDisplay); _sentry_cleanUpConfigFile(); return; } - profileOptions = [[SentryProfileOptions alloc] init]; - profileOptions.lifecycle = lifecycle; - profileOptions.profileAppStarts = true; + _sentry_hydrateV2Options(persistedLaunchConfigOptionsDict, profileOptions, decision, + SentryProfileLifecycleTrace, shouldWaitForFullDisplay); + } else { + sentry_profileConfiguration = + [[SentryProfileConfiguration alloc] initWaitingForFullDisplay:shouldWaitForFullDisplay + continuousV1:NO]; } - NSNumber *profilesRate = launchConfig[kSentryLaunchProfileConfigKeyProfilesSampleRate]; - if (profilesRate == nil) { - SENTRY_LOG_DEBUG(@"Received a nil configured launch profile sample rate, will not " - @"start trace profiler for launch."); - _sentry_cleanUpConfigFile(); - return; - } - profileOptions.sessionSampleRate = profilesRate.floatValue; - - NSNumber *profilesRand = launchConfig[kSentryLaunchProfileConfigKeyProfilesSampleRand]; - if (profilesRand == nil) { - SENTRY_LOG_DEBUG(@"Received a nil configured launch profile sample rand, will not " - @"start trace profiler for launch."); - _sentry_cleanUpConfigFile(); - return; - } - - NSNumber *tracesRate = launchConfig[kSentryLaunchProfileConfigKeyTracesSampleRate]; - if (tracesRate == nil) { - SENTRY_LOG_DEBUG(@"Received a nil configured launch trace sample rate, will not start " - @"trace profiler for launch."); - _sentry_cleanUpConfigFile(); - return; - } - - NSNumber *tracesRand = launchConfig[kSentryLaunchProfileConfigKeyTracesSampleRand]; - if (tracesRand == nil) { - SENTRY_LOG_DEBUG(@"Received a nil configured launch trace sample rand, will not start " - @"trace profiler for launch."); - _sentry_cleanUpConfigFile(); - return; - } - - SENTRY_LOG_INFO(@"Starting app launch trace profile at %llu.", - [SentryDefaultCurrentDateProvider getAbsoluteTime]); - sentry_isTracingAppLaunch = YES; - - SentryTransactionContext *context - = sentry_contextForLaunchProfilerForTrace(tracesRate, tracesRand); - SentryTracerConfiguration *config - = sentry_configForLaunchProfilerForTrace(profilesRate, profilesRand, profileOptions); - SentrySamplerDecision *decision = - [[SentrySamplerDecision alloc] initWithDecision:kSentrySampleDecisionYes - forSampleRate:profilesRate - withSampleRand:profilesRand]; - sentry_profilerSessionSampleDecision = decision; - sentry_launchTracer = [[SentryTracer alloc] initWithTransactionContext:context - hub:nil - configuration:config]; - + // trace lifecycle UI profiling (continuous profiling v2) and trace-based profiling both join + // paths here + _sentry_startTraceProfiler(persistedLaunchConfigOptionsDict, decision); _sentry_cleanUpConfigFile(); } @@ -340,10 +405,10 @@ BOOL sentry_isTracingAppLaunch; void -sentry_configureLaunchProfiling(SentryOptions *options) +sentry_configureLaunchProfilingForNextLaunch(SentryOptions *options) { [SentryDependencyContainer.sharedInstance.dispatchQueueWrapper dispatchAsyncWithBlock:^{ - SentryLaunchProfileConfig config = sentry_shouldProfileNextLaunch(options); + SentryLaunchProfileDecision config = sentry_shouldProfileNextLaunch(options); if (!config.shouldProfile) { SENTRY_LOG_DEBUG(@"Removing launch profile config file."); removeAppLaunchProfilingConfigFile(); @@ -352,7 +417,11 @@ NSMutableDictionary *configDict = [NSMutableDictionary dictionary]; + configDict[kSentryLaunchProfileConfigKeyWaitForFullDisplay] = + @(options.enableTimeToFullDisplayTracing); +# if !SDK_V9 if ([options isContinuousProfilingEnabled]) { +# endif // !SDK_V9 if ([options isContinuousProfilingV2Enabled]) { SENTRY_LOG_DEBUG(@"Configuring continuous launch profile v2."); configDict[kSentryLaunchProfileConfigKeyContinuousProfilingV2] = @YES; @@ -369,9 +438,12 @@ configDict[kSentryLaunchProfileConfigKeyProfilesSampleRand] = config.profilesDecision.sampleRand; } else { +# if !SDK_V9 SENTRY_LOG_DEBUG(@"Configuring continuous launch profile."); configDict[kSentryLaunchProfileConfigKeyContinuousProfiling] = @YES; +# endif // !SDK_V9 } +# if !SDK_V9 } else { SENTRY_LOG_DEBUG(@"Configuring trace launch profile."); configDict[kSentryLaunchProfileConfigKeyTracesSampleRate] @@ -383,6 +455,7 @@ configDict[kSentryLaunchProfileConfigKeyProfilesSampleRand] = config.profilesDecision.sampleRand; } +# endif // !SDK_V9 writeAppLaunchProfilingConfigFile(configDict); }]; } @@ -398,22 +471,12 @@ } void -sentry_stopAndTransmitLaunchProfile(SentryHub *hub) -{ - if (sentry_launchTracer == nil) { - SENTRY_LOG_DEBUG(@"No launch tracer present to stop."); - return; - } - - sentry_launchTracer.hub = hub; - sentry_stopAndDiscardLaunchProfileTracer(); -} - -void -sentry_stopAndDiscardLaunchProfileTracer(void) +sentry_stopAndDiscardLaunchProfileTracer(SentryHub *_Nullable hub) { SENTRY_LOG_DEBUG(@"Finishing launch tracer."); + sentry_launchTracer.hub = hub; [sentry_launchTracer finish]; + sentry_profileConfiguration = nil; sentry_isTracingAppLaunch = NO; sentry_launchTracer = nil; } diff --git a/Sources/Sentry/Profiling/SentryProfileConfiguration.m b/Sources/Sentry/Profiling/SentryProfileConfiguration.m new file mode 100644 index 00000000000..096fb26d31b --- /dev/null +++ b/Sources/Sentry/Profiling/SentryProfileConfiguration.m @@ -0,0 +1,60 @@ +#import "SentryProfileConfiguration.h" + +#if SENTRY_TARGET_PROFILING_SUPPORTED + +# import "SentrySampling.h" +# import "SentrySwift.h" + +@interface SentryProfileConfiguration () +@property (strong, nonatomic, nullable, readwrite) + SentrySamplerDecision *profilerSessionSampleDecision; +@end + +@implementation SentryProfileConfiguration + +- (instancetype)initWithProfileOptions:(SentryProfileOptions *)options +{ + if (!(self = [super init])) { + return nil; + } + + _profileOptions = options; + return self; +} + +- (instancetype)initWaitingForFullDisplay:(BOOL)shouldWaitForFullDisplay + continuousV1:(BOOL)continuousV1 +{ + if (!(self = [super init])) { + return nil; + } + + _waitForFullDisplay = shouldWaitForFullDisplay; + _isContinuousV1 = continuousV1; + _isProfilingThisLaunch = YES; + return self; +} + +- (instancetype)initContinuousProfilingV2WaitingForFullDisplay:(BOOL)shouldWaitForFullDisplay + samplerDecision:(SentrySamplerDecision *)decision + profileOptions:(SentryProfileOptions *)options +{ + if (!(self = [self initWaitingForFullDisplay:shouldWaitForFullDisplay continuousV1:NO])) { + return nil; + } + + _profileOptions = options; + _profilerSessionSampleDecision = decision; + _isProfilingThisLaunch = YES; + return self; +} + +- (void)reevaluateSessionSampleRate +{ + self.profilerSessionSampleDecision + = sentry_sampleProfileSession(self.profileOptions.sessionSampleRate); +} + +@end + +#endif // SENTRY_TARGET_PROFILING_SUPPORTED diff --git a/Sources/Sentry/Profiling/SentryProfiledTracerConcurrency.mm b/Sources/Sentry/Profiling/SentryProfiledTracerConcurrency.mm index 4d924448e48..76a5c07cbe5 100644 --- a/Sources/Sentry/Profiling/SentryProfiledTracerConcurrency.mm +++ b/Sources/Sentry/Profiling/SentryProfiledTracerConcurrency.mm @@ -15,12 +15,13 @@ # import "SentryInternalDefines.h" # import "SentryLaunchProfiling.h" # import "SentryOptions+Private.h" +# import "SentryProfileConfiguration.h" # import "SentryProfiledTracerConcurrency.h" # import "SentryProfiler+Private.h" # import "SentryProfilerSerialization.h" # import "SentryProfilerState.h" +# import "SentryProfilingSwiftHelpers.h" # import "SentrySamplerDecision.h" -# import "SentrySwift.h" # import "SentryTraceProfiler.h" # import "SentryTracer+Private.h" # import "SentryTransaction.h" @@ -58,15 +59,17 @@ void _unsafe_cleanUpTraceProfiler(SentryProfiler *profiler, NSString *tracerKey) { - const auto profilerKey = profiler.profilerId.sentryIdString; + const auto profilerKey = sentry_stringFromSentryID(profiler.profilerId); [_gTracersToProfilers removeObjectForKey:tracerKey]; _gProfilersToTracers[profilerKey] = @(_gProfilersToTracers[profilerKey].unsignedIntValue - 1); - if ([_gProfilersToTracers[profilerKey] unsignedIntValue] == 0) { - [_gProfilersToTracers removeObjectForKey:profilerKey]; - if ([profiler isRunning]) { - [profiler stopForReason:SentryProfilerTruncationReasonNormal]; - } + const auto remainingTracers = [_gProfilersToTracers[profilerKey] unsignedIntValue]; + if (remainingTracers > 0) { + SENTRY_LOG_DEBUG(@"Waiting on %lu tracers to finish.", remainingTracers); + return; } + + [_gProfilersToTracers removeObjectForKey:profilerKey]; + [profiler stopForReason:SentryProfilerTruncationReasonNormal]; } /** @@ -77,11 +80,6 @@ _unsafe_cleanUpContinuousProfilerV2() { if (_gInFlightRootSpans == 0) { - // This log message has been changed from an assertion failing in debug builds and tests to - // be less disruptive. This needs to be investigated because spans should not be finished - // multiple times. - // - // See https://github.com/getsentry/sentry-cocoa/pull/5363 for the full context. SENTRY_LOG_ERROR(@"Attemtpted to stop continuous profiler with no root spans in flight."); } else { _gInFlightRootSpans -= 1; @@ -101,7 +99,7 @@ std::lock_guard l(_gStateLock); if (![SentryContinuousProfiler isCurrentlyProfiling] && _gInFlightRootSpans != 0) { - SENTRY_TEST_FATAL(@"Unbalanced tracking of root spans and profiler detected."); + SENTRY_LOG_ERROR(@"Unbalanced tracking of root spans and profiler detected."); return; } @@ -119,21 +117,22 @@ SentryId *_Nullable _sentry_startContinuousProfilerV2ForTrace( SentryProfileOptions *profileOptions, SentryTransactionContext *transactionContext) { - if (profileOptions.lifecycle != SentryProfileLifecycleTrace) { + if (!sentry_isTraceLifecycle(profileOptions)) { return nil; } - if (transactionContext.sampled != kSentrySampleDecisionYes) { + if (sentry_isNotSampled(transactionContext)) { return nil; } - if (sentry_profilerSessionSampleDecision.decision != kSentrySampleDecisionYes) { + if (sentry_profileConfiguration.profilerSessionSampleDecision.decision + != kSentrySampleDecisionYes) { return nil; } - SentryId *profilerReferenceId = [[SentryId alloc] init]; + SentryId *profilerReferenceId = sentry_getSentryId(); SENTRY_LOG_DEBUG( @"Starting continuous profiler for root span tracer with profilerReferenceId %@", - profilerReferenceId.sentryIdString); + sentry_stringFromSentryID(profilerReferenceId)); sentry_trackRootSpanForContinuousProfilerV2(); return profilerReferenceId; } @@ -145,8 +144,8 @@ { std::lock_guard l(_gStateLock); - const auto profilerKey = profiler.profilerId.sentryIdString; - const auto tracerKey = internalTraceId.sentryIdString; + const auto profilerKey = sentry_stringFromSentryID(profiler.profilerId); + const auto tracerKey = sentry_stringFromSentryID(internalTraceId); SENTRY_LOG_DEBUG( @"Tracking relationship between profiler id %@ and tracer id %@", profilerKey, tracerKey); @@ -175,20 +174,27 @@ if ([SentryContinuousProfiler isCurrentlyProfiling]) { SENTRY_LOG_DEBUG(@"Stopping tracking discarded tracer with profileReferenceId %@", - internalTraceId.sentryIdString); + sentry_stringFromSentryID(internalTraceId)); _unsafe_cleanUpContinuousProfilerV2(); } else if (internalTraceId != nil) { - if ([hub.getClient.options isContinuousProfilingEnabled]) { - SENTRY_TEST_FATAL(@"Tracers are not tracked with continuous profiling V1."); +# if !SDK_V9 + SentryClient *_Nullable client = hub.getClient; + if (client == nil) { + SENTRY_LOG_ERROR(@"No client found, skipping cleanup."); + return; + } + if (sentry_isContinuousProfilingEnabled(SENTRY_UNWRAP_NULLABLE(SentryClient, client))) { + SENTRY_LOG_ERROR(@"Tracers are not tracked with continuous profiling V1."); return; } +# endif // !SDK_V9 if (_gTracersToProfilers == nil) { - SENTRY_TEST_FATAL(@"Tracer to profiler should have already been initialized by the " - @"time they are being queried"); + SENTRY_LOG_ERROR(@"Tracer to profiler should have already been initialized by the " + @"time they are being queried"); } - const auto tracerKey = internalTraceId.sentryIdString; + const auto tracerKey = sentry_stringFromSentryID(internalTraceId); const auto profiler = _gTracersToProfilers[tracerKey]; if (profiler == nil) { @@ -199,8 +205,8 @@ # if SENTRY_HAS_UIKIT if (_gProfilersToTracers == nil) { - SENTRY_TEST_FATAL(@"Profiler to tracer structure should have already been " - @"initialized by the time they are being queried"); + SENTRY_LOG_ERROR(@"Profiler to tracer structure should have already been " + @"initialized by the time they are being queried"); } if (_gProfilersToTracers.count == 0) { [SentryDependencyContainer.sharedInstance.framesTracker resetProfilingTimestamps]; @@ -213,14 +219,17 @@ { std::lock_guard l(_gStateLock); - SENTRY_CASSERT(_gTracersToProfilers != nil && _gProfilersToTracers != nil, - @"Structures should have already been initialized by the time they are being queried"); + if (_gTracersToProfilers == nil || _gProfilersToTracers == nil) { + SENTRY_LOG_ERROR( + @"Structures should have already been initialized by the time they are being queried"); + return nil; + } - const auto tracerKey = internalTraceId.sentryIdString; + const auto tracerKey = sentry_stringFromSentryID(internalTraceId); const auto profiler = _gTracersToProfilers[tracerKey]; - if (!SENTRY_CASSERT_RETURN(profiler != nil, - @"Expected a profiler to be associated with tracer id %@.", tracerKey)) { + if (profiler == nil) { + SENTRY_LOG_ERROR(@"Expected a profiler to be associated with tracer id %@.", tracerKey); return nil; } @@ -250,10 +259,21 @@ # endif // SENTRY_HAS_UIKIT ) { - if (isProfiling && [hub.getClient.options isContinuousProfilingV2Enabled] && - [hub.getClient.options isProfilingCorrelatedToTraces]) { + if (sentry_profileConfiguration != nil && sentry_profileConfiguration.isProfilingThisLaunch + && sentry_profileConfiguration.profileOptions != nil + && sentry_isTraceLifecycle(SENTRY_UNWRAP_NULLABLE( + SentryProfileOptions, sentry_profileConfiguration.profileOptions))) { + SENTRY_LOG_DEBUG(@"Stopping launch UI trace profile."); + sentry_stopTrackingRootSpanForContinuousProfilerV2(); + return; + } + + SentryClient *_Nullable client = hub.getClient; + if (isProfiling && client != nil + && sentry_isContinuousProfilingV2Enabled(SENTRY_UNWRAP_NULLABLE(SentryClient, client)) + && sentry_isProfilingCorrelatedToTraces(SENTRY_UNWRAP_NULLABLE(SentryClient, client))) { SENTRY_LOG_DEBUG(@"Stopping tracking root span tracer with profilerReferenceId %@", - transaction.trace.profilerReferenceID.sentryIdString); + sentry_stringFromSentryID(transaction.trace.profilerReferenceID)); sentry_stopTrackingRootSpanForContinuousProfilerV2(); [hub captureTransaction:transaction withScope:hub.scope]; return; @@ -278,7 +298,7 @@ if (!SENTRY_CASSERT_RETURN(startTimestamp != nil, @"A transaction with a profile should have a start timestamp already. We will " @"assign the current time but this will be incorrect.")) { - startTimestamp = [SentryDependencyContainer.sharedInstance.dateProvider date]; + startTimestamp = sentry_getDate(); } // if we have an app start span, use its app start timestamp. otherwise use the tracer's @@ -295,18 +315,20 @@ # endif // SENTRY_HAS_UIKIT [SentryTraceProfiler recordMetrics]; - transaction.endSystemTime = SentryDependencyContainer.sharedInstance.dateProvider.systemTime; + transaction.endSystemTime = sentry_getSystemTime(); - const auto profiler = sentry_profilerForFinishedTracer(transaction.trace.profilerReferenceID); - if (!profiler) { + SentryProfiler *_Nullable nullableProfiler + = sentry_profilerForFinishedTracer(transaction.trace.profilerReferenceID); + if (!nullableProfiler) { [hub captureTransaction:transaction withScope:hub.scope]; return; } + SentryProfiler *_Nonnull profiler = SENTRY_UNWRAP_NULLABLE(SentryProfiler, nullableProfiler); // This code can run on the main thread, and the profile serialization can take a couple of // milliseconds. Therefore, we move this to a background thread to avoid potentially // blocking the main thread. - [dispatchQueue dispatchAsyncWithBlock:^{ + sentry_dispatchAsync(dispatchQueue, ^{ const auto profilingData = [profiler.state copyProfilingData]; const auto profileEnvelopeItem = sentry_traceProfileEnvelopeItem( @@ -317,43 +339,52 @@ } else { [hub captureTransaction:transaction withScope:hub.scope - additionalEnvelopeItems:@[ profileEnvelopeItem ]]; + additionalEnvelopeItems:@[ SENTRY_UNWRAP_NULLABLE( + SentryEnvelopeItem, profileEnvelopeItem) ]]; } - }]; + }); } SentryId *_Nullable sentry_startProfilerForTrace(SentryTracerConfiguration *configuration, SentryHub *hub, SentryTransactionContext *transactionContext) { - if (configuration.profileOptions != nil) { + if (sentry_profileConfiguration.profileOptions != nil) { // launch profile; there's no hub to get options from, so they're read from the launch - // profile config file and packaged into the tracer configuration in the launch profile - // codepath + // profile config file return _sentry_startContinuousProfilerV2ForTrace( - configuration.profileOptions, transactionContext); - } else if ([hub.getClient.options isContinuousProfilingV2Enabled]) { + sentry_profileConfiguration.profileOptions, transactionContext); + } + SentryClient *_Nullable client = hub.getClient; + if (client != nil + && sentry_isContinuousProfilingV2Enabled(SENTRY_UNWRAP_NULLABLE(SentryClient, client))) { // non launch profile - if (transactionContext.parentSpanId != nil) { + if (sentry_getParentSpanID(transactionContext) != nil) { SENTRY_LOG_DEBUG(@"Not a root span, will not start automatically for trace lifecycle."); return nil; } return _sentry_startContinuousProfilerV2ForTrace( - hub.getClient.options.profiling, transactionContext); - } else { - BOOL profileShouldBeSampled - = configuration.profilesSamplerDecision.decision == kSentrySampleDecisionYes; - BOOL isContinuousProfiling = [hub.client.options isContinuousProfilingEnabled]; - BOOL shouldStartNormalTraceProfile = !isContinuousProfiling && profileShouldBeSampled; - if (sentry_isTracingAppLaunch || shouldStartNormalTraceProfile) { - SentryId *internalID = [[SentryId alloc] init]; - if ([SentryTraceProfiler startWithTracer:internalID]) { - SENTRY_LOG_DEBUG(@"Started profiler for trace %@ with internal id %@", - transactionContext.traceId.sentryIdString, internalID.sentryIdString); - return internalID; - } + sentry_getProfiling(SENTRY_UNWRAP_NULLABLE(SentryClient, client)), transactionContext); + } + BOOL profileShouldBeSampled + = configuration.profilesSamplerDecision.decision == kSentrySampleDecisionYes; +# if !SDK_V9 + BOOL isContinuousProfiling = client != nil + && sentry_isContinuousProfilingEnabled(SENTRY_UNWRAP_NULLABLE(SentryClient, client)); + BOOL shouldStartNormalTraceProfile = !isContinuousProfiling && profileShouldBeSampled; +# else + BOOL shouldStartNormalTraceProfile = profileShouldBeSampled; +# endif // !SDK_V9 + + if (sentry_isTracingAppLaunch || shouldStartNormalTraceProfile) { + SentryId *internalID = sentry_getSentryId(); + if ([SentryTraceProfiler startWithTracer:internalID]) { + SENTRY_LOG_DEBUG(@"Started profiler for trace %@ with internal id %@", + sentry_stringFromSentryID(sentry_getTraceID(transactionContext)), + sentry_stringFromSentryID(internalID)); + return internalID; } - return nil; } + return nil; } # if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) @@ -363,6 +394,7 @@ std::lock_guard l(_gStateLock); [_gTracersToProfilers removeAllObjects]; [_gProfilersToTracers removeAllObjects]; + _gInFlightRootSpans = 0; } NSUInteger diff --git a/Sources/Sentry/Profiling/SentryProfilerSerialization.m b/Sources/Sentry/Profiling/SentryProfilerSerialization.m index 79dfb30ba84..64d9e5cddfd 100644 --- a/Sources/Sentry/Profiling/SentryProfilerSerialization.m +++ b/Sources/Sentry/Profiling/SentryProfilerSerialization.m @@ -7,15 +7,14 @@ # import "SentryDebugImageProvider+HybridSDKs.h" # import "SentryDependencyContainer.h" # import "SentryDevice.h" -# import "SentryEnvelope.h" # import "SentryEnvelopeItemHeader.h" -# import "SentryEnvelopeItemType.h" # import "SentryEvent+Private.h" # import "SentryFormatter.h" # import "SentryInternalDefines.h" # import "SentryLogC.h" # import "SentryMeta.h" # import "SentryMetricProfiler.h" +# import "SentryModels+Serializable.h" # import "SentryProfileTimeseries.h" # import "SentryProfiledTracerConcurrency.h" # import "SentryProfiler+Private.h" @@ -26,6 +25,7 @@ # import "SentrySDK+Private.h" # import "SentrySample.h" # import "SentryScope+Private.h" +# import "SentryScope+PrivateSwift.h" # import "SentrySerialization.h" # import "SentrySwift.h" # import "SentryTime.h" @@ -156,14 +156,14 @@ payload[@"debug_meta"] = @ { @"images" : debugImages }; } - payload[@"os"] = @ { + payload[SENTRY_CONTEXT_OS_KEY] = @ { @"name" : sentry_getOSName(), @"version" : sentry_getOSVersion(), @"build_number" : sentry_getOSBuildNumber() }; bool isEmulated = sentry_isSimulatorBuild(); - payload[@"device"] = @{ + payload[SENTRY_CONTEXT_DEVICE_KEY] = @{ @"architecture" : sentry_getCPUArchitecture(), @"is_emulator" : @(isEmulated), @"locale" : NSLocale.currentLocale.localeIdentifier, @@ -314,7 +314,7 @@ NSMutableDictionary *payload = sentry_serializedContinuousProfileChunk( profileID, chunkID, profileState, metricProfilerState, [SentryDependencyContainer.sharedInstance.debugImageProvider getDebugImagesFromCache], - SentrySDK.currentHub + SentrySDKInternal.currentHub # if SENTRY_HAS_UIKIT , gpuData @@ -344,13 +344,16 @@ # endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) SentryEnvelopeItemHeader *header = - [[SentryEnvelopeItemHeader alloc] initWithType:SentryEnvelopeItemTypeProfileChunk + [[SentryEnvelopeItemHeader alloc] initWithType:SentryEnvelopeItemTypes.profileChunk length:JSONData.length]; header.platform = @"cocoa"; SentryEnvelopeItem *envelopeItem = [[SentryEnvelopeItem alloc] initWithHeader:header data:JSONData]; +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" return [[SentryEnvelope alloc] initWithId:chunkID singleItem:envelopeItem]; +# pragma clang diagnostic pop } SentryEnvelopeItem *_Nullable sentry_traceProfileEnvelopeItem(SentryHub *hub, @@ -396,7 +399,7 @@ # endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) SentryEnvelopeItemHeader *header = - [[SentryEnvelopeItemHeader alloc] initWithType:SentryEnvelopeItemTypeProfile + [[SentryEnvelopeItemHeader alloc] initWithType:SentryEnvelopeItemTypes.profile length:JSONData.length]; return [[SentryEnvelopeItem alloc] initWithHeader:header data:JSONData]; } diff --git a/Sources/Sentry/Profiling/SentryProfilerState.mm b/Sources/Sentry/Profiling/SentryProfilerState.mm index cc0067198e5..7b39e10bdfe 100644 --- a/Sources/Sentry/Profiling/SentryProfilerState.mm +++ b/Sources/Sentry/Profiling/SentryProfilerState.mm @@ -5,8 +5,8 @@ # import "SentryDependencyContainer.h" # import "SentryFormatter.h" # import "SentryProfileTimeseries.h" +# import "SentryProfilingSwiftHelpers.h" # import "SentrySample.h" -# import "SentrySwift.h" # import # import # import @@ -66,8 +66,8 @@ - (instancetype)init if (self = [super init]) { _mutableState = [[SentryProfilerMutableState alloc] init]; _mainThreadID = 0; - [SentryDependencyContainer.sharedInstance.dispatchQueueWrapper - dispatchAsyncOnMainQueue:^{ [self cacheMainThreadID]; }]; + sentry_dispatchAsyncOnMain(SentryDependencyContainer.sharedInstance.dispatchQueueWrapper, + ^{ [self cacheMainThreadID]; }); } return self; } @@ -153,8 +153,7 @@ - (void)appendBacktrace:(const Backtrace &)backtrace const auto sample = [[SentrySample alloc] init]; sample.absoluteTimestamp = backtrace.absoluteTimestamp; - sample.absoluteNSDateInterval - = SentryDependencyContainer.sharedInstance.dateProvider.date.timeIntervalSince1970; + sample.absoluteNSDateInterval = sentry_getDate().timeIntervalSince1970; sample.threadID = backtrace.threadMetadata.threadID; const auto stackKey = [stack componentsJoinedByString:@"|"]; diff --git a/Sources/Sentry/Profiling/SentryProfilingSwiftHelpers.m b/Sources/Sentry/Profiling/SentryProfilingSwiftHelpers.m new file mode 100644 index 00000000000..ecc27ef4e6b --- /dev/null +++ b/Sources/Sentry/Profiling/SentryProfilingSwiftHelpers.m @@ -0,0 +1,170 @@ +#import "SentryProfilingSwiftHelpers.h" +#if SENTRY_TARGET_PROFILING_SUPPORTED + +# import "SentryDependencyContainer.h" +# import "SentryLogC.h" +# import "SentryOptions+Private.h" +# import "SentryProfiler+Private.h" +# import "SentrySamplerDecision.h" +# import "SentrySwift.h" + +# if !SDK_V9 +BOOL +sentry_isContinuousProfilingEnabled(SentryClient *client) +{ + return [client.options isContinuousProfilingEnabled]; +} +# endif // !SDK_V9 + +BOOL +sentry_isContinuousProfilingV2Enabled(SentryClient *client) +{ + return [client.options isContinuousProfilingV2Enabled]; +} + +BOOL +sentry_isProfilingCorrelatedToTraces(SentryClient *client) +{ + return [client.options isProfilingCorrelatedToTraces]; +} + +SentryProfileOptions * +sentry_getProfiling(SentryClient *client) +{ + return client.options.profiling; +} + +NSString * +sentry_stringFromSentryID(SentryId *sentryID) +{ + return sentryID.sentryIdString; +} + +NSDate * +sentry_getDate(void) +{ + return [SentryDependencyContainer.sharedInstance.dateProvider date]; +} + +uint64_t +sentry_getSystemTime(void) +{ + return SentryDependencyContainer.sharedInstance.dateProvider.systemTime; +} + +SentryId * +sentry_getSentryId(void) +{ + return [[SentryId alloc] init]; +} + +SentryProfileOptions * +sentry_getSentryProfileOptions(void) +{ + return [[SentryProfileOptions alloc] init]; +} + +BOOL +sentry_isTraceLifecycle(SentryProfileOptions *options) +{ + return options.lifecycle == SentryProfileLifecycleTrace; +} + +float +sentry_sessionSampleRate(SentryProfileOptions *options) +{ + return options.sessionSampleRate; +} + +BOOL +sentry_profileAppStarts(SentryProfileOptions *options) +{ + return options.profileAppStarts; +} + +SentrySpanId * +sentry_getParentSpanID(SentryTransactionContext *context) +{ + return context.parentSpanId; +} + +SentryId * +sentry_getTraceID(SentryTransactionContext *context) +{ + return context.traceId; +} + +BOOL +sentry_isNotSampled(SentryTransactionContext *context) +{ + return context.sampled != kSentrySampleDecisionYes; +} + +void +sentry_dispatchAsync(SentryDispatchQueueWrapper *wrapper, dispatch_block_t block) +{ + [wrapper dispatchAsyncWithBlock:block]; +} + +void +sentry_dispatchAsyncOnMain(SentryDispatchQueueWrapper *wrapper, dispatch_block_t block) +{ + [wrapper dispatchAsyncOnMainQueue:block]; +} + +void +sentry_removeObserver(id object) +{ + [SentryDependencyContainer.sharedInstance.notificationCenterWrapper removeObserver:object + name:nil + object:nil]; +} + +void +sentry_addObserver(id observer, SEL selector, NSNotificationName name, _Nullable id object) +{ + return [SentryDependencyContainer.sharedInstance.notificationCenterWrapper addObserver:observer + selector:selector + name:name + object:object]; +} + +void +sentry_postNotification(NSNotification *notification) +{ + [SentryDependencyContainer.sharedInstance.notificationCenterWrapper + postNotification:notification]; +} + +id +sentry_addObserverForName(NSNotificationName name, dispatch_block_t block) +{ + return [SentryDependencyContainer.sharedInstance.notificationCenterWrapper + addObserverForName:name + object:nil + queue:nil + usingBlock:^(NSNotification *_Nonnull notification) { block(); }]; +} + +NSTimer * +sentry_scheduledTimer(NSTimeInterval interval, BOOL repeats, dispatch_block_t block) +{ + return [SentryDependencyContainer.sharedInstance.timerFactory + scheduledTimerWithTimeInterval:interval + repeats:repeats + block:^(NSTimer *_Nonnull timer) { block(); }]; +} + +NSTimer * +sentry_scheduledTimerWithTarget( + NSTimeInterval interval, id target, SEL selector, _Nullable id userInfo, BOOL repeats) +{ + return [SentryDependencyContainer.sharedInstance.timerFactory + scheduledTimerWithTimeInterval:interval + target:target + selector:selector + userInfo:userInfo + repeats:repeats]; +} + +#endif // SENTRY_TARGET_PROFILING_SUPPORTED diff --git a/Sources/Sentry/Profiling/SentryTraceProfiler.mm b/Sources/Sentry/Profiling/SentryTraceProfiler.mm index ac7fc64fb19..e21d95649dd 100644 --- a/Sources/Sentry/Profiling/SentryTraceProfiler.mm +++ b/Sources/Sentry/Profiling/SentryTraceProfiler.mm @@ -6,10 +6,9 @@ # import "SentryLogC.h" # import "SentryMetricProfiler.h" -# import "SentryNSTimerFactory.h" # import "SentryProfiledTracerConcurrency.h" # import "SentryProfiler+Private.h" -# import "SentrySwift.h" +# import "SentryProfilingSwiftHelpers.h" # include # pragma mark - Private @@ -49,7 +48,7 @@ + (BOOL)startWithTracer:(SentryId *)traceId return NO; } - _threadUnsafe_gTraceProfiler.profilerId = [[SentryId alloc] init]; + _threadUnsafe_gTraceProfiler.profilerId = sentry_getSentryId(); sentry_trackTransactionProfilerForTrace(_threadUnsafe_gTraceProfiler, traceId); } @@ -82,20 +81,15 @@ + (void)recordMetrics */ + (void)scheduleTimeoutTimer { - [SentryDependencyContainer.sharedInstance.dispatchQueueWrapper dispatchAsyncOnMainQueue:^{ + sentry_dispatchAsyncOnMain(SentryDependencyContainer.sharedInstance.dispatchQueueWrapper, ^{ std::lock_guard l(_threadUnsafe_gTraceProfilerLock); if (_sentry_threadUnsafe_traceProfileTimeoutTimer != nil) { return; } - _sentry_threadUnsafe_traceProfileTimeoutTimer = - [SentryDependencyContainer.sharedInstance.timerFactory - scheduledTimerWithTimeInterval:kSentryProfilerTimeoutInterval - repeats:NO - block:^(NSTimer *_Nonnull timer) { - [self timeoutTimerExpired]; - }]; - }]; + _sentry_threadUnsafe_traceProfileTimeoutTimer = sentry_scheduledTimer( + kSentryProfilerTimeoutInterval, NO, ^{ [self timeoutTimerExpired]; }); + }); } + (void)timeoutTimerExpired diff --git a/Sources/Sentry/Public/Sentry.h b/Sources/Sentry/Public/Sentry.h index 04189c74583..d1f1919853b 100644 --- a/Sources/Sentry/Public/Sentry.h +++ b/Sources/Sentry/Public/Sentry.h @@ -34,7 +34,6 @@ FOUNDATION_EXPORT const unsigned char SentryVersionString[]; # import # import # import -# import # import # import # import diff --git a/Sources/Sentry/Public/SentryBaggage.h b/Sources/Sentry/Public/SentryBaggage.h index 54223b08413..26a84836b9c 100644 --- a/Sources/Sentry/Public/SentryBaggage.h +++ b/Sources/Sentry/Public/SentryBaggage.h @@ -43,7 +43,9 @@ NS_SWIFT_NAME(Baggage) /** * The value of a segment attribute in the user's data bag, if it exists. */ +#if !SDK_V9 @property (nullable, nonatomic, readonly) NSString *userSegment; +#endif /** * The random value used to determine if the trace is sampled. @@ -69,7 +71,9 @@ NS_SWIFT_NAME(Baggage) releaseName:(nullable NSString *)releaseName environment:(nullable NSString *)environment transaction:(nullable NSString *)transaction +#if !SDK_V9 userSegment:(nullable NSString *)userSegment +#endif sampleRate:(nullable NSString *)sampleRate sampled:(nullable NSString *)sampled replayId:(nullable NSString *)replayId; @@ -79,7 +83,9 @@ NS_SWIFT_NAME(Baggage) releaseName:(nullable NSString *)releaseName environment:(nullable NSString *)environment transaction:(nullable NSString *)transaction +#if !SDK_V9 userSegment:(nullable NSString *)userSegment +#endif sampleRate:(nullable NSString *)sampleRate sampleRand:(nullable NSString *)sampleRand sampled:(nullable NSString *)sampled diff --git a/Sources/Sentry/Public/SentryBreadcrumb.h b/Sources/Sentry/Public/SentryBreadcrumb.h index 559d6a49279..15c56dceb78 100644 --- a/Sources/Sentry/Public/SentryBreadcrumb.h +++ b/Sources/Sentry/Public/SentryBreadcrumb.h @@ -6,12 +6,17 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif NS_ASSUME_NONNULL_BEGIN NS_SWIFT_NAME(Breadcrumb) -@interface SentryBreadcrumb : NSObject +@interface SentryBreadcrumb : NSObject +#if !SDK_V9 + +#endif /** * Level of breadcrumb @@ -59,7 +64,9 @@ NS_SWIFT_NAME(Breadcrumb) - (instancetype)init; + (instancetype)new NS_UNAVAILABLE; +#if !SDK_V9 - (NSDictionary *)serialize; +#endif // !SDK_V9 - (BOOL)isEqual:(id _Nullable)other; diff --git a/Sources/Sentry/Public/SentryDebugImageProvider.h b/Sources/Sentry/Public/SentryDebugImageProvider.h index 552ef8bd0d0..e54ee9b20e7 100644 --- a/Sources/Sentry/Public/SentryDebugImageProvider.h +++ b/Sources/Sentry/Public/SentryDebugImageProvider.h @@ -1,4 +1,6 @@ -#import +#if !SDK_V9 + +# import @class SentryDebugMeta; @class SentryFrame; @@ -7,8 +9,7 @@ NS_ASSUME_NONNULL_BEGIN /** - * Reserved for hybrid SDKs that the debug image list for symbolication. - * @todo This class should be renamed to @c SentryDebugImage in a future version. + * Reserved for hybrid SDKs that need the debug images for symbolication. */ @interface SentryDebugImageProvider : NSObject @@ -88,3 +89,5 @@ NS_ASSUME_NONNULL_BEGIN @end NS_ASSUME_NONNULL_END + +#endif // !SDK_V9 diff --git a/Sources/Sentry/Public/SentryDebugMeta.h b/Sources/Sentry/Public/SentryDebugMeta.h index a451beff724..4b1a08ba9a7 100644 --- a/Sources/Sentry/Public/SentryDebugMeta.h +++ b/Sources/Sentry/Public/SentryDebugMeta.h @@ -6,7 +6,9 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif NS_ASSUME_NONNULL_BEGIN @@ -20,7 +22,10 @@ NS_ASSUME_NONNULL_BEGIN * @c SentryDebugImage in a future version. */ NS_SWIFT_NAME(DebugMeta) -@interface SentryDebugMeta : NSObject +@interface SentryDebugMeta : NSObject +#if !SDK_V9 + +#endif /** * The UUID of the image. Use @c debugID when using "macho" as the @c type . diff --git a/Sources/Sentry/Public/SentryDefines.h b/Sources/Sentry/Public/SentryDefines.h index e9ed26fd097..b037e44c6f7 100644 --- a/Sources/Sentry/Public/SentryDefines.h +++ b/Sources/Sentry/Public/SentryDefines.h @@ -75,6 +75,7 @@ @class SentryEvent; @class SentrySamplingContext; @class SentryUserFeedbackConfiguration; +@class SentryLog; @protocol SentrySpan; /** @@ -107,6 +108,14 @@ typedef SentryEvent *_Nullable (^SentryBeforeSendEventCallback)(SentryEvent *_No */ typedef id _Nullable (^SentryBeforeSendSpanCallback)(id _Nonnull span); +#if !SWIFT_PACKAGE +/** + * Use this block to drop or modify a log before the SDK sends it to Sentry. Return @c nil to drop + * the log. + */ +typedef SentryLog *_Nullable (^SentryBeforeSendLogCallback)(SentryLog *_Nonnull log); +#endif // !SWIFT_PACKAGE + /** * Block can be used to decide if the SDK should capture a screenshot or not. Return @c true if the * SDK should capture a screenshot, return @c false if not. This callback doesn't work for crashes. @@ -143,6 +152,7 @@ typedef BOOL (^SentryShouldQueueEvent)( typedef NSNumber *_Nullable (^SentryTracesSamplerCallback)( SentrySamplingContext *_Nonnull samplingContext); +#if !SDK_V9 /** * Function pointer for span manipulation. * @param span The span to be used. @@ -150,7 +160,6 @@ typedef NSNumber *_Nullable (^SentryTracesSamplerCallback)( typedef void (^SentrySpanCallback)(id _Nullable span DEPRECATED_MSG_ATTRIBUTE( "See `SentryScope.useSpan` for reasoning of deprecation.")); -#if !SDK_V9 /** * Log level. */ diff --git a/Sources/Sentry/Public/SentryDsn.h b/Sources/Sentry/Public/SentryDsn.h index 206e800faee..db3f4ba873d 100644 --- a/Sources/Sentry/Public/SentryDsn.h +++ b/Sources/Sentry/Public/SentryDsn.h @@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN - (NSString *)getHash; -#if !SDK_v9 +#if !SDK_V9 - (NSURL *)getStoreEndpoint DEPRECATED_MSG_ATTRIBUTE("This endpoint is no longer used"); #endif // !SDK_V9 - (NSURL *)getEnvelopeEndpoint; diff --git a/Sources/Sentry/Public/SentryEnvelopeItemHeader.h b/Sources/Sentry/Public/SentryEnvelopeItemHeader.h index 3df7c324e7c..89800fb5ef4 100644 --- a/Sources/Sentry/Public/SentryEnvelopeItemHeader.h +++ b/Sources/Sentry/Public/SentryEnvelopeItemHeader.h @@ -5,11 +5,17 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif NS_ASSUME_NONNULL_BEGIN -@interface SentryEnvelopeItemHeader : NSObject +@interface SentryEnvelopeItemHeader : NSObject +#if !SDK_V9 + +#endif + SENTRY_NO_INIT - (instancetype)initWithType:(NSString *)type length:(NSUInteger)length NS_DESIGNATED_INITIALIZER; diff --git a/Sources/Sentry/Public/SentryEvent.h b/Sources/Sentry/Public/SentryEvent.h index defe3bc116c..bf414da793a 100644 --- a/Sources/Sentry/Public/SentryEvent.h +++ b/Sources/Sentry/Public/SentryEvent.h @@ -6,7 +6,9 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif // !SDK_V9 NS_ASSUME_NONNULL_BEGIN @@ -22,7 +24,10 @@ NS_ASSUME_NONNULL_BEGIN @class SentryUser; NS_SWIFT_NAME(Event) -@interface SentryEvent : NSObject +@interface SentryEvent : NSObject +#if !SDK_V9 + +#endif // !SDK_V9 /** * This will be set by the initializer. diff --git a/Sources/Sentry/Public/SentryException.h b/Sources/Sentry/Public/SentryException.h index a3d37a27012..5bd903ca634 100644 --- a/Sources/Sentry/Public/SentryException.h +++ b/Sources/Sentry/Public/SentryException.h @@ -6,7 +6,9 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif NS_ASSUME_NONNULL_BEGIN @@ -14,7 +16,11 @@ NS_ASSUME_NONNULL_BEGIN @class SentryStacktrace; NS_SWIFT_NAME(Exception) -@interface SentryException : NSObject +@interface SentryException : NSObject +#if !SDK_V9 + +#endif + SENTRY_NO_INIT /** diff --git a/Sources/Sentry/Public/SentryFeedbackAPI.h b/Sources/Sentry/Public/SentryFeedbackAPI.h index be068cef53f..0252f34f7f0 100644 --- a/Sources/Sentry/Public/SentryFeedbackAPI.h +++ b/Sources/Sentry/Public/SentryFeedbackAPI.h @@ -12,7 +12,6 @@ NS_ASSUME_NONNULL_BEGIN -API_AVAILABLE(ios(13.0)) @interface SentryFeedbackAPI : NSObject /** @@ -21,7 +20,8 @@ API_AVAILABLE(ios(13.0)) * @seealso See @c SentryOptions.configureUserFeedback to configure the widget. * @note User feedback widget is only available for iOS 13 or later. */ -- (void)showWidget API_AVAILABLE(ios(13.0)); +- (void)showWidget API_AVAILABLE(ios(13.0)) + NS_EXTENSION_UNAVAILABLE("Sentry User Feedback UI cannot be used from app extensions."); /** * Hide the feedback widget button. @@ -29,7 +29,8 @@ API_AVAILABLE(ios(13.0)) * @seealso See @c SentryOptions.configureUserFeedback to configure the widget. * @note User feedback widget is only available for iOS 13 or later. */ -- (void)hideWidget API_AVAILABLE(ios(13.0)); +- (void)hideWidget API_AVAILABLE(ios(13.0)) + NS_EXTENSION_UNAVAILABLE("Sentry User Feedback UI cannot be used from app extensions."); @end diff --git a/Sources/Sentry/Public/SentryFrame.h b/Sources/Sentry/Public/SentryFrame.h index 5ec3057c206..c459239bbd8 100644 --- a/Sources/Sentry/Public/SentryFrame.h +++ b/Sources/Sentry/Public/SentryFrame.h @@ -6,12 +6,17 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif NS_ASSUME_NONNULL_BEGIN NS_SWIFT_NAME(Frame) -@interface SentryFrame : NSObject +@interface SentryFrame : NSObject +#if !SDK_V9 + +#endif /** * SymbolAddress of the frame @@ -69,6 +74,24 @@ NS_SWIFT_NAME(Frame) */ @property (nonatomic, copy) NSNumber *_Nullable columnNumber; +/** + * Source code line at the error location. + * Mostly used for Godot errors. + */ +@property (nonatomic, copy) NSString *_Nullable contextLine; + +/** + * Source code lines before the error location (up to 5 lines). + * Mostly used for Godot errors. + */ +@property (nonatomic, copy) NSArray *_Nullable preContext; + +/** + * Source code lines after the error location (up to 5 lines). + * Mostly used for Godot errors. + */ +@property (nonatomic, copy) NSArray *_Nullable postContext; + /** * Determines if the Frame is inApp or not */ @@ -79,6 +102,12 @@ NS_SWIFT_NAME(Frame) */ @property (nonatomic, copy) NSNumber *_Nullable stackStart; +/** + * A mapping of variables which were available within this frame. + * Mostly used for Godot errors. + */ +@property (nonatomic, copy) NSDictionary *_Nullable vars; + - (instancetype)init; + (instancetype)new NS_UNAVAILABLE; diff --git a/Sources/Sentry/Public/SentryGeo.h b/Sources/Sentry/Public/SentryGeo.h index 17de42719eb..88fd24188a7 100644 --- a/Sources/Sentry/Public/SentryGeo.h +++ b/Sources/Sentry/Public/SentryGeo.h @@ -6,7 +6,9 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif NS_ASSUME_NONNULL_BEGIN @@ -21,7 +23,12 @@ NS_ASSUME_NONNULL_BEGIN /// } /// } NS_SWIFT_NAME(Geo) -@interface SentryGeo : NSObject +@interface SentryGeo : NSObject +#if !SDK_V9 + +#else + +#endif /** * Optional: Human readable city name. diff --git a/Sources/Sentry/Public/SentryHub.h b/Sources/Sentry/Public/SentryHub.h index 42c2ef62931..fcdf7867f13 100644 --- a/Sources/Sentry/Public/SentryHub.h +++ b/Sources/Sentry/Public/SentryHub.h @@ -12,7 +12,6 @@ @class SentryEvent; @class SentryFeedback; @class SentryId; -@class SentryMetricsAPI; @class SentryScope; @class SentryTransactionContext; @class SentryUser; @@ -25,8 +24,6 @@ SENTRY_NO_INIT - (instancetype)initWithClient:(SentryClient *_Nullable)client andScope:(SentryScope *_Nullable)scope; -@property (nonatomic, readonly) SentryMetricsAPI *metrics; - /** * Starts a new SentrySession. If there's a running SentrySession, it ends it before starting the * new one. You can use this method in combination with endSession to manually track SentrySessions. diff --git a/Sources/Sentry/Public/SentryMechanism.h b/Sources/Sentry/Public/SentryMechanism.h index d2bf603d962..68643c0c177 100644 --- a/Sources/Sentry/Public/SentryMechanism.h +++ b/Sources/Sentry/Public/SentryMechanism.h @@ -6,7 +6,9 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif NS_ASSUME_NONNULL_BEGIN @@ -14,7 +16,11 @@ NS_ASSUME_NONNULL_BEGIN @class SentryMechanismMeta; NS_SWIFT_NAME(Mechanism) -@interface SentryMechanism : NSObject +@interface SentryMechanism : NSObject +#if !SDK_V9 + +#endif + SENTRY_NO_INIT /** diff --git a/Sources/Sentry/Public/SentryMechanismMeta.h b/Sources/Sentry/Public/SentryMechanismMeta.h index 9f6dff6ff80..3b57a21f512 100644 --- a/Sources/Sentry/Public/SentryMechanismMeta.h +++ b/Sources/Sentry/Public/SentryMechanismMeta.h @@ -6,7 +6,9 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif @class SentryNSError; @@ -18,7 +20,10 @@ NS_ASSUME_NONNULL_BEGIN * @see https://develop.sentry.dev/sdk/event-payloads/exception/#meta-information. */ NS_SWIFT_NAME(MechanismMeta) -@interface SentryMechanismMeta : NSObject +@interface SentryMechanismMeta : NSObject +#if !SDK_V9 + +#endif - (instancetype)init; diff --git a/Sources/Sentry/Public/SentryMessage.h b/Sources/Sentry/Public/SentryMessage.h index 59af411a837..c704d28fb29 100644 --- a/Sources/Sentry/Public/SentryMessage.h +++ b/Sources/Sentry/Public/SentryMessage.h @@ -6,7 +6,9 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif NS_ASSUME_NONNULL_BEGIN @@ -15,7 +17,11 @@ NS_ASSUME_NONNULL_BEGIN * and structured parameters. This can help to group similar messages into the same issue. * @see https://develop.sentry.dev/sdk/event-payloads/message/ */ -@interface SentryMessage : NSObject +@interface SentryMessage : NSObject +#if !SDK_V9 + +#endif + SENTRY_NO_INIT /** diff --git a/Sources/Sentry/Public/SentryNSError.h b/Sources/Sentry/Public/SentryNSError.h index c58d5422a6b..40620c31d56 100644 --- a/Sources/Sentry/Public/SentryNSError.h +++ b/Sources/Sentry/Public/SentryNSError.h @@ -6,14 +6,20 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif NS_ASSUME_NONNULL_BEGIN /** * Sentry representation of an @c NSError to send to Sentry. */ -@interface SentryNSError : NSObject +@interface SentryNSError : NSObject +#if !SDK_V9 + +#endif + SENTRY_NO_INIT /** diff --git a/Sources/Sentry/Public/SentryOptions.h b/Sources/Sentry/Public/SentryOptions.h index b1d9ae1fad4..148569858e2 100644 --- a/Sources/Sentry/Public/SentryOptions.h +++ b/Sources/Sentry/Public/SentryOptions.h @@ -17,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN @class SentryProfileOptions; #endif // SENTRY_TARGET_PROFILING_SUPPORTED @class SentryScope; +@class SentryViewScreenshotOptions; NS_SWIFT_NAME(Options) @interface SentryOptions : NSObject @@ -156,6 +157,14 @@ NS_SWIFT_NAME(Options) */ @property (nullable, nonatomic, copy) SentryBeforeSendSpanCallback beforeSendSpan NS_SWIFT_SENDABLE; +#if !SWIFT_PACKAGE +/** + * Use this callback to drop or modify a log before the SDK sends it to Sentry. Return @c nil to + * drop the log. + */ +@property (nullable, nonatomic, copy) SentryBeforeSendLogCallback beforeSendLog NS_SWIFT_SENDABLE; +#endif // !SWIFT_PACKAGE + /** * This block can be used to modify the event before it will be serialized and sent. */ @@ -191,10 +200,14 @@ NS_SWIFT_NAME(Options) @property (nullable, nonatomic, copy) SentryOnCrashedLastRunCallback onCrashedLastRun NS_SWIFT_SENDABLE; +#if !SDK_V9 /** * Array of integrations to install. */ -@property (nullable, nonatomic, copy) NSArray *integrations; +@property (nullable, nonatomic, copy) NSArray *integrations DEPRECATED_MSG_ATTRIBUTE( + "Setting `SentryOptions.integrations` is deprecated. Integrations should be enabled or " + "disabled using their respective `SentryOptions.enable*` property."); +#endif // !SDK_V9 /** * Array of default integrations. Will be used if @c integrations is @c nil . @@ -258,9 +271,9 @@ NS_SWIFT_NAME(Options) * When enabled, the SDK sends personal identifiable along with events. * @note The default is @c NO . * @discussion When the user of an event doesn't contain an IP address, and this flag is - * @c YES, the SDK sets it to @c {{auto}} to instruct the server to use the - * connection IP address as the user address. Due to backward compatibility concerns, Sentry set the - * IP address to @c {{auto}} out of the box for Cocoa. If you want to stop Sentry from + * @c YES, the SDK sets sdk.settings.infer_ip to @c auto to instruct the server to use the + * connection IP address as the user address. Due to backward compatibility concerns, Sentry sets + * sdk.settings.infer_ip to @c auto out of the box for Cocoa. If you want to stop Sentry from * using the connections IP address, you have to enable Prevent Storing of IP Addresses in your * project settings in Sentry. */ @@ -320,6 +333,11 @@ NS_SWIFT_NAME(Options) */ @property (nonatomic, assign) BOOL attachScreenshot; +/** + * Settings to configure screenshot attachments. + */ +@property (nonatomic, nonnull, strong) SentryViewScreenshotOptions *screenshot; + /** * @warning This is an experimental feature and may still have bugs. * @brief Automatically attaches a textual representation of the view hierarchy when capturing an @@ -398,6 +416,7 @@ NS_SWIFT_NAME(Options) */ @property (nonatomic, assign) BOOL enableFileIOTracing; +#if !SDK_V9 /** * Indicates whether tracing should be enabled. * @discussion Enabling this sets @c tracesSampleRate to @c 1 if both @c tracesSampleRate and @@ -406,6 +425,7 @@ NS_SWIFT_NAME(Options) */ @property (nonatomic) BOOL enableTracing DEPRECATED_MSG_ATTRIBUTE("Use tracesSampleRate or tracesSampler instead"); +#endif // !SDK_V9 /** * Indicates the percentage of the tracing data that is collected. @@ -530,6 +550,7 @@ typedef void (^SentryProfilingConfigurationBlock)(SentryProfileOptions *_Nonnull */ @property (nullable, nonatomic, copy) SentryProfilingConfigurationBlock configureProfiling; +# if !SDK_V9 /** * @warning This is an experimental feature and may still have bugs. * Set to @c YES to run the profiler as early as possible in an app launch, before you would @@ -543,7 +564,9 @@ typedef void (^SentryProfilingConfigurationBlock)(SentryProfileOptions *_Nonnull * @c SentryProfileOptions.startOnAppStart and @c SentryProfileOptions.lifecycle . * @note Profiling is automatically disabled if a thread sanitizer is attached. */ -@property (nonatomic, assign) BOOL enableAppLaunchProfiling; +@property (nonatomic, assign) BOOL enableAppLaunchProfiling DEPRECATED_MSG_ATTRIBUTE( + "This property is deprecated and will be removed in a future version of the SDK. See " + "SentryProfileOptions.startOnAppStart and SentryProfileOptions.lifecycle"); /** * @note Profiling is not supported on watchOS or tvOS. @@ -570,7 +593,9 @@ typedef void (^SentryProfilingConfigurationBlock)(SentryProfileOptions *_Nonnull * @warning This property is deprecated and will be removed in a future version of the SDK. See * @c SentryProfileOptions.sessionSampleRate. */ -@property (nullable, nonatomic, strong) NSNumber *profilesSampleRate; +@property (nullable, nonatomic, strong) NSNumber *profilesSampleRate DEPRECATED_MSG_ATTRIBUTE( + "This property is deprecated and will be removed in a future version of the SDK. See " + "SentryProfileOptions.sessionSampleRate"); /** * @note Profiling is not supported on watchOS or tvOS. @@ -584,7 +609,10 @@ typedef void (^SentryProfilingConfigurationBlock)(SentryProfileOptions *_Nonnull * @warning This property is deprecated and will be removed in a future version of the SDK. See * @c SentryProfileOptions.sessionSampleRate . */ -@property (nullable, nonatomic) SentryTracesSamplerCallback profilesSampler NS_SWIFT_SENDABLE; +@property (nullable, nonatomic) + SentryTracesSamplerCallback profilesSampler NS_SWIFT_SENDABLE DEPRECATED_MSG_ATTRIBUTE( + "This property is deprecated and will be removed in a future version of the SDK. See " + "SentryProfileOptions.sessionSampleRate"); /** * If profiling should be enabled or not. @@ -597,7 +625,8 @@ typedef void (^SentryProfilingConfigurationBlock)(SentryProfileOptions *_Nonnull * @note Profiling is automatically disabled if a thread sanitizer is attached. * @warning This property is deprecated and will be removed in a future version of the SDK. */ -@property (nonatomic, assign, readonly) BOOL isProfilingEnabled; +@property (nonatomic, assign, readonly) BOOL isProfilingEnabled DEPRECATED_MSG_ATTRIBUTE( + "This property is deprecated and will be removed in a future version of the SDK"); /** * @brief Whether to enable the sampling profiler. @@ -611,6 +640,7 @@ typedef void (^SentryProfilingConfigurationBlock)(SentryProfileOptions *_Nonnull @property (nonatomic, assign) BOOL enableProfiling DEPRECATED_MSG_ATTRIBUTE( "Use profilesSampleRate or profilesSampler instead. This property will be removed in a future " "version of the SDK"); +# endif // !SDK_V9 #endif // SENTRY_TARGET_PROFILING_SUPPORTED /** @@ -630,6 +660,7 @@ typedef void (^SentryProfilingConfigurationBlock)(SentryProfileOptions *_Nonnull #if SENTRY_UIKIT_AVAILABLE +# if !SDK_V9 /** * AppHangTrackingV2 can differentiate between fully-blocking and non-fully blocking app hangs. * fully-blocking app hang is when the main thread is stuck completely, and the app can't render a @@ -649,6 +680,8 @@ typedef void (^SentryProfilingConfigurationBlock)(SentryProfileOptions *_Nonnull */ @property (nonatomic, assign) BOOL enableAppHangTrackingV2; +# endif // !SDK_V9 + /** * When enabled the SDK reports non-fully-blocking app hangs. A non-fully-blocking app hang is when * the app appears stuck to the user but can still render a few frames. For more information see @c @@ -799,7 +832,8 @@ typedef void (^SentryProfilingConfigurationBlock)(SentryProfileOptions *_Nonnull * @note User feedback widget is only available for iOS 13 or later. */ @property (nonatomic, copy, nullable) - SentryUserFeedbackConfigurationBlock configureUserFeedback API_AVAILABLE(ios(13.0)); + SentryUserFeedbackConfigurationBlock configureUserFeedback API_AVAILABLE(ios(13.0)) + NS_EXTENSION_UNAVAILABLE("Sentry User Feedback UI cannot be used from app extensions."); #endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT diff --git a/Sources/Sentry/Public/SentryReplayApi.h b/Sources/Sentry/Public/SentryReplayApi.h index 106537021e2..5872c92ae04 100644 --- a/Sources/Sentry/Public/SentryReplayApi.h +++ b/Sources/Sentry/Public/SentryReplayApi.h @@ -52,6 +52,8 @@ NS_ASSUME_NONNULL_BEGIN * This will only work if the debbuger is attached and it will * cause some slow frames. * + * @note This method must be called from the main thread. + * * @warning This is an experimental feature and may still have bugs. * Do not use this is production. */ @@ -67,6 +69,8 @@ NS_ASSUME_NONNULL_BEGIN * * @param opacity The opacity of the overlay. * + * @note This method must be called from the main thread. + * * @warning This is an experimental feature and may still have bugs. * Do not use this is production. */ @@ -75,6 +79,8 @@ NS_ASSUME_NONNULL_BEGIN /** * Removes the overlay that shows replay masking. * + * @note This method must be called from the main thread. + * * @warning This is an experimental feature and may still have bugs. * Do not use this is production. */ diff --git a/Sources/Sentry/Public/SentryRequest.h b/Sources/Sentry/Public/SentryRequest.h index 2a0dc30203a..dcbcea3ceb3 100644 --- a/Sources/Sentry/Public/SentryRequest.h +++ b/Sources/Sentry/Public/SentryRequest.h @@ -5,11 +5,16 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif NS_ASSUME_NONNULL_BEGIN -@interface SentryRequest : NSObject +@interface SentryRequest : NSObject +#if !SDK_V9 + +#endif /** * Optional: HTTP response body size. diff --git a/Sources/Sentry/Public/SentryScope.h b/Sources/Sentry/Public/SentryScope.h index d3531157305..b3515ed53c7 100644 --- a/Sources/Sentry/Public/SentryScope.h +++ b/Sources/Sentry/Public/SentryScope.h @@ -5,7 +5,9 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif // SDK_V9 #import SENTRY_HEADER(SentrySpanProtocol) @class SentryAttachment; @@ -22,13 +24,20 @@ NS_ASSUME_NONNULL_BEGIN * https://docs.sentry.io/platforms/apple/enriching-events/scopes/#whats-a-scope-whats-a-hub */ NS_SWIFT_NAME(Scope) -@interface SentryScope : NSObject +@interface SentryScope : NSObject +#if !SDK_V9 + +#endif // !SDK_V9 /** * Returns current Span or Transaction. * @return current Span or Transaction or null if transaction has not been set. */ +#if SDK_V9 +@property (nullable, nonatomic, readonly, strong) id span; +#else @property (nullable, nonatomic, strong) id span; +#endif // SDK_V9 /** * The id of current session replay. @@ -115,10 +124,12 @@ NS_SWIFT_NAME(Scope) */ - (void)clearBreadcrumbs; +#if !SDK_V9 /** * Serializes the Scope to JSON */ - (NSDictionary *)serialize; +#endif // !SDK_V9 /** * Sets context values which will overwrite SentryEvent.context when event is @@ -166,11 +177,6 @@ NS_SWIFT_NAME(Scope) "now considered unsafe and deprecated. Use `span` instead."); #endif // !SDK_V9 -/** - * Returns the current span. - */ -- (id _Nullable)span; - @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/Public/SentrySpanContext.h b/Sources/Sentry/Public/SentrySpanContext.h index 5b65e96504a..89c7fd3575a 100644 --- a/Sources/Sentry/Public/SentrySpanContext.h +++ b/Sources/Sentry/Public/SentrySpanContext.h @@ -6,7 +6,9 @@ # import #endif #import SENTRY_HEADER(SentrySampleDecision) -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif #import SENTRY_HEADER(SentrySpanStatus) NS_ASSUME_NONNULL_BEGIN @@ -17,7 +19,11 @@ NS_ASSUME_NONNULL_BEGIN static NSString const *SENTRY_TRACE_TYPE = @"trace"; NS_SWIFT_NAME(SpanContext) -@interface SentrySpanContext : NSObject +@interface SentrySpanContext : NSObject +#if !SDK_V9 + +#endif + SENTRY_NO_INIT /** diff --git a/Sources/Sentry/Public/SentrySpanProtocol.h b/Sources/Sentry/Public/SentrySpanProtocol.h index 84605537c0e..bd285a5a4e9 100644 --- a/Sources/Sentry/Public/SentrySpanProtocol.h +++ b/Sources/Sentry/Public/SentrySpanProtocol.h @@ -5,7 +5,9 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif // SDK_V9 #import SENTRY_HEADER(SentrySpanContext) NS_ASSUME_NONNULL_BEGIN @@ -17,7 +19,11 @@ NS_ASSUME_NONNULL_BEGIN @class SentryTraceHeader; NS_SWIFT_NAME(Span) +#if SDK_V9 +@protocol SentrySpan +#else @protocol SentrySpan +#endif /** * Determines which trace the Span belongs to. @@ -118,12 +124,14 @@ NS_SWIFT_NAME(Span) */ - (void)setDataValue:(nullable id)value forKey:(NSString *)key NS_SWIFT_NAME(setData(value:key:)); +#if !SDK_V9 /** * Use @c setDataValue instead. This method calls @c setDataValue, was added by mistake, and will be * removed in a future version. */ - (void)setExtraValue:(nullable id)value forKey:(NSString *)key DEPRECATED_ATTRIBUTE NS_SWIFT_NAME(setExtra(value:key:)); +#endif // !SDK_V9 /** * Removes a data value. @@ -188,6 +196,8 @@ NS_SWIFT_NAME(Span) */ - (nullable NSString *)baggageHttpHeader; +- (NSDictionary *)serialize; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/Public/SentryStacktrace.h b/Sources/Sentry/Public/SentryStacktrace.h index 5c8d11f8b3b..0f6b5d4695c 100644 --- a/Sources/Sentry/Public/SentryStacktrace.h +++ b/Sources/Sentry/Public/SentryStacktrace.h @@ -6,13 +6,19 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif NS_ASSUME_NONNULL_BEGIN @class SentryFrame; -@interface SentryStacktrace : NSObject +@interface SentryStacktrace : NSObject +#if !SDK_V9 + +#endif + SENTRY_NO_INIT /** diff --git a/Sources/Sentry/Public/SentryThread.h b/Sources/Sentry/Public/SentryThread.h index cbf94227817..45e1b4dd00a 100644 --- a/Sources/Sentry/Public/SentryThread.h +++ b/Sources/Sentry/Public/SentryThread.h @@ -5,13 +5,19 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif NS_ASSUME_NONNULL_BEGIN @class SentryStacktrace; -@interface SentryThread : NSObject +@interface SentryThread : NSObject +#if !SDK_V9 + +#endif + SENTRY_NO_INIT /** diff --git a/Sources/Sentry/Public/SentryTraceContext.h b/Sources/Sentry/Public/SentryTraceContext.h index 790440489cf..b54d08e597d 100644 --- a/Sources/Sentry/Public/SentryTraceContext.h +++ b/Sources/Sentry/Public/SentryTraceContext.h @@ -1,7 +1,12 @@ -#if __has_include() -# import +#if __has_include() +# import +#elif __has_include() +# import #else -# import "SentrySerializable.h" +# import +#endif +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) #endif NS_ASSUME_NONNULL_BEGIN @@ -14,7 +19,10 @@ NS_ASSUME_NONNULL_BEGIN @class SentryUser; NS_SWIFT_NAME(TraceContext) -@interface SentryTraceContext : NSObject +@interface SentryTraceContext : NSObject +#if !SDK_V9 + +#endif /** * UUID V4 encoded as a hexadecimal sequence with no dashes (e.g. 771a43a4192642f0b136d5159a501700) @@ -45,7 +53,9 @@ NS_SWIFT_NAME(TraceContext) /** * A subset of the scope's user context. */ +#if !SDK_V9 @property (nullable, nonatomic, readonly) NSString *userSegment; +#endif /** * Serialized sample rate used for this trace. @@ -75,7 +85,9 @@ NS_SWIFT_NAME(TraceContext) releaseName:(nullable NSString *)releaseName environment:(nullable NSString *)environment transaction:(nullable NSString *)transaction +#if !SDK_V9 userSegment:(nullable NSString *)userSegment +#endif sampleRate:(nullable NSString *)sampleRate sampled:(nullable NSString *)sampled replayId:(nullable NSString *)replayId; @@ -88,7 +100,9 @@ NS_SWIFT_NAME(TraceContext) releaseName:(nullable NSString *)releaseName environment:(nullable NSString *)environment transaction:(nullable NSString *)transaction +#if !SDK_V9 userSegment:(nullable NSString *)userSegment +#endif sampleRate:(nullable NSString *)sampleRate sampleRand:(nullable NSString *)sampleRand sampled:(nullable NSString *)sampled @@ -111,16 +125,29 @@ NS_SWIFT_NAME(TraceContext) scope:(nullable SentryScope *)scope options:(SentryOptions *)options; +#if SDK_V9 /** - * Initializes a SentryTraceContext with data from a traceID, options and userSegment. + * Initializes a SentryTraceContext with data from a traceId, options and replayId. + * + * @param traceId The current tracer. + * @param options The current active options. + * @param replayId The current session replay. + */ +#else +/** + * Initializes a SentryTraceContext with data from a traceId, options, userSegment and replayId. * * @param traceId The current tracer. * @param options The current active options. * @param userSegment You can retrieve this usually from the `scope.userObject.segment`. + * @param replayId The current session replay. */ +#endif - (instancetype)initWithTraceId:(SentryId *)traceId options:(SentryOptions *)options +#if !SDK_V9 userSegment:(nullable NSString *)userSegment +#endif replayId:(nullable NSString *)replayId; /** diff --git a/Sources/Sentry/Public/SentryUser.h b/Sources/Sentry/Public/SentryUser.h index 685e786f5d3..b1b6fee1f67 100644 --- a/Sources/Sentry/Public/SentryUser.h +++ b/Sources/Sentry/Public/SentryUser.h @@ -5,14 +5,21 @@ #else # import #endif -#import SENTRY_HEADER(SentrySerializable) +#if !SDK_V9 +# import SENTRY_HEADER(SentrySerializable) +#endif // !SDK_V9 NS_ASSUME_NONNULL_BEGIN @class SentryGeo; NS_SWIFT_NAME(User) -@interface SentryUser : NSObject +@interface SentryUser : NSObject +#if SDK_V9 + +#else + +#endif // SDK_V9 /** * Optional: Id of the user @@ -34,12 +41,14 @@ NS_SWIFT_NAME(User) */ @property (atomic, copy) NSString *_Nullable ipAddress; +#if !SDK_V9 /** * The user segment, for apps that divide users in user segments. * @deprecated This field will be removed in the next major version. */ @property (atomic, copy) NSString *_Nullable segment DEPRECATED_MSG_ATTRIBUTE( "This field is deprecated and will be removed in the next major update."); +#endif // !SDK_V9 /** * Optional: Human readable name diff --git a/Sources/Sentry/Public/SentryWithoutUIKit.h b/Sources/Sentry/Public/SentryWithoutUIKit.h index 8f419dea677..508d9b09348 100644 --- a/Sources/Sentry/Public/SentryWithoutUIKit.h +++ b/Sources/Sentry/Public/SentryWithoutUIKit.h @@ -35,7 +35,6 @@ FOUNDATION_EXPORT const unsigned char SentryVersionString[]; # import # import # import -# import # import # import # import diff --git a/Sources/Sentry/SentryANRTrackerV1.m b/Sources/Sentry/SentryANRTrackerV1.m index db769f782ef..ecd31be5186 100644 --- a/Sources/Sentry/SentryANRTrackerV1.m +++ b/Sources/Sentry/SentryANRTrackerV1.m @@ -1,5 +1,4 @@ #import "SentryANRTrackerV1.h" -#import "SentryCrashWrapper.h" #import "SentryDependencyContainer.h" #import "SentryLogC.h" #import "SentrySwift.h" diff --git a/Sources/Sentry/SentryANRTrackerV2.m b/Sources/Sentry/SentryANRTrackerV2.m index c9cd1255cbe..3ec62b043e8 100644 --- a/Sources/Sentry/SentryANRTrackerV2.m +++ b/Sources/Sentry/SentryANRTrackerV2.m @@ -2,7 +2,6 @@ #if SENTRY_HAS_UIKIT -# import "SentryCrashWrapper.h" # import "SentryDependencyContainer.h" # import "SentryFramesTracker.h" # import "SentryLogC.h" diff --git a/Sources/Sentry/SentryANRTrackingIntegration.m b/Sources/Sentry/SentryANRTrackingIntegration.m index 1a7c2757e79..eb2c4d7f8c6 100644 --- a/Sources/Sentry/SentryANRTrackingIntegration.m +++ b/Sources/Sentry/SentryANRTrackingIntegration.m @@ -1,7 +1,6 @@ #import "SentryANRTrackingIntegration.h" #import "SentryClient+Private.h" #import "SentryCrashMachineContext.h" -#import "SentryCrashWrapper.h" #import "SentryDebugImageProvider+HybridSDKs.h" #import "SentryDependencyContainer.h" #import "SentryEvent.h" @@ -17,8 +16,6 @@ #import "SentryThread.h" #import "SentryThreadInspector.h" #import "SentryThreadWrapper.h" -#import "SentryUIApplication.h" -#import #import #if SENTRY_HAS_UIKIT @@ -51,9 +48,14 @@ - (BOOL)installWithOptions:(SentryOptions *)options } #if SENTRY_HAS_UIKIT +# if SDK_V9 + BOOL isV2Enabled = YES; +# else + BOOL isV2Enabled = options.enableAppHangTrackingV2; +# endif // SDK_V9 self.tracker = [SentryDependencyContainer.sharedInstance getANRTracker:options.appHangTimeoutInterval - isV2Enabled:options.enableAppHangTrackingV2]; + isV2Enabled:isV2Enabled]; #else self.tracker = [SentryDependencyContainer.sharedInstance getANRTracker:options.appHangTimeoutInterval]; @@ -115,12 +117,12 @@ - (void)anrDetectedWithType:(enum SentryANRType)type // If the app is not active, the main thread may be blocked or too busy. // Since there is no UI for the user to interact, there is no need to report app hang. - if (SentryDependencyContainer.sharedInstance.application.applicationState + if (SentryDependencyContainer.sharedInstance.threadsafeApplication.applicationState != UIApplicationStateActive) { return; } #endif // SENTRY_HAS_UIKIT - SentryThreadInspector *threadInspector = SentrySDK.currentHub.getClient.threadInspector; + SentryThreadInspector *threadInspector = SentrySDKInternal.currentHub.getClient.threadInspector; NSArray *threads = [threadInspector getCurrentThreadsWithStackTrace]; @@ -157,9 +159,15 @@ - (void)anrDetectedWithType:(enum SentryANRType)type event.debugMeta = [self.debugImageProvider getDebugImagesFromCacheForThreads:event.threads]; #if SENTRY_HAS_UIKIT +# if SDK_V9 + BOOL isV2Enabled = YES; +# else + BOOL isV2Enabled = self.options.enableAppHangTrackingV2; +# endif // SDK_V9 + // We only measure app hang duration for V2. // For V1, we directly capture the app hang event. - if (self.options.enableAppHangTrackingV2) { + if (isV2Enabled) { // We only temporarily store the app hang duration info, so we can change the error message // when either sending a normal or fatal app hang event. Otherwise, we would have to rely on // string parsing to retrieve the app hang duration info from the error message. @@ -168,8 +176,8 @@ - (void)anrDetectedWithType:(enum SentryANRType)type // We need to apply the scope now because if the app hang turns into a fatal one, // we would lose the scope. Furthermore, we want to know in which state the app was when the // app hang started. - SentryScope *scope = [SentrySDK currentHub].scope; - SentryOptions *options = SentrySDK.options; + SentryScope *scope = [SentrySDKInternal currentHub].scope; + SentryOptions *options = SentrySDKInternal.options; if (scope != nil && options != nil) { [scope applyToEvent:event maxBreadcrumb:options.maxBreadcrumbs]; } @@ -187,9 +195,11 @@ - (void)anrStoppedWithResult:(SentryANRStoppedResult *_Nullable)result { #if SENTRY_HAS_UIKIT // We only measure app hang duration for V2, and therefore ignore V1. +# if !SDK_V9 if (!self.options.enableAppHangTrackingV2) { return; } +# endif // !SDK_V9 if (result == nil) { SENTRY_LOG_WARN(@"ANR stopped for V2 but result was nil.") @@ -288,7 +298,7 @@ - (void)captureStoredAppHangEvent // We already applied the scope. We use an empty scope to avoid overwriting exising // fields on the event. - [SentrySDK captureFatalAppHangEvent:event]; + [SentrySDKInternal captureFatalAppHangEvent:event]; } }]; } diff --git a/Sources/Sentry/SentryAppStartTracker.m b/Sources/Sentry/SentryAppStartTracker.m index 879ef1bd0aa..8519d0e286d 100644 --- a/Sources/Sentry/SentryAppStartTracker.m +++ b/Sources/Sentry/SentryAppStartTracker.m @@ -9,8 +9,8 @@ # import "SentryLogC.h" # import "SentrySysctl.h" # import -# import # import +# import # import # import # import @@ -28,7 +28,7 @@ @interface SentryAppStartTracker () -@property (nonatomic, strong) SentryAppState *previousAppState; +@property (nonatomic, strong, nullable) SentryAppState *previousAppState; @property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueue; @property (nonatomic, strong) SentryAppStateManager *appStateManager; @property (nonatomic, strong) SentryFramesTracker *framesTracker; @@ -214,10 +214,10 @@ - (void)buildAppStartMeasurement:(NSDate *)appStartEnd duration:appStartDuration runtimeInitTimestamp:runtimeInit moduleInitializationTimestamp:sysctl.moduleInitializationTimestamp - sdkStartTimestamp:SentrySDK.startTimestamp + sdkStartTimestamp:SentrySDKInternal.startTimestamp didFinishLaunchingTimestamp:self.didFinishLaunchingTimestamp]; - SentrySDK.appStartMeasurement = appStartMeasurement; + SentrySDKInternal.appStartMeasurement = appStartMeasurement; }; // With only running this once we know that the process is a new one when the following @@ -258,15 +258,17 @@ - (SentryAppStartType)getStartType if (self.previousAppState == nil) { return SentryAppStartTypeCold; } - + SentryAppState *_Nonnull previousAppState + = SENTRY_UNWRAP_NULLABLE(SentryAppState, self.previousAppState); SentryAppState *currentAppState = [self.appStateManager buildCurrentAppState]; // If the release name is different we assume it's an app upgrade - if (![currentAppState.releaseName isEqualToString:self.previousAppState.releaseName]) { + if (![currentAppState.releaseName + isEqualToString:SENTRY_UNWRAP_NULLABLE(NSString, previousAppState.releaseName)]) { return SentryAppStartTypeCold; } - NSTimeInterval intervalSincePreviousBootTime = [self.previousAppState.systemBootTimestamp + NSTimeInterval intervalSincePreviousBootTime = [previousAppState.systemBootTimestamp timeIntervalSinceDate:currentAppState.systemBootTimestamp]; // System rebooted, because the previous boot time is in the past. diff --git a/Sources/Sentry/SentryAppStartTrackingIntegration.m b/Sources/Sentry/SentryAppStartTrackingIntegration.m index d2e27a10d36..0bd7ca95020 100644 --- a/Sources/Sentry/SentryAppStartTrackingIntegration.m +++ b/Sources/Sentry/SentryAppStartTrackingIntegration.m @@ -8,7 +8,6 @@ # import "SentrySwift.h" # import # import -# import # import @interface SentryAppStartTrackingIntegration () diff --git a/Sources/Sentry/SentryAppState.m b/Sources/Sentry/SentryAppState.m deleted file mode 100644 index 298bfeaa5af..00000000000 --- a/Sources/Sentry/SentryAppState.m +++ /dev/null @@ -1,128 +0,0 @@ -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@implementation SentryAppState - -- (instancetype)initWithReleaseName:(nullable NSString *)releaseName - osVersion:(NSString *)osVersion - vendorId:(NSString *)vendorId - isDebugging:(BOOL)isDebugging - systemBootTimestamp:(NSDate *)systemBootTimestamp -{ - if (self = [super init]) { - _releaseName = releaseName; - _osVersion = osVersion; - _vendorId = vendorId; - _isDebugging = isDebugging; - - // Round down to seconds as the precision of the serialization of the date is only - // milliseconds. With this we avoid getting different dates before and after serialization. - NSTimeInterval interval = round(systemBootTimestamp.timeIntervalSince1970); - _systemBootTimestamp = [[NSDate alloc] initWithTimeIntervalSince1970:interval]; - - _isActive = NO; - _wasTerminated = NO; - _isANROngoing = NO; - _isSDKRunning = YES; - } - return self; -} - -- (nullable instancetype)initWithJSONObject:(NSDictionary *)jsonObject -{ - if (self = [super init]) { - id releaseName = [jsonObject valueForKey:@"release_name"]; - if (releaseName != nil && ![releaseName isKindOfClass:[NSString class]]) { - return nil; - } else { - _releaseName = releaseName; - } - - id osVersion = [jsonObject valueForKey:@"os_version"]; - if (osVersion == nil || ![osVersion isKindOfClass:[NSString class]]) { - return nil; - } else { - _osVersion = osVersion; - } - - id vendorId = [jsonObject valueForKey:@"vendor_id"]; - if (vendorId == nil || ![vendorId isKindOfClass:[NSString class]]) { - return nil; - } else { - _vendorId = vendorId; - } - - id isDebugging = [jsonObject valueForKey:@"is_debugging"]; - if (isDebugging == nil || ![isDebugging isKindOfClass:[NSNumber class]]) { - return nil; - } else { - _isDebugging = [isDebugging boolValue]; - } - - id systemBoot = [jsonObject valueForKey:@"system_boot_timestamp"]; - if (systemBoot == nil || ![systemBoot isKindOfClass:[NSString class]]) - return nil; - NSDate *systemBootTimestamp = sentry_fromIso8601String(systemBoot); - if (nil == systemBootTimestamp) { - return nil; - } - _systemBootTimestamp = systemBootTimestamp; - - id isActive = [jsonObject valueForKey:@"is_active"]; - if (isActive == nil || ![isActive isKindOfClass:[NSNumber class]]) { - return nil; - } else { - _isActive = [isActive boolValue]; - } - - id wasTerminated = [jsonObject valueForKey:@"was_terminated"]; - if (wasTerminated == nil || ![wasTerminated isKindOfClass:[NSNumber class]]) { - return nil; - } else { - _wasTerminated = [wasTerminated boolValue]; - } - - id isANROngoing = [jsonObject valueForKey:@"is_anr_ongoing"]; - if (isANROngoing == nil || ![isANROngoing isKindOfClass:[NSNumber class]]) { - return nil; - } else { - _isANROngoing = [isANROngoing boolValue]; - } - - id isSDKRunning = [jsonObject valueForKey:@"is_sdk_running"]; - if (isSDKRunning == nil || ![isSDKRunning isKindOfClass:[NSNumber class]]) { - // This property was added later so instead of returning nil, - // we're setting it to the default value. - _isSDKRunning = YES; - } else { - _isSDKRunning = [isSDKRunning boolValue]; - } - } - return self; -} - -- (NSDictionary *)serialize -{ - NSMutableDictionary *data = [[NSMutableDictionary alloc] init]; - - if (self.releaseName != nil) { - [data setValue:self.releaseName forKey:@"release_name"]; - } - [data setValue:self.osVersion forKey:@"os_version"]; - [data setValue:self.vendorId forKey:@"vendor_id"]; - [data setValue:@(self.isDebugging) forKey:@"is_debugging"]; - [data setValue:sentry_toIso8601String(self.systemBootTimestamp) - forKey:@"system_boot_timestamp"]; - [data setValue:@(self.isActive) forKey:@"is_active"]; - [data setValue:@(self.wasTerminated) forKey:@"was_terminated"]; - [data setValue:@(self.isANROngoing) forKey:@"is_anr_ongoing"]; - [data setValue:@(self.isSDKRunning) forKey:@"is_sdk_running"]; - - return data; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryAppStateManager.m b/Sources/Sentry/SentryAppStateManager.m index 5bfdeb7e1f7..173e1706bd0 100644 --- a/Sources/Sentry/SentryAppStateManager.m +++ b/Sources/Sentry/SentryAppStateManager.m @@ -1,17 +1,14 @@ #import "SentryCrashSysCtl.h" #import "SentryDependencyContainer.h" +#import "SentryNotificationNames.h" #import "SentrySysctl.h" -#import #import -#import #import -#import #import #import #if SENTRY_HAS_UIKIT # import -# import # import #endif @@ -21,7 +18,7 @@ @interface SentryAppStateManager () @property (nonatomic, strong) SentryCrashWrapper *crashWrapper; @property (nonatomic, strong) SentryFileManager *fileManager; @property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueue; -@property (nonatomic, strong) SentryNSNotificationCenterWrapper *notificationCenterWrapper; +@property (nonatomic, strong) id notificationCenterWrapper; @property (nonatomic) NSInteger startCount; @end @@ -32,7 +29,7 @@ - (instancetype)initWithOptions:(SentryOptions *)options crashWrapper:(SentryCrashWrapper *)crashWrapper fileManager:(SentryFileManager *)fileManager dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper - notificationCenterWrapper:(SentryNSNotificationCenterWrapper *)notificationCenterWrapper + notificationCenterWrapper:(id)notificationCenterWrapper { if (self = [super init]) { self.options = options; @@ -52,19 +49,23 @@ - (void)start if (self.startCount == 0) { [self.notificationCenterWrapper addObserver:self selector:@selector(didBecomeActive) - name:SentryDidBecomeActiveNotification]; + name:SentryDidBecomeActiveNotification + object:nil]; [self.notificationCenterWrapper addObserver:self selector:@selector(didBecomeActive) - name:SentryHybridSdkDidBecomeActiveNotificationName]; + name:SentryHybridSdkDidBecomeActiveNotificationName + object:nil]; [self.notificationCenterWrapper addObserver:self selector:@selector(willResignActive) - name:SentryWillResignActiveNotification]; + name:SentryWillResignActiveNotification + object:nil]; [self.notificationCenterWrapper addObserver:self selector:@selector(willTerminate) - name:SentryWillTerminateNotification]; + name:SentryWillTerminateNotification + object:nil]; [self storeCurrentAppState]; } @@ -96,16 +97,22 @@ - (void)stopWithForce:(BOOL)forceStop if (self.startCount == 0) { // Remove the observers with the most specific detail possible, see // https://developer.apple.com/documentation/foundation/nsnotificationcenter/1413994-removeobserver - [self.notificationCenterWrapper removeObserver:self name:SentryDidBecomeActiveNotification]; + [self.notificationCenterWrapper removeObserver:self + name:SentryDidBecomeActiveNotification + object:nil]; [self.notificationCenterWrapper removeObserver:self - name:SentryHybridSdkDidBecomeActiveNotificationName]; + name:SentryHybridSdkDidBecomeActiveNotificationName + object:nil]; [self.notificationCenterWrapper removeObserver:self - name:SentryWillResignActiveNotification]; + name:SentryWillResignActiveNotification + object:nil]; - [self.notificationCenterWrapper removeObserver:self name:SentryWillTerminateNotification]; + [self.notificationCenterWrapper removeObserver:self + name:SentryWillTerminateNotification + object:nil]; } } @@ -113,7 +120,7 @@ - (void)dealloc { // In dealloc it's safe to unsubscribe for all, see // https://developer.apple.com/documentation/foundation/nsnotificationcenter/1413994-removeobserver - [self.notificationCenterWrapper removeObserver:self]; + [self.notificationCenterWrapper removeObserver:self name:nil object:nil]; } /** @@ -179,7 +186,7 @@ - (SentryAppState *)buildCurrentAppState .sysctlWrapper.systemBootTimestamp]; } -- (SentryAppState *)loadPreviousAppState +- (nullable SentryAppState *)loadPreviousAppState { return [self.fileManager readPreviousAppState]; } diff --git a/Sources/Sentry/NSArray+SentrySanitize.m b/Sources/Sentry/SentryArray.m similarity index 66% rename from Sources/Sentry/NSArray+SentrySanitize.m rename to Sources/Sentry/SentryArray.m index 85ee3c9fcdb..300fd19cb0b 100644 --- a/Sources/Sentry/NSArray+SentrySanitize.m +++ b/Sources/Sentry/SentryArray.m @@ -1,5 +1,6 @@ -#import "NSArray+SentrySanitize.h" +#import "SentryArray.h" #import "SentryDateUtils.h" +#import "SentryInternalDefines.h" #import "SentryNSDictionarySanitize.h" @implementation SentryArray @@ -13,7 +14,13 @@ + (NSArray *)sanitizeArray:(NSArray *)array; } else if ([rawValue isKindOfClass:NSNumber.class]) { [result addObject:rawValue]; } else if ([rawValue isKindOfClass:NSDictionary.class]) { - [result addObject:sentry_sanitize((NSDictionary *)rawValue)]; + NSDictionary *_Nullable sanitizedDict = sentry_sanitize((NSDictionary *)rawValue); + if (sanitizedDict == nil) { + // Adding `nil` to an array is not allowed in Objective-C and raises an + // `NSInvalidArgumentException`. + continue; + } + [result addObject:SENTRY_UNWRAP_NULLABLE(NSDictionary, sanitizedDict)]; } else if ([rawValue isKindOfClass:NSArray.class]) { [result addObject:[SentryArray sanitizeArray:rawValue]]; } else if ([rawValue isKindOfClass:NSDate.class]) { diff --git a/Sources/Sentry/SentryAsyncLog.m b/Sources/Sentry/SentryAsyncLog.m index 178db933641..5a48cde8dbe 100644 --- a/Sources/Sentry/SentryAsyncLog.m +++ b/Sources/Sentry/SentryAsyncLog.m @@ -2,6 +2,7 @@ #import "SentryAsyncSafeLog.h" #import "SentryFileManager.h" #import "SentryInternalCDefines.h" +#import "SentryInternalDefines.h" #import "SentryLogC.h" NS_ASSUME_NONNULL_BEGIN @@ -10,11 +11,18 @@ @implementation SentryAsyncLogWrapper + (void)initializeAsyncLogFile { + NSString *_Nullable nullableStaticCachesPath = sentryStaticCachesPath(); + if (nullableStaticCachesPath == nil) { + SENTRY_LOG_ERROR(@"Failed to get static caches path for async log file."); + return; + } + NSString *_Nonnull cachesPath = SENTRY_UNWRAP_NULLABLE(NSString, nullableStaticCachesPath); + const char *asyncLogPath = - [[sentryStaticCachesPath() stringByAppendingPathComponent:@"async.log"] UTF8String]; + [[cachesPath stringByAppendingPathComponent:@"async.log"] UTF8String]; - NSError *error; - if (!createDirectoryIfNotExists(sentryStaticCachesPath(), &error)) { + NSError *_Nullable error; + if (!createDirectoryIfNotExists(cachesPath, &error)) { SENTRY_LOG_ERROR(@"Failed to initialize directory for async log file: %@", error); return; } diff --git a/Sources/Sentry/SentryAutoBreadcrumbTrackingIntegration.m b/Sources/Sentry/SentryAutoBreadcrumbTrackingIntegration.m index 8c194a504d0..1909d0fb901 100644 --- a/Sources/Sentry/SentryAutoBreadcrumbTrackingIntegration.m +++ b/Sources/Sentry/SentryAutoBreadcrumbTrackingIntegration.m @@ -4,7 +4,7 @@ #import "SentryFileManager.h" #import "SentryLogC.h" #import "SentryOptions.h" -#import "SentrySDK.h" +#import "SentrySDKInternal.h" #import "SentrySystemEventBreadcrumbs.h" NS_ASSUME_NONNULL_BEGIN @@ -88,7 +88,7 @@ - (void)uninstall - (void)addBreadcrumb:(SentryBreadcrumb *)crumb { - [SentrySDK addBreadcrumb:crumb]; + [SentrySDKInternal addBreadcrumb:crumb]; } @end diff --git a/Sources/Sentry/SentryAutoSessionTrackingIntegration.m b/Sources/Sentry/SentryAutoSessionTrackingIntegration.m index a3784c1662d..1f80decd3b4 100644 --- a/Sources/Sentry/SentryAutoSessionTrackingIntegration.m +++ b/Sources/Sentry/SentryAutoSessionTrackingIntegration.m @@ -2,7 +2,7 @@ #import "SentryDependencyContainer.h" #import "SentryLogC.h" #import "SentryOptions.h" -#import "SentrySDK.h" +#import "SentrySDKInternal.h" #import "SentrySessionTracker.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/Sentry/SentryBaggage.m b/Sources/Sentry/SentryBaggage.m index b7c6a936a76..f63ce92672e 100644 --- a/Sources/Sentry/SentryBaggage.m +++ b/Sources/Sentry/SentryBaggage.m @@ -15,7 +15,9 @@ - (instancetype)initWithTraceId:(SentryId *)traceId releaseName:(nullable NSString *)releaseName environment:(nullable NSString *)environment transaction:(nullable NSString *)transaction +#if !SDK_V9 userSegment:(nullable NSString *)userSegment +#endif sampleRate:(nullable NSString *)sampleRate sampled:(nullable NSString *)sampled replayId:(nullable NSString *)replayId @@ -25,7 +27,9 @@ - (instancetype)initWithTraceId:(SentryId *)traceId releaseName:releaseName environment:environment transaction:transaction +#if !SDK_V9 userSegment:userSegment +#endif sampleRate:sampleRate sampleRand:nil sampled:sampled @@ -37,7 +41,9 @@ - (instancetype)initWithTraceId:(SentryId *)traceId releaseName:(nullable NSString *)releaseName environment:(nullable NSString *)environment transaction:(nullable NSString *)transaction +#if !SDK_V9 userSegment:(nullable NSString *)userSegment +#endif sampleRate:(nullable NSString *)sampleRate sampleRand:(nullable NSString *)sampleRand sampled:(nullable NSString *)sampled @@ -50,7 +56,9 @@ - (instancetype)initWithTraceId:(SentryId *)traceId _releaseName = releaseName; _environment = environment; _transaction = transaction; +#if !SDK_V9 _userSegment = userSegment; +#endif _sampleRate = sampleRate; _sampleRand = sampleRand; _sampled = sampled; @@ -80,9 +88,11 @@ - (NSString *)toHTTPHeaderWithOriginalBaggage:(NSDictionary *_Nullable)originalB [information setValue:_transaction forKey:@"sentry-transaction"]; } +#if !SDK_V9 if (_userSegment != nil) { [information setValue:_userSegment forKey:@"sentry-user_segment"]; } +#endif if (_sampleRand != nil) { [information setValue:_sampleRand forKey:@"sentry-sample_rand"]; diff --git a/Sources/Sentry/SentryBaseIntegration.m b/Sources/Sentry/SentryBaseIntegration.m index ea29340b3f8..3b6d7fa7d5f 100644 --- a/Sources/Sentry/SentryBaseIntegration.m +++ b/Sources/Sentry/SentryBaseIntegration.m @@ -1,5 +1,4 @@ #import "SentryBaseIntegration.h" -#import "SentryCrashWrapper.h" #import "SentryLogC.h" #import "SentrySwift.h" #import @@ -78,10 +77,17 @@ - (BOOL)shouldBeEnabledWithOptions:(SentryOptions *)options if (integrationOptions & kIntegrationOptionEnableAppHangTracking) { #if SENTRY_HAS_UIKIT +# if SDK_V9 + if (!options.enableAppHangTracking) { + [self logWithOptionName:@"enableAppHangTracking"]; + return NO; + } +# else if (!options.enableAppHangTracking && !options.enableAppHangTrackingV2) { [self logWithOptionName:@"enableAppHangTracking && enableAppHangTrackingV2"]; return NO; } +# endif #else if (!options.enableAppHangTracking) { [self logWithOptionName:@"enableAppHangTracking"]; diff --git a/Sources/Sentry/SentryBinaryImageCache.m b/Sources/Sentry/SentryBinaryImageCache.m deleted file mode 100644 index 9d81d27efe0..00000000000 --- a/Sources/Sentry/SentryBinaryImageCache.m +++ /dev/null @@ -1,181 +0,0 @@ -#import "SentryBinaryImageCache.h" -#import "SentryCrashBinaryImageCache.h" -#include "SentryCrashUUIDConversion.h" -#import "SentryDependencyContainer.h" -#import "SentryInAppLogic.h" -#import "SentryLogC.h" - -NS_ASSUME_NONNULL_BEGIN - -static void binaryImageWasAdded(const SentryCrashBinaryImage *image); - -static void binaryImageWasRemoved(const SentryCrashBinaryImage *image); - -@implementation SentryBinaryImageInfo -@end - -@interface SentryBinaryImageCache () -@property (nonatomic, strong, nullable) NSMutableArray *cache; -- (void)binaryImageAdded:(const SentryCrashBinaryImage *)image; -- (void)binaryImageRemoved:(const SentryCrashBinaryImage *)image; -@end - -@implementation SentryBinaryImageCache - -- (void)start -{ - @synchronized(self) { - _cache = [NSMutableArray array]; - sentrycrashbic_registerAddedCallback(&binaryImageWasAdded); - sentrycrashbic_registerRemovedCallback(&binaryImageWasRemoved); - } -} - -- (void)stop -{ - @synchronized(self) { - sentrycrashbic_registerAddedCallback(NULL); - sentrycrashbic_registerRemovedCallback(NULL); - _cache = nil; - } -} - -- (void)binaryImageAdded:(const SentryCrashBinaryImage *)image -{ - if (image == NULL) { - SENTRY_LOG_WARN(@"The image is NULL. Can't add NULL to cache."); - return; - } - - if (image->name == NULL) { - SENTRY_LOG_WARN(@"The image name was NULL. Can't add image to cache."); - return; - } - - NSString *imageName = [NSString stringWithCString:image->name encoding:NSUTF8StringEncoding]; - - if (imageName == nil) { - SENTRY_LOG_WARN(@"Couldn't convert the cString image name to an NSString. This could be " - @"due to a different encoding than NSUTF8StringEncoding of the cString.."); - return; - } - - SentryBinaryImageInfo *newImage = [[SentryBinaryImageInfo alloc] init]; - newImage.name = imageName; - newImage.UUID = [SentryBinaryImageCache convertUUID:image->uuid]; - newImage.address = image->address; - newImage.vmAddress = image->vmAddress; - newImage.size = image->size; - - @synchronized(self) { - NSUInteger left = 0; - NSUInteger right = _cache.count; - - while (left < right) { - NSUInteger mid = (left + right) / 2; - SentryBinaryImageInfo *compareImage = _cache[mid]; - if (newImage.address < compareImage.address) { - right = mid; - } else { - left = mid + 1; - } - } - - [_cache insertObject:newImage atIndex:left]; - } -} - -+ (NSString *_Nullable)convertUUID:(const unsigned char *const)value -{ - if (nil == value) { - return nil; - } - - char uuidBuffer[37]; - sentrycrashdl_convertBinaryImageUUID(value, uuidBuffer); - return [[NSString alloc] initWithCString:uuidBuffer encoding:NSASCIIStringEncoding]; -} - -- (void)binaryImageRemoved:(const SentryCrashBinaryImage *)image -{ - if (image == NULL) { - SENTRY_LOG_WARN(@"The image is NULL. Can't remove it from the cache."); - return; - } - - @synchronized(self) { - NSInteger index = [self indexOfImage:image->address]; - if (index >= 0) { - [_cache removeObjectAtIndex:index]; - } - } -} - -- (nullable SentryBinaryImageInfo *)imageByAddress:(const uint64_t)address; -{ - @synchronized(self) { - NSInteger index = [self indexOfImage:address]; - return index >= 0 ? _cache[index] : nil; - } -} - -- (NSInteger)indexOfImage:(uint64_t)address -{ - if (_cache == nil) - return -1; - - NSInteger left = 0; - NSInteger right = _cache.count - 1; - - while (left <= right) { - NSInteger mid = (left + right) / 2; - SentryBinaryImageInfo *image = _cache[mid]; - - if (address >= image.address && address < (image.address + image.size)) { - return mid; - } else if (address < image.address) { - right = mid - 1; - } else { - left = mid + 1; - } - } - - return -1; // Address not found -} - -- (NSSet *)imagePathsForInAppInclude:(NSString *)inAppInclude -{ - NSMutableSet *imagePaths = [NSMutableSet new]; - - @synchronized(self) { - for (SentryBinaryImageInfo *info in _cache) { - if ([SentryInAppLogic isImageNameInApp:info.name inAppInclude:inAppInclude]) { - [imagePaths addObject:info.name]; - } - } - } - return imagePaths; -} - -- (NSArray *)getAllBinaryImages -{ - @synchronized(self) { - return _cache.copy; - } -} - -@end - -static void -binaryImageWasAdded(const SentryCrashBinaryImage *image) -{ - [SentryDependencyContainer.sharedInstance.binaryImageCache binaryImageAdded:image]; -} - -static void -binaryImageWasRemoved(const SentryCrashBinaryImage *image) -{ - [SentryDependencyContainer.sharedInstance.binaryImageCache binaryImageRemoved:image]; -} - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryBreadcrumb.m b/Sources/Sentry/SentryBreadcrumb.m index a0c5d64fd4a..bdcf42b208a 100644 --- a/Sources/Sentry/SentryBreadcrumb.m +++ b/Sources/Sentry/SentryBreadcrumb.m @@ -1,6 +1,7 @@ #import "SentryBreadcrumb.h" #import "SentryBreadcrumb+Private.h" #import "SentryDateUtils.h" +#import "SentryInternalDefines.h" #import "SentryLevelMapper.h" #import "SentryNSDictionarySanitize.h" #import "SentrySwift.h" @@ -59,7 +60,11 @@ - (instancetype)init NSMutableDictionary *serializedData = [NSMutableDictionary new]; [serializedData setValue:nameForSentryLevel(self.level) forKey:@"level"]; - [serializedData setValue:sentry_toIso8601String(self.timestamp) forKey:@"timestamp"]; + if (self.timestamp != nil) { + [serializedData + setValue:sentry_toIso8601String(SENTRY_UNWRAP_NULLABLE(NSDate, self.timestamp)) + forKey:@"timestamp"]; + } [serializedData setValue:self.category forKey:@"category"]; [serializedData setValue:self.type forKey:@"type"]; [serializedData setValue:self.origin forKey:@"origin"]; @@ -75,7 +80,7 @@ - (BOOL)isEqual:(id _Nullable)other if (!other || ![[other class] isEqual:[self class]]) return NO; - return [self isEqualToBreadcrumb:other]; + return [self isEqualToBreadcrumb:SENTRY_UNWRAP_NULLABLE(SentryBreadcrumb, other)]; } - (BOOL)isEqualToBreadcrumb:(SentryBreadcrumb *)breadcrumb @@ -90,15 +95,19 @@ - (BOOL)isEqualToBreadcrumb:(SentryBreadcrumb *)breadcrumb && ![self.category isEqualToString:breadcrumb.category]) return NO; if (self.timestamp != breadcrumb.timestamp - && ![self.timestamp isEqualToDate:breadcrumb.timestamp]) + && ![self.timestamp isEqualToDate:SENTRY_UNWRAP_NULLABLE(NSDate, breadcrumb.timestamp)]) return NO; - if (self.type != breadcrumb.type && ![self.type isEqualToString:breadcrumb.type]) + if (self.type != breadcrumb.type + && ![self.type isEqualToString:SENTRY_UNWRAP_NULLABLE(NSString, breadcrumb.type)]) return NO; - if (self.origin != breadcrumb.origin && ![self.origin isEqualToString:breadcrumb.origin]) + if (self.origin != breadcrumb.origin + && ![self.origin isEqualToString:SENTRY_UNWRAP_NULLABLE(NSString, breadcrumb.origin)]) return NO; - if (self.message != breadcrumb.message && ![self.message isEqualToString:breadcrumb.message]) + if (self.message != breadcrumb.message + && ![self.message isEqualToString:SENTRY_UNWRAP_NULLABLE(NSString, breadcrumb.message)]) return NO; - if (self.data != breadcrumb.data && ![self.data isEqualToDictionary:breadcrumb.data]) + if (self.data != breadcrumb.data + && ![self.data isEqualToDictionary:SENTRY_UNWRAP_NULLABLE(NSDictionary, breadcrumb.data)]) return NO; return YES; } diff --git a/Sources/Sentry/SentryBreadcrumbTracker.m b/Sources/Sentry/SentryBreadcrumbTracker.m index 09f0e1677fc..872aefaadc9 100644 --- a/Sources/Sentry/SentryBreadcrumbTracker.m +++ b/Sources/Sentry/SentryBreadcrumbTracker.m @@ -5,6 +5,7 @@ #import "SentryDefines.h" #import "SentryDependencyContainer.h" #import "SentryHub.h" +#import "SentryInternalDefines.h" #import "SentryLogC.h" #import "SentryReachability.h" #import "SentryScope.h" @@ -220,9 +221,10 @@ - (void)swizzleSendAction NSDictionary *data = nil; for (UITouch *touch in event.allTouches) { - if (touch.phase == UITouchPhaseCancelled || touch.phase == UITouchPhaseEnded) { + if (touch.view != nil + && (touch.phase == UITouchPhaseCancelled || touch.phase == UITouchPhaseEnded)) { data = [SentryBreadcrumbTracker - extractDataFromView:touch.view + extractDataFromView:SENTRY_UNWRAP_NULLABLE_VALUE(id, touch.view) withAccessibilityIdentifier:self->_reportAccessibilityIdentifier]; } } @@ -316,12 +318,14 @@ + (NSDictionary *)fetchInfoAboutViewController:(UIViewController *)controller if (controller.presentingViewController != nil) { info[@"presentingViewController"] = - [SwiftDescriptor getViewControllerClassName:controller.presentingViewController]; + [SwiftDescriptor getViewControllerClassName:SENTRY_UNWRAP_NULLABLE(UIViewController, + controller.presentingViewController)]; } if (controller.parentViewController != nil) { info[@"parentViewController"] = - [SwiftDescriptor getViewControllerClassName:controller.parentViewController]; + [SwiftDescriptor getViewControllerClassName:SENTRY_UNWRAP_NULLABLE(UIViewController, + controller.parentViewController)]; } if (controller.view.window != nil) { diff --git a/Sources/Sentry/SentryBuildAppStartSpans.m b/Sources/Sentry/SentryBuildAppStartSpans.m index 473b0991512..e02204b40cc 100644 --- a/Sources/Sentry/SentryBuildAppStartSpans.m +++ b/Sources/Sentry/SentryBuildAppStartSpans.m @@ -55,40 +55,41 @@ NSDate *appStartEndTimestamp = [appStartMeasurement.appStartTimestamp dateByAddingTimeInterval:appStartMeasurement.duration]; - SentrySpan *appStartSpan = sentryBuildAppStartSpan(tracer, tracer.spanId, operation, type); + SentrySpan *appStartSpan + = (SentrySpan *)sentryBuildAppStartSpan(tracer, tracer.spanId, operation, type); [appStartSpan setStartTimestamp:appStartMeasurement.appStartTimestamp]; [appStartSpan setTimestamp:appStartEndTimestamp]; [appStartSpans addObject:appStartSpan]; if (!appStartMeasurement.isPreWarmed) { - SentrySpan *premainSpan - = sentryBuildAppStartSpan(tracer, appStartSpan.spanId, operation, @"Pre Runtime Init"); + SentrySpan *premainSpan = (SentrySpan *)sentryBuildAppStartSpan( + tracer, appStartSpan.spanId, operation, @"Pre Runtime Init"); [premainSpan setStartTimestamp:appStartMeasurement.appStartTimestamp]; [premainSpan setTimestamp:appStartMeasurement.runtimeInitTimestamp]; [appStartSpans addObject:premainSpan]; - SentrySpan *runtimeInitSpan = sentryBuildAppStartSpan( + SentrySpan *runtimeInitSpan = (SentrySpan *)sentryBuildAppStartSpan( tracer, appStartSpan.spanId, operation, @"Runtime Init to Pre Main Initializers"); [runtimeInitSpan setStartTimestamp:appStartMeasurement.runtimeInitTimestamp]; [runtimeInitSpan setTimestamp:appStartMeasurement.moduleInitializationTimestamp]; [appStartSpans addObject:runtimeInitSpan]; } - SentrySpan *appInitSpan - = sentryBuildAppStartSpan(tracer, appStartSpan.spanId, operation, @"UIKit Init"); + SentrySpan *appInitSpan = (SentrySpan *)sentryBuildAppStartSpan( + tracer, appStartSpan.spanId, operation, @"UIKit Init"); [appInitSpan setStartTimestamp:appStartMeasurement.moduleInitializationTimestamp]; [appInitSpan setTimestamp:appStartMeasurement.sdkStartTimestamp]; [appStartSpans addObject:appInitSpan]; - SentrySpan *didFinishLaunching - = sentryBuildAppStartSpan(tracer, appStartSpan.spanId, operation, @"Application Init"); + SentrySpan *didFinishLaunching = (SentrySpan *)sentryBuildAppStartSpan( + tracer, appStartSpan.spanId, operation, @"Application Init"); [didFinishLaunching setStartTimestamp:appStartMeasurement.sdkStartTimestamp]; [didFinishLaunching setTimestamp:appStartMeasurement.didFinishLaunchingTimestamp]; [appStartSpans addObject:didFinishLaunching]; - SentrySpan *frameRenderSpan - = sentryBuildAppStartSpan(tracer, appStartSpan.spanId, operation, @"Initial Frame Render"); + SentrySpan *frameRenderSpan = (SentrySpan *)sentryBuildAppStartSpan( + tracer, appStartSpan.spanId, operation, @"Initial Frame Render"); [frameRenderSpan setStartTimestamp:appStartMeasurement.didFinishLaunchingTimestamp]; [frameRenderSpan setTimestamp:appStartEndTimestamp]; [appStartSpans addObject:frameRenderSpan]; diff --git a/Sources/Sentry/SentryClient.m b/Sources/Sentry/SentryClient.m index 120f67fd108..79876a2ef53 100644 --- a/Sources/Sentry/SentryClient.m +++ b/Sources/Sentry/SentryClient.m @@ -8,8 +8,6 @@ #import "SentryDebugImageProvider+HybridSDKs.h" #import "SentryDependencyContainer.h" #import "SentryDsn.h" -#import "SentryEnvelope+Private.h" -#import "SentryEnvelopeItemType.h" #import "SentryEvent+Private.h" #import "SentryException.h" #import "SentryExtraContextProvider.h" @@ -17,8 +15,8 @@ #import "SentryGlobalEventProcessor.h" #import "SentryHub+Private.h" #import "SentryHub.h" -#import "SentryInAppLogic.h" #import "SentryInstallation.h" +#import "SentryInternalDefines.h" #import "SentryLogC.h" #import "SentryMechanism.h" #import "SentryMechanismMeta.h" @@ -29,12 +27,10 @@ #import "SentryNSError.h" #import "SentryOptions+Private.h" #import "SentryPropagationContext.h" -#import "SentryRandom.h" #import "SentrySDK+Private.h" #import "SentryScope+Private.h" -#import "SentrySdkInfo.h" +#import "SentryScope+PrivateSwift.h" #import "SentrySerialization.h" -#import "SentrySession.h" #import "SentryStacktraceBuilder.h" #import "SentrySwift.h" #import "SentryThreadInspector.h" @@ -44,7 +40,6 @@ #import "SentryTransport.h" #import "SentryTransportAdapter.h" #import "SentryTransportFactory.h" -#import "SentryUIApplication.h" #import "SentryUseNSExceptionCallstackWrapper.h" #import "SentryUser.h" #import "SentryWatchdogTerminationTracker.h" @@ -59,7 +54,7 @@ @interface SentryClient () @property (nonatomic, strong) SentryTransportAdapter *transportAdapter; @property (nonatomic, strong) SentryDebugImageProvider *debugImageProvider; -@property (nonatomic, strong) id random; +@property (nonatomic, strong) id random; @property (nonatomic, strong) NSLocale *locale; @property (nonatomic, strong) NSTimeZone *timezone; @@ -72,17 +67,19 @@ @implementation SentryClient - (_Nullable instancetype)initWithOptions:(SentryOptions *)options { return [self initWithOptions:options - dispatchQueue:[[SentryDispatchQueueWrapper alloc] init] + dateProvider:SentryDependencyContainer.sharedInstance.dateProvider + dispatchQueue:SentryDependencyContainer.sharedInstance.dispatchQueueWrapper deleteOldEnvelopeItems:YES]; } -/** Internal constructor for testing purposes. */ - (nullable instancetype)initWithOptions:(SentryOptions *)options + dateProvider:(id)dateProvider dispatchQueue:(SentryDispatchQueueWrapper *)dispatchQueue deleteOldEnvelopeItems:(BOOL)deleteOldEnvelopeItems { NSError *error; SentryFileManager *fileManager = [[SentryFileManager alloc] initWithOptions:options + dateProvider:dateProvider dispatchQueueWrapper:dispatchQueue error:&error]; if (error != nil) { @@ -141,7 +138,7 @@ - (instancetype)initWithOptions:(SentryOptions *)options deleteOldEnvelopeItems:(BOOL)deleteOldEnvelopeItems threadInspector:(SentryThreadInspector *)threadInspector debugImageProvider:(SentryDebugImageProvider *)debugImageProvider - random:(id)random + random:(id)random locale:(NSLocale *)locale timezone:(NSTimeZone *)timezone { @@ -426,13 +423,19 @@ - (nullable SentryTraceContext *)getTraceStateWithEvent:(SentryEvent *)event } if (event.error || event.exceptions.count > 0) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#if !SDK_V9 + NSString *segment = nil; +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" + segment = scope.userObject.segment; +# pragma clang diagnostic pop +#endif return [[SentryTraceContext alloc] initWithTraceId:scope.propagationContext.traceId options:self.options - userSegment:scope.userObject.segment +#if !SDK_V9 + userSegment:segment +#endif replayId:scope.replayId]; -#pragma clang diagnostic pop } return nil; @@ -520,8 +523,11 @@ - (void)captureSession:(SentrySession *)session } SentryEnvelopeItem *item = [[SentryEnvelopeItem alloc] initWithSession:session]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" SentryEnvelope *envelope = [[SentryEnvelope alloc] initWithHeader:[SentryEnvelopeHeader empty] singleItem:item]; +#pragma clang diagnostic pop [self captureEnvelope:envelope]; } @@ -534,8 +540,16 @@ - (void)captureReplayEvent:(SentryReplayEvent *)replayEvent withScope:scope alwaysAttachStacktrace:NO]; + if (replayEvent == nil) { + SENTRY_LOG_DEBUG(@"The replay event was filtered out in prepare event. " + @"The replay was discarded."); + return; + } + + // Only check the type of the returned event, as the instance could be changed in the event + // preprocessor and before-send handlers. if (![replayEvent isKindOfClass:SentryReplayEvent.class]) { - SENTRY_LOG_DEBUG(@"The event preprocessor didn't update the replay event in place. The " + SENTRY_LOG_ERROR(@"The event preprocessor didn't update the replay event in place. The " @"replay was discarded."); return; } @@ -546,15 +560,23 @@ - (void)captureReplayEvent:(SentryReplayEvent *)replayEvent video:videoURL]; if (videoEnvelopeItem == nil) { - SENTRY_LOG_DEBUG(@"The Session Replay segment will not be sent to Sentry because an " + SENTRY_LOG_ERROR(@"The Session Replay segment will not be sent to Sentry because an " @"Envelope Item could not be created."); + // Record a counted lost event in case preparing the event (e.g. encoding the event) failed. + // This is used to determine if replay events are missing due to an error in the SDK. + [self recordLostEvent:kSentryDataCategoryReplay + reason:kSentryDiscardReasonInsufficientData + quantity:1]; return; } // Hybrid SDKs may override the sdk info for a replay Event, // the same SDK should be used for the envelope header. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" SentrySdkInfo *sdkInfo = replayEvent.sdk ? [[SentrySdkInfo alloc] initWithDict:replayEvent.sdk] : [SentrySdkInfo global]; +#pragma clang diagnotsic pop SentryEnvelopeHeader *envelopeHeader = [[SentryEnvelopeHeader alloc] initWithId:replayEvent.eventId sdkInfo:sdkInfo @@ -593,6 +615,17 @@ - (void)captureUserFeedback:(SentryUserFeedback *)userFeedback #endif // !SDK_V9 - (void)captureFeedback:(SentryFeedback *)feedback withScope:(SentryScope *)scope +{ + [self captureSerializedFeedback:[feedback serialize] + withEventId:feedback.eventId.sentryIdString + attachments:[feedback attachmentsForEnvelope] + scope:scope]; +} + +- (void)captureSerializedFeedback:(NSDictionary *)serializedFeedback + withEventId:(NSString *)feedbackEventId + attachments:(NSArray *)feedbackAttachments + scope:(SentryScope *)scope { if ([self isDisabled]) { [self logDisabledMessage]; @@ -600,10 +633,8 @@ - (void)captureFeedback:(SentryFeedback *)feedback withScope:(SentryScope *)scop } SentryEvent *feedbackEvent = [[SentryEvent alloc] init]; - feedbackEvent.eventId = feedback.eventId; - feedbackEvent.type = SentryEnvelopeItemTypeFeedback; - - NSDictionary *serializedFeedback = [feedback serialize]; + feedbackEvent.eventId = [[SentryId alloc] initWithUUIDString:feedbackEventId]; + feedbackEvent.type = SentryEnvelopeItemTypes.feedback; NSUInteger optionalItems = (scope.span == nil ? 0 : 1) + (scope.replayId == nil ? 0 : 1); NSMutableDictionary *context = [NSMutableDictionary dictionaryWithCapacity:1 + optionalItems]; @@ -623,7 +654,7 @@ - (void)captureFeedback:(SentryFeedback *)feedback withScope:(SentryScope *)scop SentryTraceContext *traceContext = [self getTraceStateWithEvent:preparedEvent withScope:scope]; NSArray *attachments = [[self processAttachmentsForEvent:preparedEvent attachments:scope.attachments] - arrayByAddingObjectsFromArray:[feedback attachmentsForEnvelope]]; + arrayByAddingObjectsFromArray:feedbackAttachments]; [self.transportAdapter sendEvent:preparedEvent traceContext:traceContext @@ -686,14 +717,15 @@ - (SentryEvent *_Nullable)prepareEvent:(SentryEvent *)event } BOOL eventIsNotATransaction - = event.type == nil || ![event.type isEqualToString:SentryEnvelopeItemTypeTransaction]; + = event.type == nil || ![event.type isEqualToString:SentryEnvelopeItemTypes.transaction]; BOOL eventIsNotReplay - = event.type == nil || ![event.type isEqualToString:SentryEnvelopeItemTypeReplayVideo]; + = event.type == nil || ![event.type isEqualToString:SentryEnvelopeItemTypes.replayVideo]; BOOL eventIsNotUserFeedback - = event.type == nil || ![event.type isEqualToString:SentryEnvelopeItemTypeFeedback]; + = event.type == nil || ![event.type isEqualToString:SentryEnvelopeItemTypes.feedback]; // Transactions and replays have their own sampleRate - if (eventIsNotATransaction && eventIsNotReplay && [self isSampled:self.options.sampleRate]) { + if (eventIsNotATransaction && eventIsNotReplay && eventIsNotUserFeedback && + [self isSampled:self.options.sampleRate]) { SENTRY_LOG_DEBUG(@"Event got sampled, will not send the event"); [self recordLostEvent:kSentryDataCategoryError reason:kSentryDiscardReasonSampleRate]; return nil; @@ -752,7 +784,7 @@ - (SentryEvent *_Nullable)prepareEvent:(SentryEvent *)event context[@"app"] = app; UIApplicationState appState = - [SentryDependencyContainer sharedInstance].application.applicationState; + [SentryDependencyContainer sharedInstance].threadsafeApplication.applicationState; BOOL inForeground = appState == UIApplicationStateActive; app[@"in_foreground"] = @(inForeground); event.context = context; @@ -794,17 +826,8 @@ - (SentryEvent *_Nullable)prepareEvent:(SentryEvent *)event // Need to do this after the scope is applied cause this sets the user if there is any [self setUserIdIfNoUserSet:event]; - // User can't be nil as setUserIdIfNoUserSet sets it. - if (self.options.sendDefaultPii && nil == event.user.ipAddress) { - // Let Sentry infer the IP address from the connection. - // Due to backward compatibility concerns, Sentry servers set the IP address to {{auto}} out - // of the box for only Cocoa and JavaScript, which makes this toggle currently somewhat - // useless. Still, we keep it for future compatibility reasons. - event.user.ipAddress = @"{{auto}}"; - } - BOOL eventIsATransaction - = event.type != nil && [event.type isEqualToString:SentryEnvelopeItemTypeTransaction]; + = event.type != nil && [event.type isEqualToString:SentryEnvelopeItemTypes.transaction]; BOOL eventIsATransactionClass = eventIsATransaction && [event isKindOfClass:[SentryTransaction class]]; @@ -816,22 +839,6 @@ - (SentryEvent *_Nullable)prepareEvent:(SentryEvent *)event currentSpanCount = 0; } - event = [self callEventProcessors:event]; - if (event == nil) { - [self recordLost:eventIsNotATransaction reason:kSentryDiscardReasonEventProcessor]; - if (eventIsATransaction) { - // We dropped the whole transaction, the dropped count includes all child spans + 1 root - // span - [self recordLostSpanWithReason:kSentryDiscardReasonEventProcessor - quantity:currentSpanCount + 1]; - } - } else { - if (eventIsATransactionClass) { - [self recordPartiallyDroppedSpans:(SentryTransaction *)event - withReason:kSentryDiscardReasonEventProcessor - withCurrentSpanCount:¤tSpanCount]; - } - } if (event != nil && eventIsATransaction && self.options.beforeSendSpan != nil) { SentryTransaction *transaction = (SentryTransaction *)event; NSMutableArray> *processedSpans = [NSMutableArray array]; @@ -850,7 +857,7 @@ - (SentryEvent *_Nullable)prepareEvent:(SentryEvent *)event } } - if (event != nil && nil != self.options.beforeSend) { + if (eventIsNotUserFeedback && event != nil && nil != self.options.beforeSend) { event = self.options.beforeSend(event); if (event == nil) { [self recordLost:eventIsNotATransaction reason:kSentryDiscardReasonBeforeSend]; @@ -869,11 +876,32 @@ - (SentryEvent *_Nullable)prepareEvent:(SentryEvent *)event } } + if (event != nil) { + // if the event is dropped by beforeSend we should not execute event processors as they + // might trigger e.g. unnecessary replay capture + event = [self callEventProcessors:event]; + if (event == nil) { + [self recordLost:eventIsNotATransaction reason:kSentryDiscardReasonEventProcessor]; + if (eventIsATransaction) { + // We dropped the whole transaction, the dropped count includes all child spans + 1 + // root span + [self recordLostSpanWithReason:kSentryDiscardReasonEventProcessor + quantity:currentSpanCount + 1]; + } + } else { + if (eventIsATransactionClass) { + [self recordPartiallyDroppedSpans:(SentryTransaction *)event + withReason:kSentryDiscardReasonEventProcessor + withCurrentSpanCount:¤tSpanCount]; + } + } + } + if (event != nil && isFatalEvent && nil != self.options.onCrashedLastRun - && !SentrySDK.crashedLastRunCalled) { + && !SentrySDKInternal.crashedLastRunCalled) { // We only want to call the callback once. It can occur that multiple crash events are // about to be sent. - SentrySDK.crashedLastRunCalled = YES; + SentrySDKInternal.crashedLastRunCalled = YES; self.options.onCrashedLastRun(event); } @@ -893,7 +921,7 @@ - (void)recordPartiallyDroppedSpans:(SentryTransaction *)transaction *currentSpanCount = spanCountAfter; } -- (BOOL)isSampled:(NSNumber *)sampleRate +- (BOOL)isSampled:(NSNumber *_Nullable)sampleRate { if (sampleRate == nil) { return NO; @@ -1010,9 +1038,9 @@ - (void)applyExtraDeviceContextToEvent:(SentryEvent *)event NSDictionary *extraContext = [SentryDependencyContainer.sharedInstance.extraContextProvider getExtraContext]; [self modifyContext:event - key:@"device" + key:SENTRY_CONTEXT_DEVICE_KEY block:^(NSMutableDictionary *device) { - [device addEntriesFromDictionary:extraContext[@"device"]]; + [device addEntriesFromDictionary:extraContext[SENTRY_CONTEXT_DEVICE_KEY]]; }]; [self modifyContext:event @@ -1035,7 +1063,8 @@ - (void)applyCurrentViewNamesToEventContext:(SentryEvent *)event withScope:(Sent } } else { if (scope.currentScreen != nil) { - app[@"view_names"] = @[ scope.currentScreen ]; + app[@"view_names"] = + @[ SENTRY_UNWRAP_NULLABLE(NSString, scope.currentScreen) ]; } else { app[@"view_names"] = [SentryDependencyContainer.sharedInstance .application relevantViewControllersNames]; @@ -1048,7 +1077,7 @@ - (void)applyCurrentViewNamesToEventContext:(SentryEvent *)event withScope:(Sent - (void)removeExtraDeviceContextFromEvent:(SentryEvent *)event { [self modifyContext:event - key:@"device" + key:SENTRY_CONTEXT_DEVICE_KEY block:^(NSMutableDictionary *device) { [device removeObjectForKey:SentryDeviceContextFreeMemoryKey]; [device removeObjectForKey:@"orientation"]; @@ -1072,10 +1101,14 @@ - (void)modifyContext:(SentryEvent *)event return; } - NSMutableDictionary *context = [[NSMutableDictionary alloc] initWithDictionary:event.context]; - NSMutableDictionary *dict = event.context[key] == nil - ? [[NSMutableDictionary alloc] init] - : [[NSMutableDictionary alloc] initWithDictionary:context[key]]; + NSMutableDictionary *context = [[NSMutableDictionary alloc] + initWithDictionary:SENTRY_UNWRAP_NULLABLE(NSDictionary, event.context)]; + NSMutableDictionary *dict + = event.context[key] != nil && [event.context[key] isKindOfClass:[NSDictionary class]] + ? [[NSMutableDictionary alloc] + initWithDictionary:SENTRY_UNWRAP_NULLABLE(NSDictionary, context[key])] + : [NSMutableDictionary dictionary]; + block(dict); context[key] = dict; event.context = context; @@ -1116,12 +1149,33 @@ - (void)removeAttachmentProcessor:(id)attachmen NSArray *processedAttachments = attachments; for (id attachmentProcessor in self.attachmentProcessors) { - processedAttachments = [attachmentProcessor processAttachments:attachments forEvent:event]; + // Keep chaining the processed attachments so each processor works on the output of the + // previous one. This is necessary so each processor can add and remove attachments. + // + // Important: This means the order of adding processors matters and relies on the + // initialization order of the integrations. At this point in time the attachment processors + // are only adding attachments, therefore we can ignore this restriction for now. + processedAttachments = [attachmentProcessor processAttachments:processedAttachments + forEvent:event]; } return processedAttachments; } +- (void)captureLogsData:(NSData *)data with:(NSNumber *)itemCount; +{ + SentryEnvelopeItemHeader *header = + [[SentryEnvelopeItemHeader alloc] initWithType:SentryEnvelopeItemTypes.log + length:data.length + contentType:@"application/vnd.sentry.items.log+json" + itemCount:itemCount]; + + SentryEnvelopeItem *envelopeItem = [[SentryEnvelopeItem alloc] initWithHeader:header data:data]; + SentryEnvelope *envelope = [[SentryEnvelope alloc] initWithHeader:[SentryEnvelopeHeader empty] + singleItem:envelopeItem]; + [self captureEnvelope:envelope]; +} + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryClientReport.m b/Sources/Sentry/SentryClientReport.m deleted file mode 100644 index 2fbd12cd185..00000000000 --- a/Sources/Sentry/SentryClientReport.m +++ /dev/null @@ -1,33 +0,0 @@ -#import "SentryClientReport.h" -#import "SentryDependencyContainer.h" -#import "SentrySwift.h" -#import - -NS_ASSUME_NONNULL_BEGIN - -@implementation SentryClientReport - -- (instancetype)initWithDiscardedEvents:(NSArray *)discardedEvents -{ - if (self = [super init]) { - _timestamp = [SentryDependencyContainer.sharedInstance.dateProvider date]; - _discardedEvents = discardedEvents; - } - return self; -} - -- (NSDictionary *)serialize -{ - NSMutableArray *> *events = - [[NSMutableArray alloc] initWithCapacity:self.discardedEvents.count]; - for (SentryDiscardedEvent *event in self.discardedEvents) { - [events addObject:[event serialize]]; - } - - return - @{ @"timestamp" : @(self.timestamp.timeIntervalSince1970), @"discarded_events" : events }; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryConcurrentRateLimitsDictionary.m b/Sources/Sentry/SentryConcurrentRateLimitsDictionary.m index 58b05e857e2..a30e8779849 100644 --- a/Sources/Sentry/SentryConcurrentRateLimitsDictionary.m +++ b/Sources/Sentry/SentryConcurrentRateLimitsDictionary.m @@ -24,7 +24,7 @@ - (void)addRateLimit:(SentryDataCategory)category validUntil:(NSDate *)date } } -- (NSDate *)getRateLimitForCategory:(SentryDataCategory)category +- (nullable NSDate *)getRateLimitForCategory:(SentryDataCategory)category { @synchronized(self.rateLimits) { return self.rateLimits[@(category)]; diff --git a/Sources/Sentry/SentryCoreDataTracker.m b/Sources/Sentry/SentryCoreDataTracker.m index d05a4d59b2d..727ed4ec946 100644 --- a/Sources/Sentry/SentryCoreDataTracker.m +++ b/Sources/Sentry/SentryCoreDataTracker.m @@ -4,7 +4,6 @@ #import "SentryHub+Private.h" #import "SentryInternalDefines.h" #import "SentryLogC.h" -#import "SentryNSProcessInfoWrapper.h" #import "SentryPredicateDescriptor.h" #import "SentrySDK+Private.h" #import "SentryScope+Private.h" @@ -19,11 +18,11 @@ @implementation SentryCoreDataTracker { SentryPredicateDescriptor *predicateDescriptor; SentryThreadInspector *_threadInspector; - SentryNSProcessInfoWrapper *_processInfoWrapper; + id _processInfoWrapper; } - (instancetype)initWithThreadInspector:(SentryThreadInspector *)threadInspector - processInfoWrapper:(SentryNSProcessInfoWrapper *)processInfoWrapper; + processInfoWrapper:(id)processInfoWrapper; { if (self = [super init]) { predicateDescriptor = [[SentryPredicateDescriptor alloc] init]; @@ -38,7 +37,7 @@ - (NSArray *)managedObjectContext:(NSManagedObjectContext *)context error:(NSError **)error originalImp:(NSArray *(NS_NOESCAPE ^)(NSFetchRequest *, NSError **))original { - id _Nullable currentSpan = [SentrySDK.currentHub.scope span]; + id _Nullable currentSpan = [SentrySDKInternal.currentHub.scope span]; id _Nullable fetchSpan; if (currentSpan) { NSString *spanDescription = [self descriptionFromRequest:request]; @@ -57,7 +56,7 @@ - (NSArray *)managedObjectContext:(NSManagedObjectContext *)context NSArray *result = original(request, error); if (fetchSpan) { - [self addExtraInfoToSpan:fetchSpan withContext:context]; + [self addExtraInfoToSpan:(SentrySpan *)fetchSpan withContext:context]; [fetchSpan setDataValue:[NSNumber numberWithInteger:result.count] forKey:@"read_count"]; [fetchSpan @@ -80,7 +79,7 @@ - (BOOL)managedObjectContext:(NSManagedObjectContext *)context __block NSDictionary *operations = [self groupEntitiesOperations:context]; - id _Nullable currentSpan = [SentrySDK.currentHub.scope span]; + id _Nullable currentSpan = [SentrySDKInternal.currentHub.scope span]; if (currentSpan) { NSString *spanDescription = [self descriptionForOperations:operations inContext:context]; @@ -104,7 +103,7 @@ - (BOOL)managedObjectContext:(NSManagedObjectContext *)context BOOL result = original(error); if (saveSpan) { - [self addExtraInfoToSpan:saveSpan withContext:context]; + [self addExtraInfoToSpan:(SentrySpan *)saveSpan withContext:context]; [saveSpan finishWithStatus:result ? kSentrySpanStatusOk : kSentrySpanStatusInternalError]; SENTRY_LOG_DEBUG(@"SentryCoreDataTracker automatically finished span with status: %@", @@ -125,7 +124,7 @@ - (void)addExtraInfoToSpan:(SentrySpan *)span withContext:(NSManagedObjectContex __kindof NSPersistentStore *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) { [systems addObject:obj.type]; if (obj.URL != nil) { - [names addObject:obj.URL.path]; + [names addObject:SENTRY_UNWRAP_NULLABLE(NSString, obj.URL.path)]; } else { [names addObject:@"(null)"]; } @@ -204,7 +203,8 @@ - (NSString *)descriptionFromRequest:(NSFetchRequest *)request if (request.predicate) { [result appendFormat:@" WHERE %@", - [predicateDescriptor predicateDescription:request.predicate]]; + [predicateDescriptor + predicateDescription:SENTRY_UNWRAP_NULLABLE(NSPredicate, request.predicate)]]; } if (request.sortDescriptors.count > 0) { diff --git a/Sources/Sentry/SentryCoreDataTrackingIntegration.m b/Sources/Sentry/SentryCoreDataTrackingIntegration.m index 825e30a00b0..f28567be312 100644 --- a/Sources/Sentry/SentryCoreDataTrackingIntegration.m +++ b/Sources/Sentry/SentryCoreDataTrackingIntegration.m @@ -4,7 +4,6 @@ #import "SentryDependencyContainer.h" #import "SentryLogC.h" #import "SentryNSDataSwizzling.h" -#import "SentryNSProcessInfoWrapper.h" #import "SentryOptions.h" #import "SentryThreadInspector.h" diff --git a/Sources/Sentry/SentryCrashDefaultBinaryImageProvider.m b/Sources/Sentry/SentryCrashDefaultBinaryImageProvider.m index cfbf34ad448..deafd4ee36c 100644 --- a/Sources/Sentry/SentryCrashDefaultBinaryImageProvider.m +++ b/Sources/Sentry/SentryCrashDefaultBinaryImageProvider.m @@ -1,7 +1,9 @@ -#import "SentryCrashDefaultBinaryImageProvider.h" -#import "SentryCrashBinaryImageProvider.h" -#import "SentryCrashDynamicLinker.h" -#import +#if !SDK_V9 + +# import "SentryCrashDefaultBinaryImageProvider.h" +# import "SentryCrashBinaryImageProvider.h" +# import "SentryCrashDynamicLinker.h" +# import @implementation SentryCrashDefaultBinaryImageProvider @@ -18,3 +20,5 @@ - (SentryCrashBinaryImage)getBinaryImage:(NSInteger)index isCrash:(BOOL)isCrash } @end + +#endif // !SDK_V9 diff --git a/Sources/Sentry/SentryCrashExceptionApplicationHelper.m b/Sources/Sentry/SentryCrashExceptionApplicationHelper.m index 3ea3c7e79e1..19621f86c16 100644 --- a/Sources/Sentry/SentryCrashExceptionApplicationHelper.m +++ b/Sources/Sentry/SentryCrashExceptionApplicationHelper.m @@ -7,7 +7,7 @@ # import "SentryCrashExceptionApplicationHelper.h" # import "SentryDependencyContainer.h" # import "SentrySDK+Private.h" -# import "SentrySDK.h" +# import "SentrySDKInternal.h" @implementation SentryCrashExceptionApplicationHelper @@ -21,7 +21,7 @@ + (void)reportException:(NSException *)exception + (void)_crashOnException:(NSException *)exception { - [SentrySDK captureCrashOnException:exception]; + [SentrySDKInternal captureCrashOnException:exception]; # if !(SENTRY_TEST || SENTRY_TEST_CI) abort(); # endif diff --git a/Sources/Sentry/SentryCrashIntegration.m b/Sources/Sentry/SentryCrashIntegration.m index 2dcf54fb9ea..89a3d98cc57 100644 --- a/Sources/Sentry/SentryCrashIntegration.m +++ b/Sources/Sentry/SentryCrashIntegration.m @@ -5,13 +5,13 @@ #import "SentryCrashIntegrationSessionHandler.h" #import "SentryCrashMonitor_CPPException.h" #include "SentryCrashMonitor_Signal.h" -#import "SentryCrashWrapper.h" #import "SentryEvent.h" #import "SentryHub.h" -#import "SentryInAppLogic.h" +#import "SentryModels+Serializable.h" #import "SentryOptions.h" #import "SentrySDK+Private.h" #import "SentryScope+Private.h" +#import "SentryScope+PrivateSwift.h" #import "SentrySpan+Private.h" #import "SentrySwift.h" #import "SentryTracer.h" @@ -24,7 +24,6 @@ #import #if SENTRY_HAS_UIKIT -# import "SentryUIApplication.h" # import #endif @@ -35,13 +34,12 @@ static dispatch_once_t installationToken = 0; static SentryCrashInstallationReporter *installation = nil; -static NSString *const DEVICE_KEY = @"device"; static NSString *const LOCALE_KEY = @"locale"; void sentry_finishAndSaveTransaction(void) { - SentrySpan *span = SentrySDK.currentHub.scope.span; + SentrySpan *span = (SentrySpan *)SentrySDKInternal.currentHub.scope.span; if (span != nil) { SentryTracer *tracer = [span tracer]; @@ -63,7 +61,7 @@ @implementation SentryCrashIntegration - (instancetype)init { - self = [self initWithCrashAdapter:[SentryCrashWrapper sharedInstance] + self = [self initWithCrashAdapter:SentryDependencyContainer.sharedInstance.crashWrapper andDispatchQueueWrapper:[[SentryDispatchQueueWrapper alloc] init]]; return self; @@ -231,7 +229,7 @@ - (void)configureScope { // We need to make sure to set always the scope to KSCrash so we have it in // case of a crash - [SentrySDK.currentHub configureScope:^(SentryScope *_Nonnull outerScope) { + [SentrySDKInternal.currentHub configureScope:^(SentryScope *_Nonnull outerScope) { NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:[outerScope serialize]]; // SentryCrashReportConverter.convertReportToEvent needs the release name and @@ -256,11 +254,12 @@ - (void)configureScope - (void)currentLocaleDidChange { - [SentrySDK.currentHub configureScope:^(SentryScope *_Nonnull scope) { + [SentrySDKInternal.currentHub configureScope:^(SentryScope *_Nonnull scope) { NSMutableDictionary *device; - if (scope.contextDictionary != nil && scope.contextDictionary[DEVICE_KEY] != nil) { + if (scope.contextDictionary != nil + && scope.contextDictionary[SENTRY_CONTEXT_DEVICE_KEY] != nil) { device = [[NSMutableDictionary alloc] - initWithDictionary:scope.contextDictionary[DEVICE_KEY]]; + initWithDictionary:scope.contextDictionary[SENTRY_CONTEXT_DEVICE_KEY]]; } else { device = [NSMutableDictionary new]; } @@ -268,7 +267,7 @@ - (void)currentLocaleDidChange NSString *locale = [[NSLocale autoupdatingCurrentLocale] objectForKey:NSLocaleIdentifier]; device[LOCALE_KEY] = locale; - [scope setContextValue:device forKey:DEVICE_KEY]; + [scope setContextValue:device forKey:SENTRY_CONTEXT_DEVICE_KEY]; }]; } diff --git a/Sources/Sentry/SentryCrashIntegrationSessionHandler.m b/Sources/Sentry/SentryCrashIntegrationSessionHandler.m index 5701c911bcd..92c7d2e2e22 100644 --- a/Sources/Sentry/SentryCrashIntegrationSessionHandler.m +++ b/Sources/Sentry/SentryCrashIntegrationSessionHandler.m @@ -1,12 +1,11 @@ #import "SentryCrashIntegrationSessionHandler.h" #import "SentryClient+Private.h" -#import "SentryCrashWrapper.h" #import "SentryDependencyContainer.h" #import "SentryFileManager.h" #import "SentryHub.h" +#import "SentryInternalDefines.h" #import "SentryLogC.h" #import "SentrySDK+Private.h" -#import "SentrySession.h" #import "SentrySwift.h" #import "SentryWatchdogTerminationLogic.h" @@ -39,7 +38,7 @@ - (instancetype)initWithCrashWrapper:(SentryCrashWrapper *)crashWrapper - (void)endCurrentSessionIfRequired { - SentryFileManager *fileManager = [[[SentrySDK currentHub] getClient] fileManager]; + SentryFileManager *fileManager = [[[SentrySDKInternal currentHub] getClient] fileManager]; if (nil == fileManager) { SENTRY_LOG_DEBUG(@"File manager is nil. Cannot end current session."); @@ -81,7 +80,8 @@ - (void)endCurrentSessionIfRequired return; } - [session endSessionAbnormalWithTimestamp:appHangEvent.timestamp]; + [session + endSessionAbnormalWithTimestamp:SENTRY_UNWRAP_NULLABLE(NSDate, appHangEvent).timestamp]; [fileManager storeAbnormalSession:session]; [fileManager deleteCurrentSession]; } diff --git a/Sources/Sentry/SentryCrashReportConverter.m b/Sources/Sentry/SentryCrashReportConverter.m index 7a118232184..dcbb3b8251e 100644 --- a/Sources/Sentry/SentryCrashReportConverter.m +++ b/Sources/Sentry/SentryCrashReportConverter.m @@ -8,7 +8,6 @@ #import "SentryException.h" #import "SentryFormatter.h" #import "SentryFrame.h" -#import "SentryInAppLogic.h" #import "SentryInternalDefines.h" #import "SentryLogC.h" #import "SentryMechanism.h" diff --git a/Sources/Sentry/SentryCrashReportSink.m b/Sources/Sentry/SentryCrashReportSink.m index d032dad9a81..7931347c285 100644 --- a/Sources/Sentry/SentryCrashReportSink.m +++ b/Sources/Sentry/SentryCrashReportSink.m @@ -4,14 +4,13 @@ #import "SentryCrash.h" #include "SentryCrashMonitor_AppState.h" #import "SentryCrashReportConverter.h" -#import "SentryCrashWrapper.h" #import "SentryDefines.h" #import "SentryEvent.h" #import "SentryException.h" #import "SentryHub.h" #import "SentryLogC.h" #import "SentrySDK+Private.h" -#import "SentrySDK.h" +#import "SentrySDKInternal.h" #import "SentryScope+Private.h" #import "SentrySwift.h" #import "SentryThread.h" @@ -50,11 +49,11 @@ - (void)filterReports:(NSArray *)reports && durationFromCrashStateInitToLastCrash <= SENTRY_APP_START_CRASH_DURATION_THRESHOLD) { SENTRY_LOG_WARN(@"Startup crash: detected."); - [SentrySDK setDetectedStartUpCrash:YES]; + [SentrySDKInternal setDetectedStartUpCrash:YES]; [self sendReports:reports onCompletion:onCompletion]; - [SentrySDK flush:SENTRY_APP_START_CRASH_FLUSH_DURATION]; + [SentrySDKInternal flush:SENTRY_APP_START_CRASH_FLUSH_DURATION]; SENTRY_LOG_DEBUG(@"Startup crash: Finished flushing."); } else { @@ -69,7 +68,7 @@ - (void)sendReports:(NSArray *)reports onCompletion:(SentryCrashReportFilterComp for (NSDictionary *report in reports) { SentryCrashReportConverter *reportConverter = [[SentryCrashReportConverter alloc] initWithReport:report inAppLogic:self.inAppLogic]; - if (nil != [SentrySDK.currentHub getClient]) { + if (nil != [SentrySDKInternal.currentHub getClient]) { SentryEvent *event = [reportConverter convertReportToEvent]; if (nil != event) { [self handleConvertedEvent:event report:report sentReports:sentReports]; @@ -92,7 +91,7 @@ - (void)handleConvertedEvent:(SentryEvent *)event sentReports:(NSMutableArray *)sentReports { [sentReports addObject:report]; - SentryScope *scope = [[SentryScope alloc] initWithScope:SentrySDK.currentHub.scope]; + SentryScope *scope = [[SentryScope alloc] initWithScope:SentrySDKInternal.currentHub.scope]; if (report[SENTRYCRASH_REPORT_ATTACHMENTS_ITEM]) { for (NSString *ssPath in report[SENTRYCRASH_REPORT_ATTACHMENTS_ITEM]) { @@ -100,7 +99,7 @@ - (void)handleConvertedEvent:(SentryEvent *)event } } - [SentrySDK captureFatalEvent:event withScope:scope]; + [SentrySDKInternal captureFatalEvent:event withScope:scope]; } @end diff --git a/Sources/Sentry/SentryCrashScopeObserver.m b/Sources/Sentry/SentryCrashScopeObserver.m index b226b044763..e17272551d9 100644 --- a/Sources/Sentry/SentryCrashScopeObserver.m +++ b/Sources/Sentry/SentryCrashScopeObserver.m @@ -1,5 +1,6 @@ #import "SentryLevelMapper.h" #import "SentrySwift.h" +#import "SentryUser+Serialize.h" #import #import #import diff --git a/Sources/Sentry/SentryCrashStackEntryMapper.m b/Sources/Sentry/SentryCrashStackEntryMapper.m index c117b830585..f8007104c2b 100644 --- a/Sources/Sentry/SentryCrashStackEntryMapper.m +++ b/Sources/Sentry/SentryCrashStackEntryMapper.m @@ -1,9 +1,8 @@ #import "SentryCrashStackEntryMapper.h" -#import "SentryBinaryImageCache.h" #import "SentryDependencyContainer.h" #import "SentryFormatter.h" #import "SentryFrame.h" -#import "SentryInAppLogic.h" +#import "SentrySwift.h" NS_ASSUME_NONNULL_BEGIN @@ -42,7 +41,7 @@ - (SentryFrame *)sentryCrashStackEntryToSentryFrame:(SentryCrashStackEntry)stack // we get image from the cache. if (stackEntry.imageAddress == 0 && stackEntry.imageName == NULL) { SentryBinaryImageInfo *info = [SentryDependencyContainer.sharedInstance.binaryImageCache - imageByAddress:stackEntry.address]; + imageByAddress:(uint64_t)stackEntry.address]; frame.imageAddress = sentry_formatHexAddressUInt64(info.address); frame.package = info.name; diff --git a/Sources/Sentry/SentryCrashWrapper.m b/Sources/Sentry/SentryCrashWrapper.m deleted file mode 100644 index 1b4976aa7d1..00000000000 --- a/Sources/Sentry/SentryCrashWrapper.m +++ /dev/null @@ -1,219 +0,0 @@ -#import "SentryCrashWrapper.h" -#import "SentryCrash.h" -#import "SentryCrashBinaryImageCache.h" -#import "SentryCrashIntegration.h" -#import "SentryCrashMonitor_AppState.h" -#import "SentryCrashMonitor_System.h" -#import "SentryScope.h" -#import "SentryUIDeviceWrapper.h" -#import -#import -#import -#import -#include - -#if SENTRY_HAS_UIKIT -# import "SentryUIApplication.h" -# import -#endif - -static NSString *const DEVICE_KEY = @"device"; -static NSString *const LOCALE_KEY = @"locale"; - -NS_ASSUME_NONNULL_BEGIN - -@implementation SentryCrashWrapper - -+ (instancetype)sharedInstance -{ - static SentryCrashWrapper *instance = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ instance = [[self alloc] init]; }); - return instance; -} - -- (instancetype)init -{ - if (self = [super init]) { - sentrycrashcm_system_getAPI()->setEnabled(YES); - } - return self; -} - -- (BOOL)crashedLastLaunch -{ - return SentryDependencyContainer.sharedInstance.crashReporter.crashedLastLaunch; -} - -- (NSTimeInterval)durationFromCrashStateInitToLastCrash -{ - return sentrycrashstate_currentState()->durationFromCrashStateInitToLastCrash; -} - -- (NSTimeInterval)activeDurationSinceLastCrash -{ - return SentryDependencyContainer.sharedInstance.crashReporter.activeDurationSinceLastCrash; -} - -- (BOOL)isBeingTraced -{ - return sentrycrashdebug_isBeingTraced(); -} - -- (BOOL)isSimulatorBuild -{ - return sentrycrash_isSimulatorBuild(); -} - -- (BOOL)isApplicationInForeground -{ - return sentrycrashstate_currentState()->applicationIsInForeground; -} - -- (NSDictionary *)systemInfo -{ - static NSDictionary *sharedInfo = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, - ^{ sharedInfo = SentryDependencyContainer.sharedInstance.crashReporter.systemInfo; }); - return sharedInfo; -} - -- (bytes)freeMemorySize -{ - return sentrycrashcm_system_freememory_size(); -} - -- (bytes)appMemorySize -{ - task_vm_info_data_t info; - mach_msg_type_number_t size = TASK_VM_INFO_COUNT; - kern_return_t kerr = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t)&info, &size); - if (kerr == KERN_SUCCESS) { - return info.internal + info.compressed; - } - - return 0; -} - -- (void)startBinaryImageCache -{ - sentrycrashbic_startCache(); -} - -- (void)stopBinaryImageCache -{ - sentrycrashbic_stopCache(); -} - -- (void)enrichScope:(SentryScope *)scope -{ - // OS - NSMutableDictionary *osData = [NSMutableDictionary new]; - -#if SENTRY_TARGET_MACOS - [osData setValue:@"macOS" forKey:@"name"]; -#elif TARGET_OS_IOS - [osData setValue:@"iOS" forKey:@"name"]; -#elif TARGET_OS_TV - [osData setValue:@"tvOS" forKey:@"name"]; -#elif TARGET_OS_WATCH - [osData setValue:@"watchOS" forKey:@"name"]; -#elif TARGET_OS_VISION - [osData setValue:@"visionOS" forKey:@"name"]; -#endif - - // For MacCatalyst the UIDevice returns the current version of MacCatalyst and not the - // macOSVersion. Therefore we have to use NSProcessInfo. -#if SENTRY_HAS_UIKIT && !TARGET_OS_MACCATALYST - [osData setValue:[SentryDependencyContainer.sharedInstance.uiDeviceWrapper getSystemVersion] - forKey:@"version"]; -#else - NSOperatingSystemVersion version = [NSProcessInfo processInfo].operatingSystemVersion; - NSString *systemVersion = [NSString stringWithFormat:@"%d.%d.%d", (int)version.majorVersion, - (int)version.minorVersion, (int)version.patchVersion]; - [osData setValue:systemVersion forKey:@"version"]; - -#endif - - NSDictionary *systemInfo = [self systemInfo]; - - // SystemInfo should only be nil when SentryCrash has not been installed - if (systemInfo != nil && systemInfo.count != 0) { - [osData setValue:systemInfo[@"osVersion"] forKey:@"build"]; - [osData setValue:systemInfo[@"kernelVersion"] forKey:@"kernel_version"]; - [osData setValue:systemInfo[@"isJailbroken"] forKey:@"rooted"]; - } - - [scope setContextValue:osData forKey:@"os"]; - - // SystemInfo should only be nil when SentryCrash has not been installed - if (systemInfo == nil || systemInfo.count == 0) { - return; - } - - // DEVICE - - NSMutableDictionary *deviceData = [NSMutableDictionary new]; - -#if TARGET_OS_SIMULATOR - [deviceData setValue:@(YES) forKey:@"simulator"]; -#else - [deviceData setValue:@(NO) forKey:@"simulator"]; -#endif - - NSString *family = [[systemInfo[@"systemName"] - componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] firstObject]; - -#if TARGET_OS_MACCATALYST - // This would be iOS. Set it to macOS instead. - family = @"macOS"; -#endif - - [deviceData setValue:family forKey:@"family"]; - [deviceData setValue:systemInfo[@"cpuArchitecture"] forKey:@"arch"]; - [deviceData setValue:systemInfo[@"machine"] forKey:@"model"]; - [deviceData setValue:systemInfo[@"model"] forKey:@"model_id"]; - [deviceData setValue:systemInfo[@"freeMemorySize"] forKey:SentryDeviceContextFreeMemoryKey]; - [deviceData setValue:systemInfo[@"usableMemorySize"] forKey:@"usable_memory"]; - [deviceData setValue:systemInfo[@"memorySize"] forKey:@"memory_size"]; - - NSString *locale = [[NSLocale autoupdatingCurrentLocale] objectForKey:NSLocaleIdentifier]; - [deviceData setValue:locale forKey:LOCALE_KEY]; - -// The UIWindowScene is unavailable on visionOS -#if SENTRY_TARGET_REPLAY_SUPPORTED - - NSArray *appWindows = SentryDependencyContainer.sharedInstance.application.windows; - if ([appWindows count] > 0) { - UIScreen *appScreen = appWindows.firstObject.screen; - if (appScreen != nil) { - [deviceData setValue:@(appScreen.bounds.size.height) forKey:@"screen_height_pixels"]; - [deviceData setValue:@(appScreen.bounds.size.width) forKey:@"screen_width_pixels"]; - } - } - -#endif - - [scope setContextValue:deviceData forKey:DEVICE_KEY]; - - // APP - NSMutableDictionary *appData = [NSMutableDictionary new]; - NSDictionary *infoDict = [[NSBundle mainBundle] infoDictionary]; - - [appData setValue:infoDict[@"CFBundleIdentifier"] forKey:@"app_identifier"]; - [appData setValue:infoDict[@"CFBundleName"] forKey:@"app_name"]; - [appData setValue:infoDict[@"CFBundleVersion"] forKey:@"app_build"]; - [appData setValue:infoDict[@"CFBundleShortVersionString"] forKey:@"app_version"]; - - [appData setValue:systemInfo[@"appStartTime"] forKey:@"app_start_time"]; - [appData setValue:systemInfo[@"deviceAppHash"] forKey:@"device_app_hash"]; - [appData setValue:systemInfo[@"appID"] forKey:@"app_id"]; - [appData setValue:systemInfo[@"buildType"] forKey:@"build_type"]; - - [scope setContextValue:appData forKey:@"app"]; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryDataCategoryMapper.m b/Sources/Sentry/SentryDataCategoryMapper.m index 2f2cf0e536e..70bbaf2b3fc 100644 --- a/Sources/Sentry/SentryDataCategoryMapper.m +++ b/Sources/Sentry/SentryDataCategoryMapper.m @@ -1,6 +1,6 @@ #import "SentryDataCategoryMapper.h" #import "SentryDataCategory.h" -#import "SentryEnvelopeItemType.h" +#import "SentrySwift.h" // While these data categories names might look similar to the envelope item types, they are not // identical, and have slight differences. Just open them side by side and you'll see the @@ -13,13 +13,14 @@ NSString *const kSentryDataCategoryNameAttachment = @"attachment"; #if !SDK_V9 NSString *const kSentryDataCategoryNameUserFeedback = @"user_report"; -#endif // !SSDK_v9 +#endif // !SDK_V9 NSString *const kSentryDataCategoryNameProfile = @"profile"; NSString *const kSentryDataCategoryNameProfileChunk = @"profile_chunk_ui"; NSString *const kSentryDataCategoryNameReplay = @"replay"; NSString *const kSentryDataCategoryNameMetricBucket = @"metric_bucket"; NSString *const kSentryDataCategoryNameSpan = @"span"; NSString *const kSentryDataCategoryNameFeedback = @"feedback"; +NSString *const kSentryDataCategoryNameLogItem = @"log_item"; NSString *const kSentryDataCategoryNameUnknown = @"unknown"; NS_ASSUME_NONNULL_BEGIN @@ -27,35 +28,38 @@ SentryDataCategory sentryDataCategoryForEnvelopItemType(NSString *itemType) { - if ([itemType isEqualToString:SentryEnvelopeItemTypeEvent]) { + if ([itemType isEqualToString:SentryEnvelopeItemTypes.event]) { return kSentryDataCategoryError; } - if ([itemType isEqualToString:SentryEnvelopeItemTypeSession]) { + if ([itemType isEqualToString:SentryEnvelopeItemTypes.session]) { return kSentryDataCategorySession; } - if ([itemType isEqualToString:SentryEnvelopeItemTypeTransaction]) { + if ([itemType isEqualToString:SentryEnvelopeItemTypes.transaction]) { return kSentryDataCategoryTransaction; } - if ([itemType isEqualToString:SentryEnvelopeItemTypeAttachment]) { + if ([itemType isEqualToString:SentryEnvelopeItemTypes.attachment]) { return kSentryDataCategoryAttachment; } - if ([itemType isEqualToString:SentryEnvelopeItemTypeProfile]) { + if ([itemType isEqualToString:SentryEnvelopeItemTypes.profile]) { return kSentryDataCategoryProfile; } - if ([itemType isEqualToString:SentryEnvelopeItemTypeProfileChunk]) { + if ([itemType isEqualToString:SentryEnvelopeItemTypes.profileChunk]) { return kSentryDataCategoryProfileChunk; } - if ([itemType isEqualToString:SentryEnvelopeItemTypeReplayVideo]) { + if ([itemType isEqualToString:SentryEnvelopeItemTypes.replayVideo]) { return kSentryDataCategoryReplay; } - if ([itemType isEqualToString:SentryEnvelopeItemTypeFeedback]) { + if ([itemType isEqualToString:SentryEnvelopeItemTypes.feedback]) { return kSentryDataCategoryFeedback; } // The envelope item type used for metrics is statsd whereas the client report category for // discarded events is metric_bucket. - if ([itemType isEqualToString:SentryEnvelopeItemTypeStatsd]) { + if ([itemType isEqualToString:SentryEnvelopeItemTypes.statsd]) { return kSentryDataCategoryMetricBucket; } + if ([itemType isEqualToString:SentryEnvelopeItemTypes.log]) { + return kSentryDataCategoryLogItem; + } return kSentryDataCategoryDefault; } @@ -114,6 +118,9 @@ if ([value isEqualToString:kSentryDataCategoryNameFeedback]) { return kSentryDataCategoryFeedback; } + if ([value isEqualToString:kSentryDataCategoryNameLogItem]) { + return kSentryDataCategoryLogItem; + } return kSentryDataCategoryUnknown; } @@ -151,6 +158,8 @@ return kSentryDataCategoryNameSpan; case kSentryDataCategoryFeedback: return kSentryDataCategoryNameFeedback; + case kSentryDataCategoryLogItem: + return kSentryDataCategoryNameLogItem; default: // !!!: fall-through! case kSentryDataCategoryUnknown: diff --git a/Sources/Sentry/SentryDateUtil.m b/Sources/Sentry/SentryDateUtil.m index d7166e40b42..3fab44f8219 100644 --- a/Sources/Sentry/SentryDateUtil.m +++ b/Sources/Sentry/SentryDateUtil.m @@ -1,4 +1,5 @@ #import "SentryDateUtil.h" +#import "SentryInternalDefines.h" #import "SentrySwift.h" NS_ASSUME_NONNULL_BEGIN @@ -24,7 +25,8 @@ - (BOOL)isInFuture:(NSDate *_Nullable)date if (date == nil) return NO; - NSComparisonResult result = [[self.currentDateProvider date] compare:date]; + NSComparisonResult result = + [[self.currentDateProvider date] compare:SENTRY_UNWRAP_NULLABLE(NSDate, date)]; return result == NSOrderedAscending; } @@ -37,7 +39,8 @@ + (NSDate *_Nullable)getMaximumDate:(NSDate *_Nullable)first andOther:(NSDate *_ if (second == nil) return first; - NSComparisonResult result = [first compare:second]; + NSComparisonResult result = + [SENTRY_UNWRAP_NULLABLE(NSDate, first) compare:SENTRY_UNWRAP_NULLABLE(NSDate, second)]; if (result == NSOrderedDescending) { return first; } else { diff --git a/Sources/Sentry/SentryDebugImageProvider.m b/Sources/Sentry/SentryDebugImageProvider.m index f24f03482c8..ff06cd148c7 100644 --- a/Sources/Sentry/SentryDebugImageProvider.m +++ b/Sources/Sentry/SentryDebugImageProvider.m @@ -1,6 +1,8 @@ #import "SentryDebugImageProvider.h" -#import "SentryBinaryImageCache.h" -#import "SentryCrashDefaultBinaryImageProvider.h" +#import "SentryDebugImageProvider+HybridSDKs.h" +#if !SDK_V9 +# import "SentryCrashDefaultBinaryImageProvider.h" +#endif // !SDK_V9 #import "SentryCrashDynamicLinker.h" #import "SentryCrashUUIDConversion.h" #import "SentryDebugMeta.h" @@ -10,6 +12,7 @@ #import "SentryInternalDefines.h" #import "SentryLogC.h" #import "SentryStacktrace.h" +#import "SentrySwift.h" #import "SentryThread.h" #import @@ -17,7 +20,9 @@ @interface SentryDebugImageProvider () +#if !SDK_V9 @property (nonatomic, strong) id binaryImageProvider; +#endif // !SDK_V9 @property (nonatomic, strong) SentryBinaryImageCache *binaryImageCache; @end @@ -26,39 +31,62 @@ @implementation SentryDebugImageProvider - (instancetype)init { +#if SDK_V9 + self = + [self initWithBinaryImageCache:SentryDependencyContainer.sharedInstance.binaryImageCache]; +#else SentryCrashDefaultBinaryImageProvider *provider = [[SentryCrashDefaultBinaryImageProvider alloc] init]; - self = [self initWithBinaryImageProvider:provider binaryImageCache:SentryDependencyContainer.sharedInstance.binaryImageCache]; +#endif // SDK_V9 return self; } /** Internal constructor for testing */ +#if SDK_V9 +- (instancetype)initWithBinaryImageCache:(SentryBinaryImageCache *)binaryImageCache +#else - (instancetype)initWithBinaryImageProvider:(id)binaryImageProvider binaryImageCache:(SentryBinaryImageCache *)binaryImageCache +#endif // SDK_V9 { if (self = [super init]) { +#if !SDK_V9 self.binaryImageProvider = binaryImageProvider; +#endif // !SDK_V9 self.binaryImageCache = binaryImageCache; } return self; } +- (void)extractDebugImageAddressFromFrames:(NSArray *)frames + intoSet:(NSMutableSet *)set +{ + for (SentryFrame *frame in frames) { + if (frame.imageAddress) { + [set addObject:SENTRY_UNWRAP_NULLABLE(NSString, frame.imageAddress)]; + } + } +} + +#if !SDK_V9 + - (NSArray *)getDebugImagesForAddresses:(NSSet *)addresses isCrash:(BOOL)isCrash { NSMutableArray *result = [NSMutableArray array]; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" NSArray *binaryImages = [self getDebugImagesCrashed:isCrash]; -#pragma clang diagnostic pop +# pragma clang diagnostic pop for (SentryDebugMeta *sourceImage in binaryImages) { - if ([addresses containsObject:sourceImage.imageAddress]) { + if (sourceImage.imageAddress && + [addresses containsObject:SENTRY_UNWRAP_NULLABLE(NSString, sourceImage.imageAddress)]) { [result addObject:sourceImage]; } } @@ -66,16 +94,6 @@ - (instancetype)initWithBinaryImageProvider:(id) return result; } -- (void)extractDebugImageAddressFromFrames:(NSArray *)frames - intoSet:(NSMutableSet *)set -{ - for (SentryFrame *frame in frames) { - if (frame.imageAddress) { - [set addObject:frame.imageAddress]; - } - } -} - - (NSArray *)getDebugImagesForFrames:(NSArray *)frames { // maintains previous behavior for the same method call by also trying to gather crash info @@ -102,31 +120,38 @@ - (void)extractDebugImageAddressFromFrames:(NSArray *)frames NSMutableSet *imageAddresses = [[NSMutableSet alloc] init]; for (SentryThread *thread in threads) { - [self extractDebugImageAddressFromFrames:thread.stacktrace.frames intoSet:imageAddresses]; + NSArray *_Nullable frames = thread.stacktrace.frames; + if (frames != nil) { + [self extractDebugImageAddressFromFrames:SENTRY_UNWRAP_NULLABLE(NSArray, frames) + intoSet:imageAddresses]; + } } return [self getDebugImagesForAddresses:imageAddresses isCrash:isCrash]; } -- (NSArray *)getDebugImagesFromCacheForFrames:(NSArray *)frames +- (NSArray *)getDebugImages { - NSMutableSet *imageAddresses = [[NSMutableSet alloc] init]; - [self extractDebugImageAddressFromFrames:frames intoSet:imageAddresses]; - - return [self getDebugImagesForImageAddressesFromCache:imageAddresses]; + // maintains previous behavior for the same method call by also trying to gather crash info + return [self getDebugImagesCrashed:YES]; } -- (NSArray *)getDebugImagesFromCacheForThreads:(NSArray *)threads +- (NSArray *)getDebugImagesCrashed:(BOOL)isCrash { - NSMutableSet *imageAddresses = [[NSMutableSet alloc] init]; + NSMutableArray *debugMetaArray = [NSMutableArray new]; - for (SentryThread *thread in threads) { - [self extractDebugImageAddressFromFrames:thread.stacktrace.frames intoSet:imageAddresses]; + NSInteger imageCount = [self.binaryImageProvider getImageCount]; + for (NSInteger i = 0; i < imageCount; i++) { + SentryCrashBinaryImage image = [self.binaryImageProvider getBinaryImage:i isCrash:isCrash]; + SentryDebugMeta *debugMeta = [self fillDebugMetaFrom:image]; + [debugMetaArray addObject:debugMeta]; } - return [self getDebugImagesForImageAddressesFromCache:imageAddresses]; + return debugMetaArray; } +#endif // !SDK_V9 + - (NSArray *)getDebugImagesForImageAddressesFromCache: (NSSet *)imageAddresses { @@ -145,10 +170,27 @@ - (void)extractDebugImageAddressFromFrames:(NSArray *)frames return result; } -- (NSArray *)getDebugImages +- (NSArray *)getDebugImagesFromCacheForFrames:(NSArray *)frames { - // maintains previous behavior for the same method call by also trying to gather crash info - return [self getDebugImagesCrashed:YES]; + NSMutableSet *imageAddresses = [[NSMutableSet alloc] init]; + [self extractDebugImageAddressFromFrames:frames intoSet:imageAddresses]; + + return [self getDebugImagesForImageAddressesFromCache:imageAddresses]; +} + +- (NSArray *)getDebugImagesFromCacheForThreads:(NSArray *)threads +{ + NSMutableSet *imageAddresses = [[NSMutableSet alloc] init]; + + for (SentryThread *thread in threads) { + NSArray *_Nullable frames = thread.stacktrace.frames; + if (frames != nil) { + [self extractDebugImageAddressFromFrames:SENTRY_UNWRAP_NULLABLE(NSArray, frames) + intoSet:imageAddresses]; + } + } + + return [self getDebugImagesForImageAddressesFromCache:imageAddresses]; } - (NSArray *)getDebugImagesFromCache @@ -162,20 +204,6 @@ - (void)extractDebugImageAddressFromFrames:(NSArray *)frames return result; } -- (NSArray *)getDebugImagesCrashed:(BOOL)isCrash -{ - NSMutableArray *debugMetaArray = [NSMutableArray new]; - - NSInteger imageCount = [self.binaryImageProvider getImageCount]; - for (NSInteger i = 0; i < imageCount; i++) { - SentryCrashBinaryImage image = [self.binaryImageProvider getBinaryImage:i isCrash:isCrash]; - SentryDebugMeta *debugMeta = [self fillDebugMetaFrom:image]; - [debugMetaArray addObject:debugMeta]; - } - - return debugMetaArray; -} - - (SentryDebugMeta *)fillDebugMetaFrom:(SentryCrashBinaryImage)image { SentryDebugMeta *debugMeta = [[SentryDebugMeta alloc] init]; @@ -200,7 +228,7 @@ - (SentryDebugMeta *)fillDebugMetaFrom:(SentryCrashBinaryImage)image - (SentryDebugMeta *)fillDebugMetaFromBinaryImageInfo:(SentryBinaryImageInfo *)info { SentryDebugMeta *debugMeta = [[SentryDebugMeta alloc] init]; - debugMeta.debugID = info.UUID; + debugMeta.debugID = info.uuid; debugMeta.type = SentryDebugImageType; if (info.vmAddress > 0) { diff --git a/Sources/Sentry/SentryDefaultObjCRuntimeWrapper.m b/Sources/Sentry/SentryDefaultObjCRuntimeWrapper.m deleted file mode 100644 index b0589f0dc67..00000000000 --- a/Sources/Sentry/SentryDefaultObjCRuntimeWrapper.m +++ /dev/null @@ -1,24 +0,0 @@ -#import "SentryDefaultObjCRuntimeWrapper.h" -#import - -@implementation SentryDefaultObjCRuntimeWrapper - -+ (instancetype)sharedInstance -{ - static SentryDefaultObjCRuntimeWrapper *instance = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ instance = [[self alloc] init]; }); - return instance; -} - -- (const char **)copyClassNamesForImage:(const char *)image amount:(unsigned int *)outCount -{ - return objc_copyClassNamesForImage(image, outCount); -} - -- (const char *)class_getImageName:(Class)cls -{ - return class_getImageName(cls); -} - -@end diff --git a/Sources/Sentry/SentryDefaultRateLimits.m b/Sources/Sentry/SentryDefaultRateLimits.m index dfc4b2553d3..df448758ad7 100644 --- a/Sources/Sentry/SentryDefaultRateLimits.m +++ b/Sources/Sentry/SentryDefaultRateLimits.m @@ -2,6 +2,7 @@ #import "SentryConcurrentRateLimitsDictionary.h" #import "SentryDataCategoryMapper.h" #import "SentryDateUtil.h" +#import "SentryInternalDefines.h" #import "SentryLogC.h" #import "SentryRateLimitParser.h" #import "SentryRetryAfterHeaderParser.h" @@ -38,8 +39,9 @@ - (instancetype)initWithRetryAfterHeaderParser: - (BOOL)isRateLimitActive:(SentryDataCategory)category { - NSDate *categoryDate = [self.rateLimits getRateLimitForCategory:category]; - NSDate *allCategoriesDate = [self.rateLimits getRateLimitForCategory:kSentryDataCategoryAll]; + NSDate *_Nullable categoryDate = [self.rateLimits getRateLimitForCategory:category]; + NSDate *_Nullable allCategoriesDate = + [self.rateLimits getRateLimitForCategory:kSentryDataCategoryAll]; BOOL isActiveForCategory = [self.dateUtil isInFuture:categoryDate]; BOOL isActiveForCategories = [self.dateUtil isInFuture:allCategoriesDate]; @@ -61,7 +63,8 @@ - (void)update:(NSHTTPURLResponse *)response SentryDataCategory category = sentryDataCategoryForNSUInteger(categoryAsNumber.unsignedIntegerValue); - [self updateRateLimit:category withDate:limits[categoryAsNumber]]; + [self updateRateLimit:category + withDate:SENTRY_UNWRAP_NULLABLE(NSDate, limits[categoryAsNumber])]; } } else if (response.statusCode == 429) { NSDate *retryAfterHeaderDate = diff --git a/Sources/Sentry/SentryDependencyContainer.m b/Sources/Sentry/SentryDependencyContainer.m index 845e59a8684..70a3988c3f8 100644 --- a/Sources/Sentry/SentryDependencyContainer.m +++ b/Sources/Sentry/SentryDependencyContainer.m @@ -1,35 +1,26 @@ #import "SentryANRTrackerV1.h" -#import "SentryApplication.h" -#import "SentryBinaryImageCache.h" #import "SentryDispatchFactory.h" #import "SentryDisplayLinkWrapper.h" #import "SentryExtraContextProvider.h" #import "SentryFileIOTracker.h" #import "SentryFileManager.h" #import "SentryInternalCDefines.h" +#import "SentryInternalDefines.h" #import "SentryLogC.h" -#import "SentryNSProcessInfoWrapper.h" -#import "SentryNSTimerFactory.h" #import "SentryOptions+Private.h" -#import "SentryRandom.h" #import "SentrySDK+Private.h" #import "SentrySessionTracker.h" #import "SentrySwift.h" #import "SentrySystemWrapper.h" #import "SentryThreadInspector.h" -#import "SentryUIDeviceWrapper.h" #import #import -#import -#import -#import +#import #import #import #import #import -#import -#import #import #import #import @@ -45,19 +36,10 @@ #if SENTRY_HAS_UIKIT # import "SentryANRTrackerV2.h" # import "SentryFramesTracker.h" -# import "SentryUIApplication.h" # import # import #endif // SENTRY_HAS_UIKIT -#if TARGET_OS_IOS -# import "SentryUIDeviceWrapper.h" -#endif // TARGET_OS_IOS - -#if TARGET_OS_OSX -# import "SentryNSApplication.h" -#endif - #if !TARGET_OS_WATCH # import "SentryReachability.h" #endif // !TARGET_OS_WATCH @@ -161,33 +143,34 @@ - (instancetype)init if (self = [super init]) { isInitialializingDependencyContainer = YES; - _dispatchQueueWrapper = [[SentryDispatchQueueWrapper alloc] init]; + _dispatchQueueWrapper = SentryDependencies.dispatchQueueWrapper; _random = [[SentryRandom alloc] init]; _threadWrapper = [[SentryThreadWrapper alloc] init]; _binaryImageCache = [[SentryBinaryImageCache alloc] init]; - _dateProvider = [[SentryDefaultCurrentDateProvider alloc] init]; + _dateProvider = SentryDependencies.dateProvider; - _notificationCenterWrapper = [[SentryNSNotificationCenterWrapper alloc] init]; + _notificationCenterWrapper = NSNotificationCenter.defaultCenter; + + _processInfoWrapper = NSProcessInfo.processInfo; + _crashWrapper = [[SentryCrashWrapper alloc] initWithProcessInfoWrapper:_processInfoWrapper]; #if SENTRY_HAS_UIKIT - _uiDeviceWrapper = [[SentryUIDeviceWrapper alloc] init]; - _application = [[SentryUIApplication alloc] - initWithNotificationCenterWrapper:_notificationCenterWrapper - dispatchQueueWrapper:_dispatchQueueWrapper]; + _uiDeviceWrapper = SentryDependencies.uiDeviceWrapper; + _application = UIApplication.sharedApplication; + _threadsafeApplication = [[SentryThreadsafeApplication alloc] + initWithInitialState:_application.unsafeApplicationState + notificationCenter:_notificationCenterWrapper]; #elif TARGET_OS_OSX - _application = [[SentryNSApplication alloc] init]; + _application = NSApplication.sharedApplication; #endif // SENTRY_HAS_UIKIT - _processInfoWrapper = [[SentryNSProcessInfoWrapper alloc] init]; - _extraContextProvider = [[SentryExtraContextProvider alloc] - initWithCrashWrapper:[SentryCrashWrapper sharedInstance] - processInfoWrapper:_processInfoWrapper + _extraContextProvider = + [[SentryExtraContextProvider alloc] initWithCrashWrapper:_crashWrapper + processInfoWrapper:_processInfoWrapper #if TARGET_OS_IOS && SENTRY_HAS_UIKIT - deviceWrapper:_uiDeviceWrapper + deviceWrapper:_uiDeviceWrapper #endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT ]; - _crashWrapper = [[SentryCrashWrapper alloc] init]; - _sysctlWrapper = [[SentrySysctl alloc] init]; SentryRetryAfterHeaderParser *retryAfterHeaderParser = [[SentryRetryAfterHeaderParser alloc] @@ -214,8 +197,11 @@ - (nullable SentryFileManager *)fileManager SENTRY_THREAD_SANITIZER_DOUBLE_CHECK { SENTRY_LAZY_INIT(_fileManager, ({ NSError *error; - SentryFileManager *manager = [[SentryFileManager alloc] initWithOptions:SentrySDK.options - error:&error]; + SentryFileManager *manager = + [[SentryFileManager alloc] initWithOptions:SentrySDKInternal.options + dateProvider:self.dateProvider + dispatchQueueWrapper:self.dispatchQueueWrapper + error:&error]; if (manager == nil) { SENTRY_LOG_DEBUG(@"Could not create file manager - %@", error); } @@ -226,7 +212,7 @@ - (nullable SentryFileManager *)fileManager SENTRY_THREAD_SANITIZER_DOUBLE_CHECK - (SentryAppStateManager *)appStateManager SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK { SENTRY_LAZY_INIT(_appStateManager, - [[SentryAppStateManager alloc] initWithOptions:SentrySDK.options + [[SentryAppStateManager alloc] initWithOptions:SentrySDKInternal.options crashWrapper:self.crashWrapper fileManager:self.fileManager dispatchQueueWrapper:self.dispatchQueueWrapper @@ -235,8 +221,8 @@ - (SentryAppStateManager *)appStateManager SENTRY_THREAD_SANITIZER_DOUBLE_CHECKE - (SentryThreadInspector *)threadInspector SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK { - SENTRY_LAZY_INIT( - _threadInspector, [[SentryThreadInspector alloc] initWithOptions:SentrySDK.options]); + SENTRY_LAZY_INIT(_threadInspector, + [[SentryThreadInspector alloc] initWithOptions:SentrySDKInternal.options]); } - (SentryFileIOTracker *)fileIOTracker SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK @@ -249,7 +235,7 @@ - (SentryFileIOTracker *)fileIOTracker SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LO - (SentryCrash *)crashReporter SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK { SENTRY_LAZY_INIT(_crashReporter, - [[SentryCrash alloc] initWithBasePath:SentrySDK.options.cacheDirectoryPath]); + [[SentryCrash alloc] initWithBasePath:SentrySDKInternal.options.cacheDirectoryPath]); } - (id)getANRTracker:(NSTimeInterval)timeout @@ -280,18 +266,34 @@ - (SentryCrash *)crashReporter SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK #endif // SENTRY_HAS_UIKIT #if SENTRY_TARGET_REPLAY_SUPPORTED -- (SentryScreenshot *)screenshot SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK +- (nonnull SentryScreenshotSource *)screenshotSource SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK { -# if SENTRY_HAS_UIKIT - SENTRY_LAZY_INIT(_screenshot, [[SentryScreenshot alloc] init]); -# else - SENTRY_LOG_DEBUG( - @"SentryDependencyContainer.screenshot only works with UIKit enabled. Ensure you're " - @"using the right configuration of Sentry that links UIKit."); - return nil; -# endif // SENTRY_HAS_UIKIT + @synchronized(sentryDependencyContainerDependenciesLock) { + if (_screenshotSource == nil) { + // The options could be null here, but this is a general issue in the dependency + // container and will be fixed in a future refactoring. + SentryViewScreenshotOptions *_Nonnull options = SENTRY_UNWRAP_NULLABLE( + SentryViewScreenshotOptions, SentrySDKInternal.options.screenshot); + + id viewRenderer; + if (options.enableViewRendererV2) { + viewRenderer = [[SentryViewRendererV2 alloc] + initWithEnableFastViewRendering:options.enableFastViewRendering]; + } else { + viewRenderer = [[SentryDefaultViewRenderer alloc] init]; + } + + SentryViewPhotographer *photographer = + [[SentryViewPhotographer alloc] initWithRenderer:viewRenderer + redactOptions:options + enableMaskRendererV2:options.enableViewRendererV2]; + _screenshotSource = [[SentryScreenshotSource alloc] initWithPhotographer:photographer]; + } + + return _screenshotSource; + } } -#endif +#endif // SENTRY_HAS_UIKIT #if SENTRY_UIKIT_AVAILABLE - (SentryViewHierarchyProvider *)viewHierarchyProvider SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK @@ -357,22 +359,20 @@ - (SentrySwizzleWrapper *)swizzleWrapper SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_ } #endif // SENTRY_UIKIT_AVAILABLE +#if SENTRY_TARGET_PROFILING_SUPPORTED - (SentrySystemWrapper *)systemWrapper SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK { - SENTRY_LAZY_INIT(_systemWrapper, [[SentrySystemWrapper alloc] init]); + SENTRY_LAZY_INIT(_systemWrapper, + [[SentrySystemWrapper alloc] + initWithProcessorCount:self.processInfoWrapper.processorCount]); } +#endif // SENTRY_TARGET_PROFILING_SUPPORTED - (SentryDispatchFactory *)dispatchFactory SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK { SENTRY_LAZY_INIT(_dispatchFactory, [[SentryDispatchFactory alloc] init]); } -- (id)dispatchQueueProvider SENTRY_DISABLE_THREAD_SANITIZER( - "double-checked lock produce false alarms") -{ - SENTRY_LAZY_INIT(_dispatchQueueProvider, [[SentryDispatchFactory alloc] init]); -} - - (SentryNSTimerFactory *)timerFactory SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK { SENTRY_LAZY_INIT(_timerFactory, [[SentryNSTimerFactory alloc] init]); @@ -453,4 +453,9 @@ - (SentrySessionTracker *)getSessionTrackerWithOptions:(SentryOptions *)options dateProvider:self.dateProvider notificationCenter:self.notificationCenterWrapper]; } + +- (id)objcRuntimeWrapper SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK +{ + SENTRY_LAZY_INIT(_objcRuntimeWrapper, [[SentryDefaultObjCRuntimeWrapper alloc] init]); +} @end diff --git a/Sources/Sentry/SentryDependencyContainerSwiftHelper.m b/Sources/Sentry/SentryDependencyContainerSwiftHelper.m index 8ee4bad1dd1..7f86418750b 100644 --- a/Sources/Sentry/SentryDependencyContainerSwiftHelper.m +++ b/Sources/Sentry/SentryDependencyContainerSwiftHelper.m @@ -1,7 +1,7 @@ #import "SentryDependencyContainerSwiftHelper.h" #import "SentryDependencyContainer.h" +#import "SentrySDK+Private.h" #import "SentrySwift.h" -#import "SentryUIApplication.h" @implementation SentryDependencyContainerSwiftHelper @@ -9,7 +9,7 @@ @implementation SentryDependencyContainerSwiftHelper + (NSArray *)windows { - return SentryDependencyContainer.sharedInstance.application.windows; + return [SentryDependencyContainer.sharedInstance.application getWindows]; } #endif // SENTRY_HAS_UIKIT @@ -19,4 +19,19 @@ + (void)dispatchSyncOnMainQueue:(void (^)(void))block [SentryDependencyContainer.sharedInstance.dispatchQueueWrapper dispatchSyncOnMainQueue:block]; } ++ (id)objcRuntimeWrapper +{ + return SentryDependencyContainer.sharedInstance.objcRuntimeWrapper; +} + ++ (SentryHub *)currentHub +{ + return SentrySDKInternal.currentHub; +} + ++ (SentryCrash *)crashReporter +{ + return SentryDependencyContainer.sharedInstance.crashReporter; +} + @end diff --git a/Sources/Sentry/SentryDevice.m b/Sources/Sentry/SentryDevice.m index edca69d4f2a..1c11ebd59d2 100644 --- a/Sources/Sentry/SentryDevice.m +++ b/Sources/Sentry/SentryDevice.m @@ -15,6 +15,8 @@ // #import "SentryDevice.h" +#import "SentryInternalDefines.h" + #import #if TARGET_OS_WATCH # import @@ -236,7 +238,7 @@ size_t size = sizeof(str); int cmd[2] = { CTL_KERN, KERN_OSVERSION }; if (SENTRY_LOG_ERRNO(sysctl(cmd, sizeof(cmd) / sizeof(*cmd), str, &size, NULL, 0)) == 0) { - return [NSString stringWithUTF8String:str]; + return SENTRY_UNWRAP_NULLABLE(NSString, [NSString stringWithUTF8String:str]); } return @""; } diff --git a/Sources/Sentry/SentryDiscardedEvent.m b/Sources/Sentry/SentryDiscardedEvent.m deleted file mode 100644 index 67374e634d4..00000000000 --- a/Sources/Sentry/SentryDiscardedEvent.m +++ /dev/null @@ -1,32 +0,0 @@ -#import "SentryDiscardedEvent.h" -#import "SentryDataCategoryMapper.h" -#import "SentryDiscardReasonMapper.h" - -NS_ASSUME_NONNULL_BEGIN - -@implementation SentryDiscardedEvent - -- (instancetype)initWithReason:(SentryDiscardReason)reason - category:(SentryDataCategory)category - quantity:(NSUInteger)quantity -{ - if (self = [super init]) { - _reason = reason; - _category = category; - _quantity = quantity; - } - return self; -} - -- (NSDictionary *)serialize -{ - return @{ - @"reason" : nameForSentryDiscardReason(self.reason), - @"category" : nameForSentryDataCategory(self.category), - @"quantity" : @(self.quantity) - }; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryDsn.m b/Sources/Sentry/SentryDsn.m index d9291018166..cc8a94d9afc 100644 --- a/Sources/Sentry/SentryDsn.m +++ b/Sources/Sentry/SentryDsn.m @@ -2,6 +2,7 @@ #import "SentryDsn.h" #import "SentryError.h" +#import "SentryInternalDefines.h" NS_ASSUME_NONNULL_BEGIN @@ -19,10 +20,11 @@ - (_Nullable instancetype)initWithString:(NSString *)dsnString { self = [super init]; if (self) { - _url = [self convertDsnString:dsnString didFailWithError:error]; - if (_url == nil) { + NSURL *_Nullable nullableUrl = [self convertDsnString:dsnString didFailWithError:error]; + if (nullableUrl == nil) { return nil; } + _url = SENTRY_UNWRAP_NULLABLE(NSURL, nullableUrl); } return self; } @@ -39,7 +41,7 @@ - (NSString *)getHash return output; } -#if !SDK_v9 +#if !SDK_V9 - (NSURL *)getStoreEndpoint { if (nil == _storeEndpoint) { @@ -51,7 +53,7 @@ - (NSURL *)getStoreEndpoint } return _storeEndpoint; } -#endif // !SDK_v9 +#endif // !SDK_V9 - (NSURL *)getEnvelopeEndpoint { @@ -102,7 +104,7 @@ - (NSURL *_Nullable)convertDsnString:(NSString *)dsnString errorMessage = @"URL scheme of DSN is missing"; url = nil; } - if (url != nil && ![allowedSchemes containsObject:url.scheme]) { + if (url != nil && ![allowedSchemes containsObject:SENTRY_UNWRAP_NULLABLE(NSURL, url).scheme]) { errorMessage = @"Unrecognized URL scheme in DSN"; url = nil; } diff --git a/Sources/Sentry/SentryDummyPrivateEmptyClass.m b/Sources/Sentry/SentryDummyPrivateEmptyClass.m new file mode 100644 index 00000000000..54fa4f47d54 --- /dev/null +++ b/Sources/Sentry/SentryDummyPrivateEmptyClass.m @@ -0,0 +1,11 @@ +#import + +// This class is required because SPM doesn't support header only targets + +NS_ASSUME_NONNULL_BEGIN + +@interface SentryPrivateDummyEmptyClass : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryDummyPublicEmptyClass.m b/Sources/Sentry/SentryDummyPublicEmptyClass.m new file mode 100644 index 00000000000..bca5d600306 --- /dev/null +++ b/Sources/Sentry/SentryDummyPublicEmptyClass.m @@ -0,0 +1,11 @@ +#import + +// This class is required because SPM doesn't support header only targets + +NS_ASSUME_NONNULL_BEGIN + +@interface SentryPublicDummyEmptyClass : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryEnvelope.m b/Sources/Sentry/SentryEnvelope.m deleted file mode 100644 index 0d844ac3b1e..00000000000 --- a/Sources/Sentry/SentryEnvelope.m +++ /dev/null @@ -1,326 +0,0 @@ -#import "SentryAttachment.h" -#import "SentryBreadcrumb.h" -#import "SentryClientReport.h" -#import "SentryEnvelope+Private.h" -#import "SentryEnvelopeAttachmentHeader.h" -#import "SentryEnvelopeItemHeader.h" -#import "SentryEnvelopeItemType.h" -#import "SentryEvent.h" -#import "SentryLogC.h" -#import "SentryMessage.h" -#import "SentryMsgPackSerializer.h" -#import "SentrySdkInfo.h" -#import "SentrySerialization.h" -#import "SentrySession.h" -#import "SentrySwift.h" -#import "SentryTransaction.h" - -NS_ASSUME_NONNULL_BEGIN - -@implementation SentryEnvelopeHeader - -// id can be null if no event in the envelope or attachment related to event -- (instancetype)initWithId:(SentryId *_Nullable)eventId -{ - self = [self initWithId:eventId traceContext:nil]; - return self; -} - -- (instancetype)initWithId:(nullable SentryId *)eventId - traceContext:(nullable SentryTraceContext *)traceContext -{ - SentrySdkInfo *sdkInfo = [SentrySdkInfo global]; - self = [self initWithId:eventId sdkInfo:sdkInfo traceContext:traceContext]; - return self; -} - -- (instancetype)initWithId:(nullable SentryId *)eventId - sdkInfo:(nullable SentrySdkInfo *)sdkInfo - traceContext:(nullable SentryTraceContext *)traceContext -{ - if (self = [super init]) { - _eventId = eventId; - _sdkInfo = sdkInfo; - _traceContext = traceContext; - } - - return self; -} - -+ (instancetype)empty -{ - return [[SentryEnvelopeHeader alloc] initWithId:nil traceContext:nil]; -} - -@end - -@implementation SentryEnvelopeItem - -- (instancetype)initWithHeader:(SentryEnvelopeItemHeader *)header data:(NSData *)data -{ - if (self = [super init]) { - _header = header; - _data = data; - } - return self; -} - -- (instancetype)initWithEvent:(SentryEvent *)event -{ - NSData *json = [SentrySerialization dataWithJSONObject:[event serialize]]; - - if (nil == json) { - // We don't know what caused the serialization to fail. - SentryEvent *errorEvent = [[SentryEvent alloc] initWithLevel:kSentryLevelWarning]; - - // Add some context to the event. We can only set simple properties otherwise we - // risk that the conversion fails again. - NSString *message = [NSString - stringWithFormat:@"JSON conversion error for event with message: '%@'", event.message]; - - errorEvent.message = [[SentryMessage alloc] initWithFormatted:message]; - errorEvent.releaseName = event.releaseName; - errorEvent.environment = event.environment; - errorEvent.platform = event.platform; - errorEvent.timestamp = event.timestamp; - - // We accept the risk that this simple serialization fails. Therefore we ignore the - // error on purpose. - json = [SentrySerialization dataWithJSONObject:[errorEvent serialize]]; - } - - // event.type can be nil and the server infers error if there's a stack trace, otherwise - // default. In any case in the envelope type it should be event. Except for transactions - NSString *envelopeType = [event.type isEqualToString:SentryEnvelopeItemTypeTransaction] - ? SentryEnvelopeItemTypeTransaction - : [event.type isEqualToString:SentryEnvelopeItemTypeFeedback] - ? SentryEnvelopeItemTypeFeedback - : SentryEnvelopeItemTypeEvent; - - return [self initWithHeader:[[SentryEnvelopeItemHeader alloc] initWithType:envelopeType - length:json.length] - data:json]; -} - -- (instancetype)initWithSession:(SentrySession *)session -{ - NSData *json = [NSJSONSerialization dataWithJSONObject:[session serialize] options:0 error:nil]; - return [self - initWithHeader:[[SentryEnvelopeItemHeader alloc] initWithType:SentryEnvelopeItemTypeSession - length:json.length] - data:json]; -} - -#if !SDK_V9 -- (instancetype)initWithUserFeedback:(SentryUserFeedback *)userFeedback -{ - NSError *error = nil; - NSData *json = [NSJSONSerialization dataWithJSONObject:[userFeedback serialize] - options:0 - error:&error]; - - if (nil != error) { - SENTRY_LOG_ERROR(@"Couldn't serialize user feedback."); - json = [NSData new]; - } - - return [self initWithHeader:[[SentryEnvelopeItemHeader alloc] - initWithType:SentryEnvelopeItemTypeUserFeedback - length:json.length] - data:json]; -} -#endif // !SDK_V9 - -- (instancetype)initWithClientReport:(SentryClientReport *)clientReport -{ - NSError *error = nil; - NSData *json = [NSJSONSerialization dataWithJSONObject:[clientReport serialize] - options:0 - error:&error]; - - if (nil != error) { - SENTRY_LOG_ERROR(@"Couldn't serialize client report."); - json = [NSData new]; - } - - return [self initWithHeader:[[SentryEnvelopeItemHeader alloc] - initWithType:SentryEnvelopeItemTypeClientReport - length:json.length] - data:json]; -} - -- (_Nullable instancetype)initWithAttachment:(SentryAttachment *)attachment - maxAttachmentSize:(NSUInteger)maxAttachmentSize -{ - NSData *data = nil; - if (nil != attachment.data) { - if (attachment.data.length > maxAttachmentSize) { - SENTRY_LOG_DEBUG( - @"Dropping attachment with filename '%@', because the size of the passed data with " - @"%lu bytes is bigger than the maximum allowed attachment size of %lu bytes.", - attachment.filename, (unsigned long)attachment.data.length, - (unsigned long)maxAttachmentSize); - return nil; - } - -#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI - if ([NSProcessInfo.processInfo.arguments - containsObject:@"--io.sentry.base64-attachment-data"]) { - data = [[attachment.data base64EncodedStringWithOptions:0] - dataUsingEncoding:NSUTF8StringEncoding]; - } else { - data = attachment.data; - } -#else - data = attachment.data; -#endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI - } else if (nil != attachment.path) { - - NSError *error = nil; - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSDictionary *attr = - [fileManager attributesOfItemAtPath:attachment.path error:&error]; - - if (nil != error) { - SENTRY_LOG_ERROR(@"Couldn't check file size of attachment with path: %@. Error: %@", - attachment.path, error.localizedDescription); - - return nil; - } - - unsigned long long fileSize = [attr fileSize]; - - if (fileSize > maxAttachmentSize) { - SENTRY_LOG_DEBUG( - @"Dropping attachment, because the size of the it located at '%@' with %llu bytes " - @"is bigger than the maximum allowed attachment size of %lu bytes.", - attachment.path, fileSize, (unsigned long)maxAttachmentSize); - return nil; - } - -#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI - if ([NSProcessInfo.processInfo.arguments - containsObject:@"--io.sentry.base64-attachment-data"]) { - data = [[[[NSFileManager defaultManager] contentsAtPath:attachment.path] - base64EncodedStringWithOptions:0] dataUsingEncoding:NSUTF8StringEncoding]; - } else { - data = [[NSFileManager defaultManager] contentsAtPath:attachment.path]; - } -#else - data = [[NSFileManager defaultManager] contentsAtPath:attachment.path]; -#endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI - } - - if (data == nil) { - SENTRY_LOG_ERROR(@"Couldn't init Attachment."); - return nil; - } - - SentryEnvelopeItemHeader *itemHeader = - [[SentryEnvelopeAttachmentHeader alloc] initWithType:SentryEnvelopeItemTypeAttachment - length:data.length - filename:attachment.filename - contentType:attachment.contentType - attachmentType:attachment.attachmentType]; - - return [self initWithHeader:itemHeader data:data]; -} - -- (nullable instancetype)initWithReplayEvent:(SentryReplayEvent *)replayEvent - replayRecording:(SentryReplayRecording *)replayRecording - video:(NSURL *)videoURL -{ - NSData *replayEventData = [SentrySerialization dataWithJSONObject:[replayEvent serialize]]; - NSData *recording = [SentrySerialization dataWithReplayRecording:replayRecording]; - NSURL *envelopeContentUrl = - [[videoURL URLByDeletingPathExtension] URLByAppendingPathExtension:@"dat"]; - - BOOL success = [SentryMsgPackSerializer serializeDictionaryToMessagePack:@{ - @"replay_event" : replayEventData, - @"replay_recording" : recording, - @"replay_video" : videoURL - } - intoFile:envelopeContentUrl]; - if (success == NO) { - SENTRY_LOG_ERROR(@"Could not create MessagePack for session replay envelope item."); - return nil; - } - - NSData *envelopeItemContent = [NSData dataWithContentsOfURL:envelopeContentUrl]; - - NSError *error; - if (![NSFileManager.defaultManager removeItemAtURL:envelopeContentUrl error:&error]) { - SENTRY_LOG_ERROR(@"Cound not delete temporary replay content from disk: %@", error); - } - return [self initWithHeader:[[SentryEnvelopeItemHeader alloc] - initWithType:SentryEnvelopeItemTypeReplayVideo - length:envelopeItemContent.length] - data:envelopeItemContent]; -} - -@end - -@implementation SentryEnvelope - -- (instancetype)initWithSession:(SentrySession *)session -{ - SentryEnvelopeItem *item = [[SentryEnvelopeItem alloc] initWithSession:session]; - return [self initWithHeader:[[SentryEnvelopeHeader alloc] initWithId:nil] singleItem:item]; -} - -- (instancetype)initWithSessions:(NSArray *)sessions -{ - NSMutableArray *envelopeItems = [[NSMutableArray alloc] initWithCapacity:sessions.count]; - for (int i = 0; i < sessions.count; ++i) { - SentryEnvelopeItem *item = - [[SentryEnvelopeItem alloc] initWithSession:[sessions objectAtIndex:i]]; - [envelopeItems addObject:item]; - } - return [self initWithHeader:[[SentryEnvelopeHeader alloc] initWithId:nil] items:envelopeItems]; -} - -- (instancetype)initWithEvent:(SentryEvent *)event -{ - SentryEnvelopeItem *item = [[SentryEnvelopeItem alloc] initWithEvent:event]; - return [self initWithHeader:[[SentryEnvelopeHeader alloc] initWithId:event.eventId] - singleItem:item]; -} - -#if !SDK_V9 -- (instancetype)initWithUserFeedback:(SentryUserFeedback *)userFeedback -{ - SentryEnvelopeItem *item = [[SentryEnvelopeItem alloc] initWithUserFeedback:userFeedback]; - - return [self initWithHeader:[[SentryEnvelopeHeader alloc] initWithId:userFeedback.eventId] - singleItem:item]; -} -#endif // !SDK_V9 - -- (instancetype)initWithId:(SentryId *_Nullable)id singleItem:(SentryEnvelopeItem *)item -{ - return [self initWithHeader:[[SentryEnvelopeHeader alloc] initWithId:id] singleItem:item]; -} - -- (instancetype)initWithId:(SentryId *_Nullable)id items:(NSArray *)items -{ - return [self initWithHeader:[[SentryEnvelopeHeader alloc] initWithId:id] items:items]; -} - -- (instancetype)initWithHeader:(SentryEnvelopeHeader *)header singleItem:(SentryEnvelopeItem *)item -{ - return [self initWithHeader:header items:@[ item ]]; -} - -- (instancetype)initWithHeader:(SentryEnvelopeHeader *)header - items:(NSArray *)items -{ - if (self = [super init]) { - _header = header; - _items = items; - } - return self; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryEnvelopeAttachmentHeader.m b/Sources/Sentry/SentryEnvelopeAttachmentHeader.m index 309354107c8..23b50c5c90a 100644 --- a/Sources/Sentry/SentryEnvelopeAttachmentHeader.m +++ b/Sources/Sentry/SentryEnvelopeAttachmentHeader.m @@ -1,5 +1,5 @@ #import "SentryEnvelopeAttachmentHeader.h" -#import "SentryEnvelope+Private.h" +#import "SentryModels+Serializable.h" @implementation SentryEnvelopeAttachmentHeader diff --git a/Sources/Sentry/SentryEnvelopeHeaderHelper.m b/Sources/Sentry/SentryEnvelopeHeaderHelper.m new file mode 100644 index 00000000000..00a8723b3e1 --- /dev/null +++ b/Sources/Sentry/SentryEnvelopeHeaderHelper.m @@ -0,0 +1,12 @@ +#import "SentryEnvelopeHeaderHelper.h" +#import "SentrySDKInternal.h" +#import "SentrySwift.h" + +@implementation SentryEnvelopeHeaderHelper + ++ (SentryIdWrapper *)headerIdFromEvent:(SentryEvent *)event +{ + return [[SentryIdWrapper alloc] initWithId:event.eventId.sentryIdString]; +} + +@end diff --git a/Sources/Sentry/SentryEnvelopeRateLimit.m b/Sources/Sentry/SentryEnvelopeRateLimit.m index 5d09800c7a2..12a4c7913ba 100644 --- a/Sources/Sentry/SentryEnvelopeRateLimit.m +++ b/Sources/Sentry/SentryEnvelopeRateLimit.m @@ -1,8 +1,8 @@ #import "SentryEnvelopeRateLimit.h" #import "SentryDataCategoryMapper.h" -#import "SentryEnvelope.h" #import "SentryEnvelopeItemHeader.h" #import "SentryRateLimits.h" +#import "SentrySwift.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/Sentry/SentryEvent.m b/Sources/Sentry/SentryEvent.m index 56640378899..aa3aeadbb77 100644 --- a/Sources/Sentry/SentryEvent.m +++ b/Sources/Sentry/SentryEvent.m @@ -9,11 +9,13 @@ #import "SentryLevelMapper.h" #import "SentryMessage.h" #import "SentryMeta.h" +#import "SentryModels+Serializable.h" #import "SentryNSDictionarySanitize.h" #import "SentryRequest.h" #import "SentryStacktrace.h" #import "SentrySwift.h" #import "SentryThread.h" +#import "SentryUser+Serialize.h" #import "SentryUser.h" #if SENTRY_HAS_METRIC_KIT @@ -201,7 +203,8 @@ - (BOOL)isMetricKitEvent SentryException *exception = self.exceptions[0]; if (exception.mechanism != nil && - [metricKitMechanisms containsObject:exception.mechanism.type]) { + [metricKitMechanisms + containsObject:SENTRY_UNWRAP_NULLABLE(NSString, exception.mechanism).type]) { return YES; } else { return NO; @@ -214,7 +217,9 @@ - (BOOL)isAppHangEvent { return self.exceptions.count == 1 && [SentryAppHangTypeMapper - isExceptionTypeAppHangWithExceptionType:self.exceptions.firstObject.type]; + isExceptionTypeAppHangWithExceptionType:SENTRY_UNWRAP_NULLABLE( + NSString, self.exceptions.firstObject) + .type]; } @end diff --git a/Sources/Sentry/SentryException.m b/Sources/Sentry/SentryException.m index 6fdc4143226..c868449093b 100644 --- a/Sources/Sentry/SentryException.m +++ b/Sources/Sentry/SentryException.m @@ -1,5 +1,6 @@ #import "SentryException.h" #import "SentryMechanism.h" +#import "SentryModels+Serializable.h" #import "SentryStacktrace.h" #import "SentryThread.h" diff --git a/Sources/Sentry/SentryExtraContextProvider.h b/Sources/Sentry/SentryExtraContextProvider.h index a8db1b3c11d..086760056c9 100644 --- a/Sources/Sentry/SentryExtraContextProvider.h +++ b/Sources/Sentry/SentryExtraContextProvider.h @@ -5,12 +5,8 @@ #endif @class SentryCrashWrapper; -@class SentryNSProcessInfoWrapper; -@class SentryUIDeviceWrapper; - -#if TARGET_OS_IOS && SENTRY_HAS_UIKIT -@class SentryUIDeviceWrapper; -#endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT +@protocol SentryUIDeviceWrapper; +@protocol SentryProcessInfoSource; NS_ASSUME_NONNULL_BEGIN @@ -21,9 +17,9 @@ NS_ASSUME_NONNULL_BEGIN SENTRY_NO_INIT - (instancetype)initWithCrashWrapper:(SentryCrashWrapper *)crashWrapper - processInfoWrapper:(SentryNSProcessInfoWrapper *)processInfoWrapper + processInfoWrapper:(id)processInfoWrapper #if TARGET_OS_IOS && SENTRY_HAS_UIKIT - deviceWrapper:(SentryUIDeviceWrapper *)deviceWrapper + deviceWrapper:(id)deviceWrapper #endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT ; diff --git a/Sources/Sentry/SentryExtraContextProvider.m b/Sources/Sentry/SentryExtraContextProvider.m index 726e38874fa..7ab3250455a 100644 --- a/Sources/Sentry/SentryExtraContextProvider.m +++ b/Sources/Sentry/SentryExtraContextProvider.m @@ -1,9 +1,7 @@ #import "SentryExtraContextProvider.h" #import "SentryCrashIntegration.h" -#import "SentryCrashWrapper.h" #import "SentryLogC.h" -#import "SentryNSProcessInfoWrapper.h" -#import "SentryUIDeviceWrapper.h" +#import "SentrySwift.h" NSString *const kSentryProcessInfoThermalStateNominal = @"nominal"; NSString *const kSentryProcessInfoThermalStateFair = @"fair"; @@ -13,10 +11,10 @@ @interface SentryExtraContextProvider () @property (nonatomic, strong) SentryCrashWrapper *crashWrapper; -@property (nonatomic, strong) SentryNSProcessInfoWrapper *processInfoWrapper; +@property (nonatomic, strong) id processInfoWrapper; #if TARGET_OS_IOS && SENTRY_HAS_UIKIT -@property (nonatomic, strong) SentryUIDeviceWrapper *deviceWrapper; +@property (nonatomic, strong) id deviceWrapper; #endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT @end @@ -26,7 +24,7 @@ @implementation SentryExtraContextProvider - (instancetype)initWithCrashWrapper:(id)crashWrapper processInfoWrapper:(id)processInfoWrapper #if TARGET_OS_IOS && SENTRY_HAS_UIKIT - deviceWrapper:(SentryUIDeviceWrapper *)deviceWrapper + deviceWrapper:(id)deviceWrapper #endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT { if (self = [super init]) { diff --git a/Sources/Sentry/SentryFeedbackAPI.m b/Sources/Sentry/SentryFeedbackAPI.m index c9555063875..2459bb81bf4 100644 --- a/Sources/Sentry/SentryFeedbackAPI.m +++ b/Sources/Sentry/SentryFeedbackAPI.m @@ -19,8 +19,8 @@ @implementation SentryFeedbackAPI - (void)showWidget { if (@available(iOS 13.0, *)) { - SentryUserFeedbackIntegration *feedback = - [[SentrySDK currentHub] getInstalledIntegration:[SentryUserFeedbackIntegration class]]; + SentryUserFeedbackIntegration *feedback = [[SentrySDKInternal currentHub] + getInstalledIntegration:[SentryUserFeedbackIntegration class]]; [feedback showWidget]; } else { SENTRY_LOG_WARN(@"Sentry User Feedback is only available on iOS 13 or later."); @@ -30,8 +30,8 @@ - (void)showWidget - (void)hideWidget { if (@available(iOS 13.0, *)) { - SentryUserFeedbackIntegration *feedback = - [SentrySDK.currentHub getInstalledIntegration:[SentryUserFeedbackIntegration class]]; + SentryUserFeedbackIntegration *feedback = [SentrySDKInternal.currentHub + getInstalledIntegration:[SentryUserFeedbackIntegration class]]; [feedback hideWidget]; } else { SENTRY_LOG_WARN(@"Sentry User Feedback is only available on iOS 13 or later."); diff --git a/Sources/Sentry/SentryFileIOTracker.m b/Sources/Sentry/SentryFileIOTracker.m index 8602c6954a2..4a7f148bf57 100644 --- a/Sources/Sentry/SentryFileIOTracker.m +++ b/Sources/Sentry/SentryFileIOTracker.m @@ -7,7 +7,6 @@ #import "SentryHub+Private.h" #import "SentryInternalDefines.h" #import "SentryLogC.h" -#import "SentryNSProcessInfoWrapper.h" #import "SentryOptions.h" #import "SentrySDK+Private.h" #import "SentryScope+Private.h" @@ -26,7 +25,7 @@ @interface SentryFileIOTracker () @property (nonatomic, assign) BOOL isEnabled; @property (nonatomic, strong) NSMutableSet *processingData; @property (nonatomic, strong) SentryThreadInspector *threadInspector; -@property (nonatomic, strong) SentryNSProcessInfoWrapper *processInfoWrapper; +@property (nonatomic, strong) id processInfoWrapper; @end @@ -46,7 +45,7 @@ + (instancetype _Nullable)sharedInstance } - (instancetype)initWithThreadInspector:(SentryThreadInspector *)threadInspector - processInfoWrapper:(SentryNSProcessInfoWrapper *)processInfoWrapper + processInfoWrapper:(id)processInfoWrapper { if (self = [super init]) { _processInfoWrapper = processInfoWrapper; @@ -209,7 +208,7 @@ - (BOOL)measureNSFileManagerCreateFileAtPath:(NSString *)path } NSString *spanDescription = [self transactionDescriptionForFile:path fileSize:size]; - id _Nullable currentSpan = [SentrySDK.currentHub.scope span]; + id _Nullable currentSpan = [SentrySDKInternal.currentHub.scope span]; if (currentSpan == NULL) { SENTRY_LOG_DEBUG(@"No transaction bound to scope. Won't track file IO operation."); return nil; @@ -322,7 +321,7 @@ - (void)finishTrackingNSData:(NSData *)data span:(id)span - (BOOL)ignoreFile:(NSString *)path { - SentryFileManager *fileManager = [SentrySDK.currentHub getClient].fileManager; + SentryFileManager *fileManager = [SentrySDKInternal.currentHub getClient].fileManager; return fileManager.sentryPath != nil && [path hasPrefix:fileManager.sentryPath]; } diff --git a/Sources/Sentry/SentryFileManager.m b/Sources/Sentry/SentryFileManager.m index b2ec7972987..4187cccdfbf 100644 --- a/Sources/Sentry/SentryFileManager.m +++ b/Sources/Sentry/SentryFileManager.m @@ -1,12 +1,11 @@ #import "SentryFileManager.h" -#import "SentryAppState.h" #import "SentryDataCategoryMapper.h" #import "SentryDateUtils.h" #import "SentryDependencyContainer.h" #import "SentryDsn.h" -#import "SentryEnvelope.h" #import "SentryEnvelopeItemHeader.h" #import "SentryError.h" +#import "SentryEvent+Serialize.h" #import "SentryEvent.h" #import "SentryInternalDefines.h" #import "SentryLogC.h" @@ -74,13 +73,13 @@ void _non_thread_safe_removeFileAtPath(NSString *path) { - NSError *error = nil; + NSError *_Nullable error = nil; NSFileManager *fileManager = [NSFileManager defaultManager]; if ([fileManager removeItemAtPath:path error:&error]) { SENTRY_LOG_DEBUG(@"Successfully deleted file at %@", path); } else if (error.code == NSFileNoSuchFileError) { SENTRY_LOG_DEBUG(@"No file to delete at %@", path); - } else if (isErrorPathTooLong(error)) { + } else if (error != NULL && isErrorPathTooLong(SENTRY_UNWRAP_NULLABLE(NSError, error))) { SENTRY_LOG_FATAL(@"Failed to remove file, path is too long: %@", path); } else { SENTRY_LOG_ERROR(@"Error occurred while deleting file at %@ because of %@", path, error); @@ -91,7 +90,9 @@ @interface SentryFileManager () +@property (nonatomic, strong) id dateProvider; @property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueue; + @property (nonatomic, copy) NSString *basePath; @property (nonatomic, copy) NSString *sentryPath; @property (nonatomic, copy) NSString *eventsPath; @@ -116,19 +117,15 @@ @interface SentryFileManager () @implementation SentryFileManager -- (nullable instancetype)initWithOptions:(SentryOptions *)options error:(NSError **)error -{ - return [self initWithOptions:options - dispatchQueueWrapper:SentryDependencyContainer.sharedInstance.dispatchQueueWrapper - error:error]; -} - - (nullable instancetype)initWithOptions:(SentryOptions *)options + dateProvider:(id)dateProvider dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper error:(NSError **)error { if (self = [super init]) { + self.dateProvider = dateProvider; self.dispatchQueue = dispatchQueueWrapper; + [self createPathsWithOptions:options]; // Remove old cached events for versions before 6.0.0 @@ -158,7 +155,25 @@ - (void)createPathsWithOptions:(SentryOptions *)options SENTRY_LOG_DEBUG(@"SentryFileManager.cachePath: %@", cachePath); self.basePath = [cachePath stringByAppendingPathComponent:@"io.sentry"]; - self.sentryPath = [self.basePath stringByAppendingPathComponent:[options.parsedDsn getHash]]; + + NSString *_Nullable nullableDsnHash = [options.parsedDsn getHash]; +#if !SENTRY_TEST && !SENTRY_TEST_CI + if (nullableDsnHash == nil) { + SENTRY_LOG_FATAL(@"No DSN provided, using base path for envelopes: %@", self.basePath); + } +#endif // !SENTRY_TEST && !SENTRY_TEST_CI + + // We decided against changing the `sentryPath` and use a null fallback instead, because this + // has been broken for a long time and the impact of changing the base path can result in + // critical issues. + // + // Instead we silence the nullability warning and let `stringByAppendingPathComponent` handle + // the null case. + // + // Full discussion in https://github.com/getsentry/sentry-cocoa/pull/5737 + self.sentryPath = [self.basePath + stringByAppendingPathComponent:SENTRY_UNWRAP_NULLABLE(NSString, nullableDsnHash)]; + self.currentSessionFilePath = [self.sentryPath stringByAppendingPathComponent:@"session.current"]; self.crashedSessionFilePath = @@ -233,7 +248,7 @@ - (nullable NSString *)getEnvelopesPath:(NSString *)filePath return nil; } - NSError *error = nil; + NSError *_Nullable error = nil; NSDictionary *dict = [[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:&error]; if (error != nil) { @@ -295,7 +310,7 @@ - (void)deleteOldEnvelopeItems - (void)deleteAllEnvelopes { [self removeFileAtPath:self.envelopesPath]; - NSError *error; + NSError *_Nullable error; if (!createDirectoryIfNotExists(self.envelopesPath, &error)) { SENTRY_LOG_ERROR(@"Couldn't create envelopes path."); } @@ -355,7 +370,12 @@ - (void)storeTimestampLastInForeground:(NSDate *)timestamp NSString *timestampString = sentry_toIso8601String(timestamp); SENTRY_LOG_DEBUG(@"Persisting lastInForeground: %@", timestampString); @synchronized(self.lastInForegroundFilePath) { - if (![self writeData:[timestampString dataUsingEncoding:NSUTF8StringEncoding] + NSData *_Nullable nullableData = [timestampString dataUsingEncoding:NSUTF8StringEncoding]; + if (nullableData == nil) { + SENTRY_LOG_ERROR(@"Failed to convert lastInForeground timestamp to data."); + return; + } + if (![self writeData:SENTRY_UNWRAP_NULLABLE(NSData, nullableData) toPath:self.lastInForegroundFilePath]) { SENTRY_LOG_WARN(@"Failed to store timestamp of last foreground event."); } @@ -491,7 +511,7 @@ - (NSArray *)readPreviousBreadcrumbs continue; } - NSError *error; + NSError *_Nullable error; NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error]; @@ -535,7 +555,14 @@ - (void)storeTimezoneOffset:(NSInteger)offset NSString *timezoneOffsetString = [NSString stringWithFormat:@"%ld", (long)offset]; SENTRY_LOG_DEBUG(@"Persisting timezone offset: %@", timezoneOffsetString); @synchronized(self.timezoneOffsetFilePath) { - if (![self writeData:[timezoneOffsetString dataUsingEncoding:NSUTF8StringEncoding] + NSData *_Nullable nullableData = + [timezoneOffsetString dataUsingEncoding:NSUTF8StringEncoding]; + if (nullableData == nil) { + SENTRY_LOG_ERROR(@"Failed to convert timezone offset to data."); + return; + } + + if (![self writeData:SENTRY_UNWRAP_NULLABLE(NSData, nullableData) toPath:self.timezoneOffsetFilePath]) { SENTRY_LOG_WARN(@"Failed to store timezone offset."); } @@ -613,7 +640,7 @@ - (nullable NSData *)readDataFromPath:(NSString *)path - (BOOL)writeData:(NSData *)data toPath:(NSString *)path { - NSError *error; + NSError *_Nullable error; if (!createDirectoryIfNotExists(self.sentryPath, &error)) { SENTRY_LOG_ERROR(@"File I/O not available at path %@: %@", path, error); return NO; @@ -645,7 +672,7 @@ - (void)removeFileAtPath:(NSString *)path return @[]; } - NSError *error = nil; + NSError *_Nullable error = nil; NSArray *storedFiles = [fileManager contentsOfDirectoryAtPath:path error:&error]; if (error != nil) { SENTRY_LOG_ERROR(@"Couldn't load files in folder %@: %@", path, error); @@ -674,13 +701,14 @@ - (BOOL)isDirectory:(NSString *)path // For iOS apps and macOS apps with sandboxing, this path will be scoped for the current // app. For macOS apps without sandboxing, this path is not scoped and will be shared // between all apps. - NSString *_Nullable cachesDirectory + NSString *_Nullable nullableCachesDirectory = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) .firstObject; - if (cachesDirectory == nil) { + if (nullableCachesDirectory == nil) { SENTRY_LOG_WARN(@"No caches directory location reported."); return; } + NSString *_Nonnull cachesDirectory = (NSString *_Nonnull)nullableCachesDirectory; // We need to ensure our own scoped directory so that this path is not shared between other // apps on the same system. @@ -767,7 +795,7 @@ - (BOOL)isDirectory:(NSString *)path return nil; } - return [cachesDirectory stringByAppendingPathComponent:identifier]; + return [cachesDirectory stringByAppendingPathComponent:(NSString *_Nonnull)identifier]; } NSString *_Nullable sentryStaticBasePath(void) @@ -789,7 +817,12 @@ - (BOOL)isDirectory:(NSString *)path void removeSentryStaticBasePath(void) { - _non_thread_safe_removeFileAtPath(sentryStaticBasePath()); + NSString *_Nullable basePath = sentryStaticBasePath(); + if (basePath == nil) { + SENTRY_LOG_DEBUG(@"No base path available to remove."); + return; + } + _non_thread_safe_removeFileAtPath((NSString *_Nonnull)basePath); } #endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) @@ -808,7 +841,7 @@ - (BOOL)isDirectory:(NSString *)path SENTRY_LOG_WARN(@"No location available to write a launch profiling config."); return; } - NSError *error; + NSError *_Nullable error; if (!createDirectoryIfNotExists(basePath, &error)) { SENTRY_LOG_ERROR( @"Can't create base path to store launch profile config file: %@", error); @@ -821,16 +854,28 @@ - (BOOL)isDirectory:(NSString *)path return sentryLaunchConfigFileURL; } -NSDictionary *_Nullable sentry_appLaunchProfileConfiguration(void) +NSDictionary *_Nullable sentry_persistedLaunchProfileConfigurationOptions( + void) { - NSURL *url = launchProfileConfigFileURL(); - if (![[NSFileManager defaultManager] fileExistsAtPath:url.path]) { + NSURL *_Nullable url = launchProfileConfigFileURL(); + if (url == nil) { + SENTRY_LOG_ERROR(@"Failed to construct the URL to retrieve launch profile configs.") + return nil; + } + NSString *_Nullable nullablePath = url.path; + if (nullablePath == nil) { + SENTRY_LOG_ERROR(@"Failed to construct the path to retrieve launch profile configs.") + return nil; + } + if (![[NSFileManager defaultManager] + fileExistsAtPath:SENTRY_UNWRAP_NULLABLE(NSString, nullablePath)]) { return nil; } - NSError *error; - NSDictionary *config = - [NSDictionary dictionaryWithContentsOfURL:url error:&error]; + NSError *_Nullable error; + NSDictionary *config = [NSDictionary + dictionaryWithContentsOfURL:SENTRY_UNWRAP_NULLABLE(NSURL, url) + error:&error]; if (error != nil) { SENTRY_LOG_ERROR( @@ -844,9 +889,14 @@ - (BOOL)isDirectory:(NSString *)path BOOL appLaunchProfileConfigFileExists(void) { - NSString *path = launchProfileConfigFileURL().path; + NSURL *_Nullable url = launchProfileConfigFileURL(); + if (url == nil) { + SENTRY_LOG_ERROR(@"Failed to construct the URL to check for launch profile configs.") + return NO; + } + NSString *_Nullable path = url.path; if (path == nil) { - SENTRY_LOG_DEBUG(@"Failed to construct the path to check for launch profile configs.") + SENTRY_LOG_ERROR(@"Failed to construct the path to check for launch profile configs.") return NO; } @@ -856,16 +906,34 @@ - (BOOL)isDirectory:(NSString *)path void writeAppLaunchProfilingConfigFile(NSMutableDictionary *config) { - NSError *error; - SENTRY_LOG_DEBUG(@"Writing launch profiling config file."); - SENTRY_CASSERT([config writeToURL:launchProfileConfigFileURL() error:&error], + NSURL *_Nullable url = launchProfileConfigFileURL(); + if (url == nil) { + SENTRY_LOG_ERROR(@"Failed to construct the URL to write launch profile configs."); + return; + } + SENTRY_LOG_DEBUG(@"Writing launch profiling config file at url %@", url); + + NSError *_Nullable error; + SENTRY_CASSERT([config writeToURL:SENTRY_UNWRAP_NULLABLE(NSURL, url) error:&error], @"Failed to write launch profile config file: %@.", error); } void removeAppLaunchProfilingConfigFile(void) { - _non_thread_safe_removeFileAtPath(launchProfileConfigFileURL().path); + NSURL *_Nullable url = launchProfileConfigFileURL(); + if (url == nil) { + SENTRY_LOG_ERROR(@"Failed to construct the URL to remove launch profile configs."); + return; + } + NSString *_Nullable path = url.path; + if (path == nil) { + SENTRY_LOG_ERROR(@"Failed to construct the path to remove launch profile configs."); + return; + } + + SENTRY_LOG_DEBUG(@"Removing launch profiling config file at path: %@", path); + _non_thread_safe_removeFileAtPath(SENTRY_UNWRAP_NULLABLE(NSString, path)); } #endif // SENTRY_TARGET_PROFILING_SUPPORTED @@ -939,7 +1007,7 @@ - (void)moveState:(NSString *)stateFilePath toPreviousState:(NSString *)previous // We first need to remove the old previous state file, // or we can't move the current state file to it. [self removeFileAtPath:previousStateFilePath]; - NSError *error = nil; + NSError *_Nullable error = nil; if (![fileManager moveItemAtPath:stateFilePath toPath:previousStateFilePath error:&error]) { // We don't want to log an error if the file doesn't exist. if (nil != error && error.code != NSFileNoSuchFileError) { @@ -965,8 +1033,7 @@ - (void)deleteOldEnvelopesFromAllSentryPaths - (void)deleteOldEnvelopesFromPath:(NSString *)envelopesPath { - NSTimeInterval now = - [[SentryDependencyContainer.sharedInstance.dateProvider date] timeIntervalSince1970]; + NSTimeInterval now = [[self.dateProvider date] timeIntervalSince1970]; for (NSString *path in [self allFilesInFolder:envelopesPath]) { NSString *fullPath = [envelopesPath stringByAppendingPathComponent:path]; @@ -1042,8 +1109,8 @@ - (NSString *)uniqueAscendingJsonName // %@ = NSString // For example 978307200.000000-00001-3FE8C3AE-EB9C-4BEB-868C-14B8D47C33DD.json return [NSString stringWithFormat:@"%f-%05lu-%@.json", - [[SentryDependencyContainer.sharedInstance.dateProvider date] timeIntervalSince1970], - (unsigned long)self.currentFileCounter++, [NSUUID UUID].UUIDString]; + [[self.dateProvider date] timeIntervalSince1970], (unsigned long)self.currentFileCounter++, + [NSUUID UUID].UUIDString]; } - (SentryFileContents *_Nullable)getFileContents:(NSString *)folderPath diff --git a/Sources/Sentry/SentryFrame.m b/Sources/Sentry/SentryFrame.m index c66ca71dcf0..499a9746050 100644 --- a/Sources/Sentry/SentryFrame.m +++ b/Sources/Sentry/SentryFrame.m @@ -1,5 +1,6 @@ #import "SentryFrame.h" #import "NSMutableDictionary+Sentry.h" +#import "SentryNSDictionarySanitize.h" NS_ASSUME_NONNULL_BEGIN @@ -27,6 +28,10 @@ - (instancetype)init [serializedData setValue:self.imageAddress forKey:@"image_addr"]; [serializedData setValue:self.instructionAddress forKey:@"instruction_addr"]; [serializedData setValue:self.platform forKey:@"platform"]; + [serializedData setValue:self.contextLine forKey:@"context_line"]; + [serializedData setValue:self.preContext forKey:@"pre_context"]; + [serializedData setValue:self.postContext forKey:@"post_context"]; + [serializedData setValue:sentry_sanitize(self.vars) forKey:@"vars"]; [SentryDictionary setBoolValue:self.inApp forKey:@"in_app" intoDictionary:serializedData]; [SentryDictionary setBoolValue:self.stackStart forKey:@"stack_start" diff --git a/Sources/Sentry/SentryFramesTracker.m b/Sources/Sentry/SentryFramesTracker.m index 034ed0b2a9e..3fdc8c69a8c 100644 --- a/Sources/Sentry/SentryFramesTracker.m +++ b/Sources/Sentry/SentryFramesTracker.m @@ -8,7 +8,7 @@ # import "SentryDisplayLinkWrapper.h" # import "SentryInternalCDefines.h" # import "SentryLogC.h" -# import "SentryNSNotificationCenterWrapper.h" +# import "SentryNotificationNames.h" # import "SentryProfilingConditionals.h" # import "SentrySwift.h" # import "SentryTime.h" @@ -34,7 +34,7 @@ @interface SentryFramesTracker () @property (nonatomic, strong, readonly) SentryDisplayLinkWrapper *displayLinkWrapper; @property (nonatomic, strong, readonly) id dateProvider; @property (nonatomic, strong, readonly) SentryDispatchQueueWrapper *dispatchQueueWrapper; -@property (nonatomic, strong) SentryNSNotificationCenterWrapper *notificationCenter; +@property (nonatomic, strong) id notificationCenter; @property (nonatomic, assign) CFTimeInterval previousFrameTimestamp; @property (nonatomic) uint64_t previousFrameSystemTimestamp; @property (nonatomic) uint64_t currentFrameRate; @@ -66,7 +66,7 @@ @implementation SentryFramesTracker { - (instancetype)initWithDisplayLinkWrapper:(SentryDisplayLinkWrapper *)displayLinkWrapper dateProvider:(id)dateProvider dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper - notificationCenter:(SentryNSNotificationCenterWrapper *)notificationCenter + notificationCenter:(id)notificationCenter keepDelayedFramesDuration:(CFTimeInterval)keepDelayedFramesDuration { if (self = [super init]) { @@ -138,11 +138,13 @@ - (void)start [self.notificationCenter addObserver:self selector:@selector(didBecomeActive) - name:SentryDidBecomeActiveNotification]; + name:SentryDidBecomeActiveNotification + object:nil]; [self.notificationCenter addObserver:self selector:@selector(willResignActive) - name:SentryWillResignActiveNotification]; + name:SentryWillResignActiveNotification + object:nil]; [self unpause]; } @@ -164,7 +166,8 @@ - (void)unpause } _isRunning = YES; - + // Reset the previous frame timestamp to avoid wrong metrics being collected + self.previousFrameTimestamp = SentryPreviousFrameInitialValue; [_displayLinkWrapper linkWithTarget:self selector:@selector(displayLinkCallback)]; } @@ -334,8 +337,10 @@ - (void)stop // Remove the observers with the most specific detail possible, see // https://developer.apple.com/documentation/foundation/nsnotificationcenter/1413994-removeobserver - [self.notificationCenter removeObserver:self name:SentryDidBecomeActiveNotification]; - [self.notificationCenter removeObserver:self name:SentryWillResignActiveNotification]; + [self.notificationCenter removeObserver:self name:SentryDidBecomeActiveNotification object:nil]; + [self.notificationCenter removeObserver:self + name:SentryWillResignActiveNotification + object:nil]; @synchronized(self.listeners) { [self.listeners removeAllObjects]; diff --git a/Sources/Sentry/SentryGeo.m b/Sources/Sentry/SentryGeo.m index b913713cbf8..8543f1c7641 100644 --- a/Sources/Sentry/SentryGeo.m +++ b/Sources/Sentry/SentryGeo.m @@ -1,4 +1,5 @@ #import "SentryGeo.h" +#import "SentryInternalDefines.h" #import "SentrySwift.h" NS_ASSUME_NONNULL_BEGIN @@ -46,7 +47,7 @@ - (BOOL)isEqual:(id _Nullable)other return NO; } - return [self isEqualToGeo:other]; + return [self isEqualToGeo:SENTRY_UNWRAP_NULLABLE(SentryGeo, other)]; } - (BOOL)isEqualToGeo:(SentryGeo *)geo diff --git a/Sources/Sentry/SentryHttpTransport.m b/Sources/Sentry/SentryHttpTransport.m index 32e658ac098..82fe1caa382 100644 --- a/Sources/Sentry/SentryHttpTransport.m +++ b/Sources/Sentry/SentryHttpTransport.m @@ -1,18 +1,14 @@ #import "SentryHttpTransport.h" -#import "SentryClientReport.h" #import "SentryDataCategory.h" #import "SentryDataCategoryMapper.h" #import "SentryDependencyContainer.h" #import "SentryDiscardReasonMapper.h" -#import "SentryDiscardedEvent.h" #import "SentryDsn.h" -#import "SentryEnvelope+Private.h" -#import "SentryEnvelope.h" #import "SentryEnvelopeItemHeader.h" -#import "SentryEnvelopeItemType.h" #import "SentryEnvelopeRateLimit.h" #import "SentryEvent.h" #import "SentryFileManager.h" +#import "SentryInternalDefines.h" #import "SentryLogC.h" #import "SentryNSURLRequestBuilder.h" #import "SentryOptions.h" @@ -32,7 +28,8 @@ @interface SentryHttpTransport () @property (nonatomic, strong) SentryFileManager *fileManager; @property (nonatomic, strong) id requestManager; @property (nonatomic, strong) SentryNSURLRequestBuilder *requestBuilder; -@property (nonatomic, strong) SentryOptions *options; +@property (nonatomic, strong) SentryDsn *dsn; +@property (nonatomic) BOOL sendClientReports; @property (nonatomic, strong) id rateLimits; @property (nonatomic, strong) SentryEnvelopeRateLimit *envelopeRateLimit; @property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueue; @@ -66,7 +63,8 @@ @interface SentryHttpTransport () @implementation SentryHttpTransport -- (id)initWithOptions:(SentryOptions *)options +- (id)initWithDsn:(SentryDsn *)dsn + sendClientReports:(BOOL)sendClientReports cachedEnvelopeSendDelay:(NSTimeInterval)cachedEnvelopeSendDelay dateProvider:(id)dateProvider fileManager:(SentryFileManager *)fileManager @@ -77,7 +75,8 @@ - (id)initWithOptions:(SentryOptions *)options dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper { if (self = [super init]) { - self.options = options; + self.dsn = dsn; + self.sendClientReports = sendClientReports; _cachedEnvelopeSendDelay = cachedEnvelopeSendDelay; self.requestManager = requestManager; self.requestBuilder = requestBuilder; @@ -161,7 +160,7 @@ - (void)recordLostEvent:(SentryDataCategory)category reason:(SentryDiscardReason)reason quantity:(NSUInteger)quantity { - if (!self.options.sendClientReports) { + if (!self.sendClientReports) { return; } @@ -174,8 +173,8 @@ - (void)recordLostEvent:(SentryDataCategory)category quantity = event.quantity + 1; } - event = [[SentryDiscardedEvent alloc] initWithReason:reason - category:category + event = [[SentryDiscardedEvent alloc] initWithReason:nameForSentryDiscardReason(reason) + category:nameForSentryDataCategory(category) quantity:quantity]; self.discardedEvents[key] = event; @@ -223,6 +222,12 @@ - (SentryFlushResult)flush:(NSTimeInterval)timeout intptr_t result = dispatch_group_wait(self.dispatchGroup, dispatchTimeout); + // Every `dispatch_group_enter` must have a corresponding `dispatch_group_leave`. + // If nobody called `stopFlushing`, we must call `dispatch_group_leave` here, because + // otherwise the dispatch group never leaves and the next time somebody calls flush, + // flush will always time out. + [self stopFlushing]; + if (result == 0) { SENTRY_LOG_DEBUG(@"Finished flushing."); return kSentryFlushResultSuccess; @@ -232,6 +237,17 @@ - (SentryFlushResult)flush:(NSTimeInterval)timeout } } +- (void)stopFlushing +{ + @synchronized(self) { + if (_isFlushing) { + SENTRY_LOG_DEBUG(@"Stop flushing."); + _isFlushing = NO; + dispatch_group_leave(self.dispatchGroup); + } + } +} + /** * SentryEnvelopeRateLimitDelegate. */ @@ -258,7 +274,7 @@ - (void)envelopeItemDeleted:(SentryEnvelopeItem *)envelopeItem - (SentryEnvelope *)addClientReportTo:(SentryEnvelope *)envelope { - if (!self.options.sendClientReports) { + if (!self.sendClientReports) { return envelope; } @@ -273,7 +289,8 @@ - (SentryEnvelope *)addClientReportTo:(SentryEnvelope *)envelope [self.discardedEvents removeAllObjects]; } - SentryClientReport *clientReport = [[SentryClientReport alloc] initWithDiscardedEvents:events]; + SentryClientReport *clientReport = + [[SentryClientReport alloc] initWithDiscardedEvents:events dateProvider:self.dateProvider]; SentryEnvelopeItem *clientReportEnvelopeItem = [[SentryEnvelopeItem alloc] initWithClientReport:clientReport]; @@ -339,14 +356,14 @@ - (void)sendAllCachedEnvelopes // We must set sentAt as close as possible to the transmission of the envelope to Sentry. rateLimitedEnvelope.header.sentAt = [self.dateProvider date]; - NSError *requestError = nil; + NSError *_Nullable requestError = nil; NSURLRequest *request = [self.requestBuilder createEnvelopeRequest:rateLimitedEnvelope - dsn:self.options.parsedDsn + dsn:self.dsn didFailWithError:&requestError]; if (nil == request || nil != requestError) { if (nil != requestError) { - SENTRY_LOG_DEBUG(@"Failed to build request: %@.", requestError); + SENTRY_LOG_FATAL(@"Failed to build request to send envelope: %@.", requestError); } [self recordLostEventFor:rateLimitedEnvelope.items]; [self deleteEnvelopeAndSendNext:envelopeFilePath]; @@ -360,7 +377,7 @@ - (void)deleteEnvelopeAndSendNext:(nullable NSString *)envelopePath { SENTRY_LOG_DEBUG(@"Deleting envelope and sending next."); if (envelopePath != nil) { - [self.fileManager removeFileAtPath:envelopePath]; + [self.fileManager removeFileAtPath:SENTRY_UNWRAP_NULLABLE(NSString, envelopePath)]; } @synchronized(self) { self.isSending = NO; @@ -400,7 +417,7 @@ - (void)sendEnvelope:(SentryEnvelope *)envelope return; } - [weakSelf.rateLimits update:response]; + [weakSelf.rateLimits update:SENTRY_UNWRAP_NULLABLE(NSHTTPURLResponse, response)]; if (response.statusCode == 200) { SENTRY_LOG_DEBUG(@"Envelope sent successfully!"); @@ -417,11 +434,7 @@ - (void)finishedSending { @synchronized(self) { self.isSending = NO; - if (self.isFlushing) { - SENTRY_LOG_DEBUG(@"Stop flushing."); - self.isFlushing = NO; - dispatch_group_leave(self.dispatchGroup); - } + [self stopFlushing]; } } @@ -431,7 +444,7 @@ - (void)recordLostEventFor:(NSArray *)items NSString *itemType = item.header.type; // We don't want to record a lost event when it's a client report. // It's fine to drop it silently. - if ([itemType isEqualToString:SentryEnvelopeItemTypeClientReport]) { + if ([itemType isEqualToString:SentryEnvelopeItemTypes.clientReport]) { continue; } SentryDataCategory category = sentryDataCategoryForEnvelopItemType(itemType); @@ -442,7 +455,7 @@ - (void)recordLostEventFor:(NSArray *)items - (void)recordLostSpans:(SentryEnvelopeItem *)envelopeItem reason:(SentryDiscardReason)reason { - if ([SentryEnvelopeItemTypeTransaction isEqualToString:envelopeItem.header.type]) { + if ([SentryEnvelopeItemTypes.transaction isEqualToString:envelopeItem.header.type]) { NSDictionary *_Nullable transactionJson = [SentrySerialization deserializeDictionaryFromJsonData:envelopeItem.data]; if (transactionJson == nil) { diff --git a/Sources/Sentry/SentryHub.m b/Sources/Sentry/SentryHub.m index f2ec986940c..602f4e68af6 100644 --- a/Sources/Sentry/SentryHub.m +++ b/Sources/Sentry/SentryHub.m @@ -1,17 +1,14 @@ #import "SentryClient+Private.h" -#import "SentryCrashWrapper.h" #import "SentryDependencyContainer.h" -#import "SentryEnvelope.h" #import "SentryEnvelopeItemHeader.h" -#import "SentryEnvelopeItemType.h" #import "SentryEvent+Private.h" #import "SentryFileManager.h" #import "SentryHub+Private.h" #import "SentryInstallation.h" #import "SentryIntegrationProtocol.h" +#import "SentryInternalDefines.h" #import "SentryLevelMapper.h" #import "SentryLogC.h" -#import "SentryNSTimerFactory.h" #import "SentryOptions+Private.h" #import "SentryPerformanceTracker.h" #import "SentryProfilingConditionals.h" @@ -21,7 +18,6 @@ #import "SentrySamplingContext.h" #import "SentryScope+Private.h" #import "SentrySerialization.h" -#import "SentrySession+Private.h" #import "SentrySwift.h" #import "SentryTraceOrigin.h" #import "SentryTracer.h" @@ -79,7 +75,7 @@ - (instancetype)initWithClient:(nullable SentryClient *)client _errorsBeforeSession = 0; if (_scope) { - [_crashWrapper enrichScope:_scope]; + [_crashWrapper enrichScope:SENTRY_UNWRAP_NULLABLE(SentryScope, _scope)]; } } @@ -194,7 +190,7 @@ - (void)closeCachedSessionWithTimestamp:(nullable NSDate *)timestamp [session endSessionAbnormalWithTimestamp:timestamp]; } else { SENTRY_LOG_DEBUG(@"Closing cached session as exited."); - [session endSessionExitedWithTimestamp:timestamp]; + [session endSessionExitedWithTimestamp:SENTRY_UNWRAP_NULLABLE(NSDate, timestamp)]; } [self deleteCurrentSession]; [client captureSession:session]; @@ -464,13 +460,13 @@ - (SentryTracer *)startTransactionWithContext:(SentryTransactionContext *)transa sampleRate:tracesSamplerDecision.sampleRate sampleRand:tracesSamplerDecision.sampleRand]; -#if SENTRY_TARGET_PROFILING_SUPPORTED +#if SENTRY_TARGET_PROFILING_SUPPORTED && !SDK_V9 if (![self.client.options isContinuousProfilingEnabled]) { SentrySamplerDecision *profilesSamplerDecision = sentry_sampleTraceProfile( samplingContext, tracesSamplerDecision, self.client.options); configuration.profilesSamplerDecision = profilesSamplerDecision; } -#endif // SENTRY_TARGET_PROFILING_SUPPORTED" +#endif // SENTRY_TARGET_PROFILING_SUPPORTED && !SDK_V9 SentryTracer *tracer = [[SentryTracer alloc] initWithTransactionContext:transactionContext hub:self @@ -558,21 +554,35 @@ - (void)captureFeedback:(SentryFeedback *)feedback } } +- (void)captureSerializedFeedback:(NSDictionary *)serializedFeedback + withEventId:(NSString *)feedbackEventId + attachments:(NSArray *)feedbackAttachments +{ + SentryClient *client = self.client; + if (client != nil) { + [client captureSerializedFeedback:serializedFeedback + withEventId:feedbackEventId + attachments:feedbackAttachments + scope:self.scope]; + } +} + - (void)addBreadcrumb:(SentryBreadcrumb *)crumb { SentryOptions *options = [[self client] options]; if (options.maxBreadcrumbs < 1) { return; } + SentryBreadcrumb *_Nullable nullableCrumb = crumb; SentryBeforeBreadcrumbCallback callback = [options beforeBreadcrumb]; if (callback != nil) { - crumb = callback(crumb); + nullableCrumb = callback(crumb); } - if (crumb == nil) { + if (nullableCrumb == nil) { SENTRY_LOG_DEBUG(@"Discarded Breadcrumb in `beforeBreadcrumb`"); return; } - [self.scope addBreadcrumb:crumb]; + [self.scope addBreadcrumb:SENTRY_UNWRAP_NULLABLE(SentryBreadcrumb, nullableCrumb)]; } - (nullable SentryClient *)getClient @@ -596,9 +606,9 @@ - (SentryScope *)scope _scope = [[SentryScope alloc] init]; } - [_crashWrapper enrichScope:_scope]; + [_crashWrapper enrichScope:SENTRY_UNWRAP_NULLABLE(SentryScope, _scope)]; } - return _scope; + return SENTRY_UNWRAP_NULLABLE(SentryScope, _scope); } } @@ -759,13 +769,15 @@ - (BOOL)envelopeContainsEventWithErrorOrHigher:(NSArray *) wasHandled:(BOOL *)handled; { for (SentryEnvelopeItem *item in items) { - if ([item.header.type isEqualToString:SentryEnvelopeItemTypeEvent]) { + if ([item.header.type isEqualToString:SentryEnvelopeItemTypes.event]) { // If there is no level the default is error - NSDictionary *_Nullable eventJson = + NSDictionary *_Nullable nullableEventJson = [SentrySerialization deserializeDictionaryFromJsonData:item.data]; - if (eventJson == nil) { + if (nullableEventJson == nil) { return NO; } + NSDictionary *_Nonnull eventJson + = SENTRY_UNWRAP_NULLABLE(NSDictionary, nullableEventJson); SentryLevel level = sentryLevelForString(eventJson[@"level"]); if (level >= kSentryLevelError) { @@ -839,10 +851,10 @@ - (void)unregisterSessionListener:(id)listener #pragma mark - Protected -- (NSMutableArray *)trimmedInstalledIntegrationNames +- (NSArray *)trimmedInstalledIntegrationNames { NSMutableArray *integrations = [NSMutableArray array]; - for (NSString *integration in SentrySDK.currentHub.installedIntegrationNames) { + for (NSString *integration in SentrySDKInternal.currentHub.installedIntegrationNames) { // Every integration starts with "Sentry" and ends with "Integration". To keep the // payload of the event small we remove both. NSString *withoutSentry = [integration stringByReplacingOccurrencesOfString:@"Sentry" diff --git a/Sources/Sentry/SentryInAppLogic.m b/Sources/Sentry/SentryInAppLogic.m deleted file mode 100644 index 74afcdd6511..00000000000 --- a/Sources/Sentry/SentryInAppLogic.m +++ /dev/null @@ -1,85 +0,0 @@ -#import "SentryInAppLogic.h" -#import "SentryLogC.h" -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryInAppLogic () - -@property (nonnull, readonly) NSArray *inAppExcludes; - -@end - -@implementation SentryInAppLogic - -- (instancetype)initWithInAppIncludes:(NSArray *)inAppIncludes - inAppExcludes:(NSArray *)inAppExcludes -{ - if (self = [super init]) { - NSMutableArray *includes = - [[NSMutableArray alloc] initWithCapacity:inAppIncludes.count]; - for (NSString *include in inAppIncludes) { - [includes addObject:include.lowercaseString]; - } - _inAppIncludes = includes; - - NSMutableArray *excludes = - [[NSMutableArray alloc] initWithCapacity:inAppExcludes.count]; - for (NSString *exclude in inAppExcludes) { - [excludes addObject:exclude.lowercaseString]; - } - _inAppExcludes = excludes; - } - - return self; -} - -- (BOOL)isInApp:(nullable NSString *)imageName -{ - if (nil == imageName) { - return NO; - } - - NSString *imageNameLastPathComponent = imageName.lastPathComponent.lowercaseString; - - for (NSString *inAppInclude in self.inAppIncludes) { - if ([SentryInAppLogic isImageNameLastPathComponentInApp:imageNameLastPathComponent - inAppInclude:inAppInclude]) - - return YES; - } - - for (NSString *inAppExclude in self.inAppExcludes) { - if ([imageNameLastPathComponent hasPrefix:inAppExclude]) - return NO; - } - - return NO; -} - -- (BOOL)isClassInApp:(Class)targetClass -{ - const char *imageName = class_getImageName(targetClass); - if (imageName == nil) - return NO; - - NSString *classImageName = [NSString stringWithCString:imageName encoding:NSUTF8StringEncoding]; - return [self isInApp:classImageName]; -} - -+ (BOOL)isImageNameInApp:(NSString *)imageName inAppInclude:(NSString *)inAppInclude -{ - return [SentryInAppLogic - isImageNameLastPathComponentInApp:imageName.lastPathComponent.lowercaseString - inAppInclude:inAppInclude.lowercaseString]; -} - -+ (BOOL)isImageNameLastPathComponentInApp:(NSString *)imageNameLastPathComponent - inAppInclude:(NSString *)inAppInclude -{ - return [imageNameLastPathComponent hasPrefix:inAppInclude]; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryLevelMapper.m b/Sources/Sentry/SentryLevelMapper.m index f9cf7ead754..1672add0600 100644 --- a/Sources/Sentry/SentryLevelMapper.m +++ b/Sources/Sentry/SentryLevelMapper.m @@ -3,7 +3,7 @@ NS_ASSUME_NONNULL_BEGIN SentryLevel -sentryLevelForString(NSString *string) +sentryLevelForString(NSString *_Nullable string) { return [SentryLevelHelper levelForName:string]; } diff --git a/Sources/Sentry/SentryMeasurementValue.m b/Sources/Sentry/SentryMeasurementValue.m deleted file mode 100644 index e91b38224e5..00000000000 --- a/Sources/Sentry/SentryMeasurementValue.m +++ /dev/null @@ -1,35 +0,0 @@ -#import "SentryMeasurementValue.h" - -NS_ASSUME_NONNULL_BEGIN - -@implementation SentryMeasurementValue - -- (instancetype)initWithValue:(NSNumber *)value -{ - if (self = [super init]) { - _value = value; - } - return self; -} - -- (instancetype)initWithValue:(NSNumber *)value unit:(SentryMeasurementUnit *)unit -{ - if (self = [super init]) { - _value = value; - _unit = unit; - } - return self; -} - -- (NSDictionary *)serialize -{ - if (self.unit != nil) { - return @{ @"value" : _value, @"unit" : _unit.unit }; - } else { - return @{ @"value" : _value }; - } -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryMechanism.m b/Sources/Sentry/SentryMechanism.m index 01245da7d5e..e7052c81b00 100644 --- a/Sources/Sentry/SentryMechanism.m +++ b/Sources/Sentry/SentryMechanism.m @@ -1,6 +1,7 @@ #import "SentryMechanism.h" #import "NSMutableDictionary+Sentry.h" #import "SentryMechanismMeta.h" +#import "SentryModels+Serializable.h" #import "SentryNSDictionarySanitize.h" #import "SentryNSError.h" diff --git a/Sources/Sentry/SentryMechanismMeta.m b/Sources/Sentry/SentryMechanismMeta.m index 3eaa14e85f6..caf3a928328 100644 --- a/Sources/Sentry/SentryMechanismMeta.m +++ b/Sources/Sentry/SentryMechanismMeta.m @@ -1,4 +1,5 @@ #import "SentryMechanismMeta.h" +#import "SentryModels+Serializable.h" #import "SentryNSDictionarySanitize.h" #import "SentryNSError.h" diff --git a/Sources/Sentry/SentryMeta.m b/Sources/Sentry/SentryMeta.m index 4c0a87651ea..af7fbc0db42 100644 --- a/Sources/Sentry/SentryMeta.m +++ b/Sources/Sentry/SentryMeta.m @@ -5,7 +5,7 @@ @implementation SentryMeta // Don't remove the static keyword. If you do the compiler adds the constant name to the global // symbol table and it might clash with other constants. When keeping the static keyword the // compiler replaces all occurrences with the value. -static NSString *versionString = @"8.53.2"; +static NSString *versionString = @"8.56.0"; static NSString *sdkName = @"sentry.cocoa"; + (NSString *)versionString diff --git a/Sources/Sentry/SentryMetricKitIntegration.m b/Sources/Sentry/SentryMetricKitIntegration.m index ee0585cdfea..7bb41352ff2 100644 --- a/Sources/Sentry/SentryMetricKitIntegration.m +++ b/Sources/Sentry/SentryMetricKitIntegration.m @@ -14,7 +14,6 @@ # import # import # import -# import # import # import # import @@ -509,7 +508,7 @@ - (SentryStacktrace *)convertMXFramesToSentryStacktrace:(NSEnumerator * +serializeContinuousProfileMetrics(NSDictionary *state) +{ + NSMutableDictionary *dict = [NSMutableDictionary dictionary]; + NSArray *memoryFootprint + = state[kSentryMetricProfilerSerializationKeyMemoryFootprint]; + if (memoryFootprint.count > 0) { + dict[kSentryMetricProfilerSerializationKeyMemoryFootprint] + = serializeContinuousProfileMetricReadings( + memoryFootprint, kSentryMetricProfilerSerializationUnitBytes); + } + NSArray *cpuEnergyUsage + = state[kSentryMetricProfilerSerializationKeyCPUEnergyUsage]; + if (cpuEnergyUsage.count > 0) { + dict[kSentryMetricProfilerSerializationKeyCPUEnergyUsage] + = serializeContinuousProfileMetricReadings( + cpuEnergyUsage, kSentryMetricProfilerSerializationUnitNanoJoules); + } + + NSArray *cpuUsage = state[kSentryMetricProfilerSerializationKeyCPUUsage]; + if (cpuUsage.count > 0) { + dict[kSentryMetricProfilerSerializationKeyCPUUsage] + = serializeContinuousProfileMetricReadings( + cpuUsage, kSentryMetricProfilerSerializationUnitPercentage); + } + + return dict; +} + @implementation SentryMetricProfiler { SentryDispatchSourceWrapper *_dispatchSource; @@ -135,7 +163,9 @@ - (void)recordMetrics { [self recordCPUsage]; [self recordMemoryFootprint]; +# if defined(__arm__) || defined(__arm64__) [self recordEnergyUsageEstimate]; +# endif } - (void)stop @@ -177,36 +207,15 @@ - (void)stop return dict; } -- (NSMutableDictionary *)serializeContinuousProfileMetrics; +- (NSDictionary *> *)copyMetricProfilerData { - NSArray *memoryFootprint; - NSArray *cpuEnergyUsage; - NSArray *cpuUsage; + NSMutableDictionary *copy = [NSMutableDictionary dictionary]; @synchronized(self) { - cpuEnergyUsage = [NSArray arrayWithArray:_cpuEnergyUsage]; - memoryFootprint = [NSArray arrayWithArray:_memoryFootprint]; - cpuUsage = [NSArray arrayWithArray:_cpuUsage]; - } - - NSMutableDictionary *dict = [NSMutableDictionary dictionary]; - if (memoryFootprint.count > 0) { - dict[kSentryMetricProfilerSerializationKeyMemoryFootprint] - = serializeContinuousProfileMetricReadings( - memoryFootprint, kSentryMetricProfilerSerializationUnitBytes); - } - if (cpuEnergyUsage.count > 0) { - dict[kSentryMetricProfilerSerializationKeyCPUEnergyUsage] - = serializeContinuousProfileMetricReadings( - cpuEnergyUsage, kSentryMetricProfilerSerializationUnitNanoJoules); - } - - if (cpuUsage.count > 0) { - dict[kSentryMetricProfilerSerializationKeyCPUUsage] - = serializeContinuousProfileMetricReadings( - cpuUsage, kSentryMetricProfilerSerializationUnitPercentage); + copy[kSentryMetricProfilerSerializationKeyMemoryFootprint] = [_memoryFootprint copy]; + copy[kSentryMetricProfilerSerializationKeyCPUUsage] = [_cpuUsage copy]; + copy[kSentryMetricProfilerSerializationKeyCPUEnergyUsage] = [_cpuEnergyUsage copy]; } - - return dict; + return copy; } - (void)clear @@ -275,6 +284,8 @@ - (void)recordCPUsage } } +// Only some architectures support reading energy. +# if defined(__arm__) || defined(__arm64__) - (void)recordEnergyUsageEstimate { NSError *error; @@ -297,6 +308,7 @@ - (void)recordEnergyUsageEstimate [_cpuEnergyUsage addObject:[self metricReadingForValue:@(value)]]; } } +# endif - (SentryMetricReading *)metricReadingForValue:(NSNumber *)value { diff --git a/Sources/Sentry/SentryMigrateSessionInit.m b/Sources/Sentry/SentryMigrateSessionInit.m index 12da60bbb01..dbc6b637c68 100644 --- a/Sources/Sentry/SentryMigrateSessionInit.m +++ b/Sources/Sentry/SentryMigrateSessionInit.m @@ -1,10 +1,7 @@ #import "SentryMigrateSessionInit.h" -#import "SentryEnvelope.h" #import "SentryEnvelopeItemHeader.h" -#import "SentryEnvelopeItemType.h" #import "SentryLogC.h" #import "SentrySerialization.h" -#import "SentrySession+Private.h" #import "SentrySwift.h" NS_ASSUME_NONNULL_BEGIN @@ -20,7 +17,7 @@ + (BOOL)migrateSessionInit:(SentryEnvelope *)envelope } for (SentryEnvelopeItem *item in envelope.items) { - if ([item.header.type isEqualToString:SentryEnvelopeItemTypeSession]) { + if ([item.header.type isEqualToString:SentryEnvelopeItemTypes.session]) { SentrySession *session = [SentrySerialization sessionWithData:item.data]; if (nil != session && [session.flagInit boolValue]) { BOOL didSetInitFlag = @@ -74,7 +71,7 @@ + (BOOL)setInitFlagIfContainsSameSessionId:(NSUUID *)sessionId envelopeFilePath:(NSString *)envelopeFilePath { for (SentryEnvelopeItem *item in envelope.items) { - if ([item.header.type isEqualToString:SentryEnvelopeItemTypeSession]) { + if ([item.header.type isEqualToString:SentryEnvelopeItemTypes.session]) { SentrySession *localSession = [SentrySerialization sessionWithData:item.data]; if (nil != localSession && [localSession.sessionId isEqual:sessionId]) { @@ -120,7 +117,7 @@ + (void)storeSessionInit:(SentryEnvelope *)originalEnvelope NSPredicate *noSessionEnvelopeItems = [NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) { SentryEnvelopeItem *item = object; - return ![item.header.type isEqualToString:SentryEnvelopeItemTypeSession]; + return ![item.header.type isEqualToString:SentryEnvelopeItemTypes.session]; }]; NSMutableArray *itemsWithoutSession = (NSMutableArray *)[[envelope.items diff --git a/Sources/Sentry/SentryNSApplication.m b/Sources/Sentry/SentryNSApplication.m deleted file mode 100644 index 1a2b52c3a12..00000000000 --- a/Sources/Sentry/SentryNSApplication.m +++ /dev/null @@ -1,17 +0,0 @@ -#import "SentryNSApplication.h" - -#if TARGET_OS_OSX - -# import - -@implementation SentryNSApplication - -- (BOOL)isActive -{ - NSApplication *application = [NSApplication sharedApplication]; - return application.isActive; -} - -@end - -#endif // TARGET_OS_OSX diff --git a/Sources/Sentry/SentryNSDataUtils.m b/Sources/Sentry/SentryNSDataUtils.m index 85106ce3470..7429900d524 100644 --- a/Sources/Sentry/SentryNSDataUtils.m +++ b/Sources/Sentry/SentryNSDataUtils.m @@ -3,6 +3,7 @@ #endif #import "SentryError.h" +#import "SentryInternalDefines.h" #import "SentryNSDataUtils.h" NS_ASSUME_NONNULL_BEGIN @@ -63,7 +64,7 @@ + (NSData *_Nullable)sentry_gzippedWithData:(NSData *)data if (data == nil) { return nil; } - NSMutableData *mutable = [NSMutableData dataWithData:data]; + NSMutableData *mutable = [NSMutableData dataWithData:SENTRY_UNWRAP_NULLABLE(NSData, data)]; [mutable appendBytes:"\0" length:1]; return mutable; } diff --git a/Sources/Sentry/SentryNSDictionarySanitize.m b/Sources/Sentry/SentryNSDictionarySanitize.m index faa72c5dfa4..ef3d6bfc46d 100644 --- a/Sources/Sentry/SentryNSDictionarySanitize.m +++ b/Sources/Sentry/SentryNSDictionarySanitize.m @@ -1,5 +1,5 @@ #import "SentryNSDictionarySanitize.h" -#import "NSArray+SentrySanitize.h" +#import "SentryArray.h" #import "SentryDateUtils.h" NSDictionary *_Nullable sentry_sanitize(NSDictionary *_Nullable dictionary) diff --git a/Sources/Sentry/SentryNSNotificationCenterWrapper.m b/Sources/Sentry/SentryNSNotificationCenterWrapper.m deleted file mode 100644 index e6728074882..00000000000 --- a/Sources/Sentry/SentryNSNotificationCenterWrapper.m +++ /dev/null @@ -1,71 +0,0 @@ -#import "SentryNSNotificationCenterWrapper.h" - -#import "SentryDefines.h" - -#if SENTRY_TARGET_MACOS_HAS_UI -# import -#endif - -#if SENTRY_HAS_UIKIT -# import -#endif // SENTRY_HAS_UIKIT - -NS_ASSUME_NONNULL_BEGIN - -@implementation SentryNSNotificationCenterWrapper - -- (void)addObserver:(NSObject *)observer - selector:(SEL)aSelector - name:(NSNotificationName)aName - object:(nullable id)anObject -{ - [NSNotificationCenter.defaultCenter addObserver:observer - selector:aSelector - name:aName - object:anObject]; -} - -- (void)addObserver:(NSObject *)observer selector:(SEL)aSelector name:(NSNotificationName)aName -{ - [NSNotificationCenter.defaultCenter addObserver:observer - selector:aSelector - name:aName - object:nil]; -} - -- (id)addObserverForName:(nullable NSNotificationName)name - object:(nullable id)obj - queue:(nullable NSOperationQueue *)queue - usingBlock:(void (^)(NSNotification *notification))block -{ - return [NSNotificationCenter.defaultCenter addObserverForName:name - object:obj - queue:queue - usingBlock:block]; -} - -- (void)removeObserver:(NSObject *)observer name:(NSNotificationName)aName -{ - [NSNotificationCenter.defaultCenter removeObserver:observer name:aName object:nil]; -} - -- (void)removeObserver:(NSObject *)observer - name:(NSNotificationName)aName - object:(nullable id)anObject -{ - [NSNotificationCenter.defaultCenter removeObserver:observer name:aName object:anObject]; -} - -- (void)removeObserver:(id)observer -{ - [NSNotificationCenter.defaultCenter removeObserver:observer]; -} - -- (void)postNotification:(NSNotification *)notification -{ - [NSNotificationCenter.defaultCenter postNotification:notification]; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryNSProcessInfoWrapper.mm b/Sources/Sentry/SentryNSProcessInfoWrapper.mm deleted file mode 100644 index b17b694df4c..00000000000 --- a/Sources/Sentry/SentryNSProcessInfoWrapper.mm +++ /dev/null @@ -1,50 +0,0 @@ -#import "SentryNSProcessInfoWrapper.h" - -@implementation SentryNSProcessInfoWrapper { -#if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - NSString *_executablePath; -} -- (void)setProcessPath:(NSString *)path -{ - _executablePath = path; -} -# define SENTRY_BINARY_EXECUTABLE_PATH _executablePath; - -- (instancetype)init -{ - self = [super init]; - _executablePath = NSBundle.mainBundle.bundlePath; - return self; -} - -#else -} -# define SENTRY_BINARY_EXECUTABLE_PATH NSBundle.mainBundle.executablePath; -#endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - -- (NSString *)processDirectoryPath -{ - return NSBundle.mainBundle.bundlePath; -} - -- (NSString *)processPath -{ - return SENTRY_BINARY_EXECUTABLE_PATH; -} - -- (NSUInteger)processorCount -{ - return NSProcessInfo.processInfo.processorCount; -} - -- (NSProcessInfoThermalState)thermalState -{ - return NSProcessInfo.processInfo.thermalState; -} - -- (NSDictionary *)environment -{ - return NSProcessInfo.processInfo.environment; -} - -@end diff --git a/Sources/Sentry/SentryNSTimerFactory.m b/Sources/Sentry/SentryNSTimerFactory.m deleted file mode 100644 index 32ab757d192..00000000000 --- a/Sources/Sentry/SentryNSTimerFactory.m +++ /dev/null @@ -1,36 +0,0 @@ -#import "SentryNSTimerFactory.h" -#import "SentryInternalDefines.h" - -@implementation SentryNSTimerFactory - -- (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval - repeats:(BOOL)repeats - block:(void (^)(NSTimer *timer))block -{ - SENTRY_ASSERT([NSThread isMainThread], - @"Timers must be scheduled from the main thread, or they may never fire. See the attribute " - @"on the declaration in NSTimer.h. See " - @"https://stackoverflow.com/questions/8304702/" - @"how-do-i-create-a-nstimer-on-a-background-thread for more info."); - return [NSTimer scheduledTimerWithTimeInterval:interval repeats:repeats block:block]; -} - -- (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti - target:(id)aTarget - selector:(SEL)aSelector - userInfo:(nullable id)userInfo - repeats:(BOOL)yesOrNo -{ - SENTRY_ASSERT([NSThread isMainThread], - @"Timers must be scheduled from the main thread, or they may never fire. See the attribute " - @"on the declaration in NSTimer.h. See " - @"https://stackoverflow.com/questions/8304702/" - @"how-do-i-create-a-nstimer-on-a-background-thread for more info."); - return [NSTimer scheduledTimerWithTimeInterval:ti - target:aTarget - selector:aSelector - userInfo:userInfo - repeats:yesOrNo]; -} - -@end diff --git a/Sources/Sentry/SentryNetworkTracker.m b/Sources/Sentry/SentryNetworkTracker.m index 03380a00799..0343099c5a9 100644 --- a/Sources/Sentry/SentryNetworkTracker.m +++ b/Sources/Sentry/SentryNetworkTracker.m @@ -17,6 +17,7 @@ #import "SentryRequest.h" #import "SentrySDK+Private.h" #import "SentryScope+Private.h" +#import "SentryScope+PrivateSwift.h" #import "SentrySerialization.h" #import "SentrySpanOperation.h" #import "SentryStacktrace.h" @@ -132,7 +133,7 @@ - (BOOL)sessionTaskRequiresPropagation:(NSURLSessionTask *)sessionTask { return sessionTask.currentRequest != nil && [self isTargetMatch:sessionTask.currentRequest.URL - withTargets:SentrySDK.options.tracePropagationTargets]; + withTargets:SentrySDKInternal.options.tracePropagationTargets]; } - (void)urlSessionTaskResume:(NSURLSessionTask *)sessionTask @@ -147,7 +148,7 @@ - (void)urlSessionTaskResume:(NSURLSessionTask *)sessionTask return; // SDK not enabled no need to continue - if (SentrySDK.options == nil) { + if (SentrySDKInternal.options == nil) { return; } @@ -158,7 +159,7 @@ - (void)urlSessionTaskResume:(NSURLSessionTask *)sessionTask } // Don't measure requests to Sentry's backend - NSURL *apiUrl = SentrySDK.options.parsedDsn.url; + NSURL *apiUrl = SentrySDKInternal.options.parsedDsn.url; if ([url.host isEqualToString:apiUrl.host] && [url.path containsString:apiUrl.path]) { return; } @@ -185,7 +186,7 @@ - (void)urlSessionTaskResume:(NSURLSessionTask *)sessionTask return; } - id _Nullable currentSpan = [SentrySDK.currentHub.scope span]; + id _Nullable currentSpan = [SentrySDKInternal.currentHub.scope span]; if (currentSpan != nil) { span = currentSpan; netSpan = [span startChildWithOperation:SentrySpanOperationNetworkRequestOperation @@ -229,15 +230,24 @@ - (void)urlSessionTaskResume:(NSURLSessionTask *)sessionTask - (void)addTraceWithoutTransactionToTask:(NSURLSessionTask *)sessionTask { - SentryPropagationContext *propagationContext = SentrySDK.currentHub.scope.propagationContext; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" + SentryPropagationContext *propagationContext + = SentrySDKInternal.currentHub.scope.propagationContext; + +#if !SDK_V9 + NSString *segment = nil; +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" + segment = SentrySDKInternal.currentHub.scope.userObject.segment; +# pragma clang diagnostic pop +#endif + SentryTraceContext *traceContext = [[SentryTraceContext alloc] initWithTraceId:propagationContext.traceId - options:SentrySDK.currentHub.client.options - userSegment:SentrySDK.currentHub.scope.userObject.segment - replayId:SentrySDK.currentHub.scope.replayId]; -#pragma clang diagnostic pop + options:SentrySDKInternal.currentHub.client.options +#if !SDK_V9 + userSegment:segment +#endif + replayId:SentrySDKInternal.currentHub.scope.replayId]; [self addBaggageHeader:[traceContext toBaggage] traceHeader:[propagationContext traceHeader] @@ -323,7 +333,7 @@ - (void)urlSessionTask:(NSURLSessionTask *)sessionTask setState:(NSURLSessionTas } // Don't measure requests to Sentry's backend - NSURL *apiUrl = SentrySDK.options.parsedDsn.url; + NSURL *apiUrl = SentrySDKInternal.options.parsedDsn.url; if ([url.host isEqualToString:apiUrl.host] && [url.path containsString:apiUrl.path]) { return; } @@ -391,7 +401,8 @@ - (void)captureFailedRequests:(NSURLSessionTask *)sessionTask return; } - if (![self isTargetMatch:myRequest.URL withTargets:SentrySDK.options.failedRequestTargets]) { + if (![self isTargetMatch:myRequest.URL + withTargets:SentrySDKInternal.options.failedRequestTargets]) { SENTRY_LOG_DEBUG( @"Request url isn't within the request targets, not capturing HTTP Client errors."); return; @@ -402,7 +413,7 @@ - (void)captureFailedRequests:(NSURLSessionTask *)sessionTask SentryEvent *event = [[SentryEvent alloc] initWithLevel:kSentryLevelError]; - SentryThreadInspector *threadInspector = SentrySDK.currentHub.getClient.threadInspector; + SentryThreadInspector *threadInspector = SentrySDKInternal.currentHub.getClient.threadInspector; NSArray *threads = [threadInspector getCurrentThreads]; // sessionTask.error isn't used because it's not about network errors but rather @@ -469,7 +480,7 @@ - (void)captureFailedRequests:(NSURLSessionTask *)sessionTask - (BOOL)containsStatusCode:(NSInteger)statusCode { - for (SentryHttpStatusCodeRange *range in SentrySDK.options.failedRequestStatusCodes) { + for (SentryHttpStatusCodeRange *range in SentrySDKInternal.options.failedRequestStatusCodes) { if ([range isInRange:statusCode]) { return YES; } diff --git a/Sources/Sentry/SentryOptions.m b/Sources/Sentry/SentryOptions.m index 3b9e0283a77..885617f745c 100644 --- a/Sources/Sentry/SentryOptions.m +++ b/Sources/Sentry/SentryOptions.m @@ -12,7 +12,8 @@ #import "SentryMeta.h" #import "SentryNetworkTrackingIntegration.h" #import "SentryOptions+Private.h" -#import "SentrySDK.h" +#import "SentryOptionsInternal.h" +#import "SentrySDKInternal.h" #import "SentryScope.h" #import "SentrySessionReplayIntegration.h" #import "SentrySwift.h" @@ -20,29 +21,35 @@ #import "SentryTracer.h" #import -#if SENTRY_HAS_UIKIT -# import "SentryAppStartTrackingIntegration.h" -# import "SentryFramesTrackingIntegration.h" -# import "SentryPerformanceTrackingIntegration.h" -# import "SentryScreenshotIntegration.h" -# import "SentryUIEventTrackingIntegration.h" -# import "SentryUserFeedbackIntegration.h" -# import "SentryViewHierarchyIntegration.h" -# import "SentryWatchdogTerminationTrackingIntegration.h" -#endif // SENTRY_HAS_UIKIT - -#if SENTRY_HAS_METRIC_KIT -# import "SentryMetricKitIntegration.h" -#endif // SENTRY_HAS_METRIC_KIT NSString *const kSentryDefaultEnvironment = @"production"; @implementation SentryOptions { +#if !SDK_V9 BOOL _enableTracingManual; +#endif // !SDK_V9 +#if SWIFT_PACKAGE || SENTRY_TEST + id _beforeSendLogDynamic; +#endif // SWIFT_PACKAGE || SENTRY_TEST +} + +#if SWIFT_PACKAGE || SENTRY_TEST +// Provide explicit implementation for SPM builds where the property is excluded from header +// Use id to avoid typedef dependency, Swift extension provides type safety +- (id)beforeSendLogDynamic +{ + return _beforeSendLogDynamic; +} + +- (void)setBeforeSendLogDynamic:(id)beforeSendLogDynamic +{ + _beforeSendLogDynamic = beforeSendLogDynamic; } +#endif // SWIFT_PACKAGE || SENTRY_TEST + + (NSArray *)defaultIntegrations { - NSArray *defaultIntegrationClasses = [self defaultIntegrationClasses]; + NSArray *defaultIntegrationClasses = [SentryOptionsInternal defaultIntegrationClasses]; NSMutableArray *defaultIntegrationNames = [[NSMutableArray alloc] initWithCapacity:defaultIntegrationClasses.count]; @@ -53,45 +60,6 @@ @implementation SentryOptions { return defaultIntegrationNames; } -+ (NSArray *)defaultIntegrationClasses -{ - // The order of integrations here is important. - // SentryCrashIntegration needs to be initialized before SentryAutoSessionTrackingIntegration. - // And SentrySessionReplayIntegration before SentryCrashIntegration. - NSMutableArray *defaultIntegrations = [NSMutableArray arrayWithObjects: -#if SENTRY_TARGET_REPLAY_SUPPORTED - [SentrySessionReplayIntegration class], -#endif // SENTRY_TARGET_REPLAY_SUPPORTED - [SentryCrashIntegration class], -#if SENTRY_HAS_UIKIT - [SentryAppStartTrackingIntegration class], [SentryFramesTrackingIntegration class], - [SentryPerformanceTrackingIntegration class], [SentryUIEventTrackingIntegration class], - [SentryViewHierarchyIntegration class], - [SentryWatchdogTerminationTrackingIntegration class], -#endif // SENTRY_HAS_UIKIT -#if SENTRY_TARGET_REPLAY_SUPPORTED - [SentryScreenshotIntegration class], -#endif // SENTRY_TARGET_REPLAY_SUPPORTED - [SentryANRTrackingIntegration class], [SentryAutoBreadcrumbTrackingIntegration class], - [SentryAutoSessionTrackingIntegration class], [SentryCoreDataTrackingIntegration class], - [SentryFileIOTrackingIntegration class], [SentryNetworkTrackingIntegration class], - [SentrySwiftAsyncIntegration class], nil]; - -#if TARGET_OS_IOS && SENTRY_HAS_UIKIT - if (@available(iOS 13.0, *)) { - [defaultIntegrations addObject:[SentryUserFeedbackIntegration class]]; - } -#endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT - -#if SENTRY_HAS_METRIC_KIT - if (@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, *)) { - [defaultIntegrations addObject:[SentryMetricKitIntegration class]]; - } -#endif // SENTRY_HAS_METRIC_KIT - - return defaultIntegrations; -} - - (instancetype)init { if (self = [super init]) { @@ -108,7 +76,9 @@ - (instancetype)init self.debug = NO; self.maxBreadcrumbs = defaultMaxBreadcrumbs; self.maxCacheItems = 30; +#if !SDK_V9 _integrations = [SentryOptions defaultIntegrations]; +#endif // !SDK_V9 self.sampleRate = SENTRY_DEFAULT_SAMPLE_RATE; self.enableAutoSessionTracking = YES; self.enableGraphQLOperationTracking = NO; @@ -126,17 +96,22 @@ - (instancetype)init self.initialScope = ^SentryScope *(SentryScope *scope) { return scope; }; __swiftExperimentalOptions = [[SentryExperimentalOptions alloc] init]; +#if !SDK_V9 _enableTracing = NO; _enableTracingManual = NO; +#endif // !SDK_V9 #if SENTRY_HAS_UIKIT self.enableUIViewControllerTracing = YES; self.attachScreenshot = NO; + self.screenshot = [[SentryViewScreenshotOptions alloc] init]; self.attachViewHierarchy = NO; self.reportAccessibilityIdentifier = YES; self.enableUserInteractionTracing = YES; self.idleTimeout = SentryTracerDefaultTimeout; self.enablePreWarmedAppStartTracing = NO; +# if !SDK_V9 self.enableAppHangTrackingV2 = NO; +# endif // !SDK_V9 self.enableReportNonFullyBlockingAppHangs = YES; #endif // SENTRY_HAS_UIKIT @@ -152,8 +127,13 @@ - (instancetype)init self.enableNetworkBreadcrumbs = YES; self.tracesSampleRate = nil; #if SENTRY_TARGET_PROFILING_SUPPORTED +# if !SDK_V9 _enableProfiling = NO; +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" self.profilesSampleRate = SENTRY_INITIAL_PROFILES_SAMPLE_RATE; +# pragma clang diagnostic pop +# endif // !SDK_V9 #endif // SENTRY_TARGET_PROFILING_SUPPORTED self.enableCoreDataTracing = YES; _enableSwizzling = YES; @@ -209,9 +189,11 @@ - (instancetype)init SentryHttpStatusCodeRange *defaultHttpStatusCodeRange = [[SentryHttpStatusCodeRange alloc] initWithMin:500 max:599]; self.failedRequestStatusCodes = @[ defaultHttpStatusCodeRange ]; + self.cacheDirectoryPath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) - .firstObject; + .firstObject + ?: @""; #if SENTRY_HAS_METRIC_KIT if (@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, *)) { @@ -223,23 +205,6 @@ - (instancetype)init return self; } -/** Only exposed via `SentryOptions+HybridSDKs.h`. */ -- (_Nullable instancetype)initWithDict:(NSDictionary *)options - didFailWithError:(NSError *_Nullable *_Nullable)error -{ - if (self = [self init]) { - if (![self validateOptions:options didFailWithError:error]) { - if (error != nil) { - SENTRY_LOG_ERROR(@"Failed to initialize SentryOptions: %@", *error); - } else { - SENTRY_LOG_ERROR(@"Failed to initialize SentryOptions"); - } - return nil; - } - } - return self; -} - - (void)setTracePropagationTargets:(NSArray *)tracePropagationTargets { for (id targetCheck in tracePropagationTargets) { @@ -266,13 +231,12 @@ - (void)setFailedRequestTargets:(NSArray *)failedRequestTargets _failedRequestTargets = failedRequestTargets; } +#if !SDK_V9 - (void)setIntegrations:(NSArray *)integrations { - SENTRY_LOG_WARN( - @"Setting `SentryOptions.integrations` is deprecated. Integrations should be enabled or " - @"disabled using their respective `SentryOptions.enable*` property."); _integrations = integrations.mutableCopy; } +#endif // !SDK_V9 - (void)setDsn:(NSString *)dsn { @@ -286,321 +250,6 @@ - (void)setDsn:(NSString *)dsn } } -/** - * Populates all @c SentryOptions values from @c options dict using fallbacks/defaults if needed. - */ -- (BOOL)validateOptions:(NSDictionary *)options - didFailWithError:(NSError *_Nullable *_Nullable)error -{ - NSPredicate *isNSString = [NSPredicate predicateWithBlock:^BOOL( - id object, NSDictionary *bindings) { return [object isKindOfClass:[NSString class]]; }]; - - [self setBool:options[@"debug"] block:^(BOOL value) { self->_debug = value; }]; - - if ([options[@"diagnosticLevel"] isKindOfClass:[NSString class]]) { - for (SentryLevel level = 0; level <= kSentryLevelFatal; level++) { - if ([nameForSentryLevel(level) isEqualToString:options[@"diagnosticLevel"]]) { - self.diagnosticLevel = level; - break; - } - } - } - - if (options[@"dsn"] != [NSNull null]) { - NSString *dsn = @""; - if (nil != options[@"dsn"] && [options[@"dsn"] isKindOfClass:[NSString class]]) { - dsn = options[@"dsn"]; - } - - self.parsedDsn = [[SentryDsn alloc] initWithString:dsn didFailWithError:error]; - if (self.parsedDsn == nil) { - return NO; - } - } - - if ([options[@"release"] isKindOfClass:[NSString class]]) { - self.releaseName = options[@"release"]; - } - - if ([options[@"environment"] isKindOfClass:[NSString class]]) { - self.environment = options[@"environment"]; - } - - if ([options[@"dist"] isKindOfClass:[NSString class]]) { - self.dist = options[@"dist"]; - } - - [self setBool:options[@"enabled"] block:^(BOOL value) { self->_enabled = value; }]; - - if ([options[@"shutdownTimeInterval"] isKindOfClass:[NSNumber class]]) { - self.shutdownTimeInterval = [options[@"shutdownTimeInterval"] doubleValue]; - } - - [self setBool:options[@"enableCrashHandler"] - block:^(BOOL value) { self->_enableCrashHandler = value; }]; - -#if TARGET_OS_OSX - [self setBool:options[@"enableUncaughtNSExceptionReporting"] - block:^(BOOL value) { self->_enableUncaughtNSExceptionReporting = value; }]; -#endif // TARGET_OS_OSX - -#if !TARGET_OS_WATCH - [self setBool:options[@"enableSigtermReporting"] - block:^(BOOL value) { self->_enableSigtermReporting = value; }]; -#endif // !TARGET_OS_WATCH - - if ([options[@"maxBreadcrumbs"] isKindOfClass:[NSNumber class]]) { - self.maxBreadcrumbs = [options[@"maxBreadcrumbs"] unsignedIntValue]; - } - - [self setBool:options[@"enableNetworkBreadcrumbs"] - block:^(BOOL value) { self->_enableNetworkBreadcrumbs = value; }]; - - if ([options[@"maxCacheItems"] isKindOfClass:[NSNumber class]]) { - self.maxCacheItems = [options[@"maxCacheItems"] unsignedIntValue]; - } - - if ([options[@"cacheDirectoryPath"] isKindOfClass:[NSString class]]) { - self.cacheDirectoryPath = options[@"cacheDirectoryPath"]; - } - - if ([self isBlock:options[@"beforeSend"]]) { - self.beforeSend = options[@"beforeSend"]; - } - - if ([self isBlock:options[@"beforeSendSpan"]]) { - self.beforeSendSpan = options[@"beforeSendSpan"]; - } - - if ([self isBlock:options[@"beforeBreadcrumb"]]) { - self.beforeBreadcrumb = options[@"beforeBreadcrumb"]; - } - - if ([self isBlock:options[@"beforeCaptureScreenshot"]]) { - self.beforeCaptureScreenshot = options[@"beforeCaptureScreenshot"]; - } - - if ([self isBlock:options[@"beforeCaptureViewHierarchy"]]) { - self.beforeCaptureViewHierarchy = options[@"beforeCaptureViewHierarchy"]; - } - - if ([self isBlock:options[@"onCrashedLastRun"]]) { - self.onCrashedLastRun = options[@"onCrashedLastRun"]; - } - - if ([options[@"integrations"] isKindOfClass:[NSArray class]]) { - self.integrations = - [[options[@"integrations"] filteredArrayUsingPredicate:isNSString] mutableCopy]; - } - - if ([options[@"sampleRate"] isKindOfClass:[NSNumber class]]) { - self.sampleRate = options[@"sampleRate"]; - } - - [self setBool:options[@"enableAutoSessionTracking"] - block:^(BOOL value) { self->_enableAutoSessionTracking = value; }]; - - [self setBool:options[@"enableGraphQLOperationTracking"] - block:^(BOOL value) { self->_enableGraphQLOperationTracking = value; }]; - - [self setBool:options[@"enableWatchdogTerminationTracking"] - block:^(BOOL value) { self->_enableWatchdogTerminationTracking = value; }]; - - [self setBool:options[@"swiftAsyncStacktraces"] - block:^(BOOL value) { self->_swiftAsyncStacktraces = value; }]; - - if ([options[@"sessionTrackingIntervalMillis"] isKindOfClass:[NSNumber class]]) { - self.sessionTrackingIntervalMillis = - [options[@"sessionTrackingIntervalMillis"] unsignedIntValue]; - } - - [self setBool:options[@"attachStacktrace"] - block:^(BOOL value) { self->_attachStacktrace = value; }]; - - if ([options[@"maxAttachmentSize"] isKindOfClass:[NSNumber class]]) { - self.maxAttachmentSize = [options[@"maxAttachmentSize"] unsignedIntValue]; - } - - [self setBool:options[@"sendDefaultPii"] - block:^(BOOL value) { self->_sendDefaultPii = value; }]; - - [self setBool:options[@"enableAutoPerformanceTracing"] - block:^(BOOL value) { self->_enableAutoPerformanceTracing = value; }]; - - [self setBool:options[@"enablePerformanceV2"] - block:^(BOOL value) { self->_enablePerformanceV2 = value; }]; - - [self setBool:options[@"enablePersistingTracesWhenCrashing"] - block:^(BOOL value) { self->_enablePersistingTracesWhenCrashing = value; }]; - - [self setBool:options[@"enableCaptureFailedRequests"] - block:^(BOOL value) { self->_enableCaptureFailedRequests = value; }]; - - [self setBool:options[@"enableTimeToFullDisplayTracing"] - block:^(BOOL value) { self->_enableTimeToFullDisplayTracing = value; }]; - - if ([self isBlock:options[@"initialScope"]]) { - self.initialScope = options[@"initialScope"]; - } -#if SENTRY_HAS_UIKIT - [self setBool:options[@"enableUIViewControllerTracing"] - block:^(BOOL value) { self->_enableUIViewControllerTracing = value; }]; - - [self setBool:options[@"attachScreenshot"] - block:^(BOOL value) { self->_attachScreenshot = value; }]; - - [self setBool:options[@"attachViewHierarchy"] - block:^(BOOL value) { self->_attachViewHierarchy = value; }]; - - [self setBool:options[@"reportAccessibilityIdentifier"] - block:^(BOOL value) { self->_reportAccessibilityIdentifier = value; }]; - - [self setBool:options[@"enableUserInteractionTracing"] - block:^(BOOL value) { self->_enableUserInteractionTracing = value; }]; - - if ([options[@"idleTimeout"] isKindOfClass:[NSNumber class]]) { - self.idleTimeout = [options[@"idleTimeout"] doubleValue]; - } - - [self setBool:options[@"enablePreWarmedAppStartTracing"] - block:^(BOOL value) { self->_enablePreWarmedAppStartTracing = value; }]; - - [self setBool:options[@"enableAppHangTrackingV2"] - block:^(BOOL value) { self->_enableAppHangTrackingV2 = value; }]; - - [self setBool:options[@"enableReportNonFullyBlockingAppHangs"] - block:^(BOOL value) { self->_enableReportNonFullyBlockingAppHangs = value; }]; - -#endif // SENTRY_HAS_UIKIT - -#if SENTRY_TARGET_REPLAY_SUPPORTED - if ([options[@"sessionReplay"] isKindOfClass:NSDictionary.class]) { - self.sessionReplay = - [[SentryReplayOptions alloc] initWithDictionary:options[@"sessionReplay"]]; - } -#endif // SENTRY_TARGET_REPLAY_SUPPORTED - - [self setBool:options[@"enableAppHangTracking"] - block:^(BOOL value) { self->_enableAppHangTracking = value; }]; - - if ([options[@"appHangTimeoutInterval"] isKindOfClass:[NSNumber class]]) { - self.appHangTimeoutInterval = [options[@"appHangTimeoutInterval"] doubleValue]; - } - - [self setBool:options[@"enableNetworkTracking"] - block:^(BOOL value) { self->_enableNetworkTracking = value; }]; - - [self setBool:options[@"enableFileIOTracing"] - block:^(BOOL value) { self->_enableFileIOTracing = value; }]; - - if ([options[@"tracesSampleRate"] isKindOfClass:[NSNumber class]]) { - self.tracesSampleRate = options[@"tracesSampleRate"]; - } - - if ([self isBlock:options[@"tracesSampler"]]) { - self.tracesSampler = options[@"tracesSampler"]; - } -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" - if ([options[@"enableTracing"] isKindOfClass:NSNumber.self]) { - self.enableTracing = [options[@"enableTracing"] boolValue]; - } -#pragma clang diagnostic pop - - if ([options[@"inAppIncludes"] isKindOfClass:[NSArray class]]) { - NSArray *inAppIncludes = - [options[@"inAppIncludes"] filteredArrayUsingPredicate:isNSString]; - _inAppIncludes = [_inAppIncludes arrayByAddingObjectsFromArray:inAppIncludes]; - } - - if ([options[@"inAppExcludes"] isKindOfClass:[NSArray class]]) { - _inAppExcludes = [options[@"inAppExcludes"] filteredArrayUsingPredicate:isNSString]; - } - - if ([options[@"urlSession"] isKindOfClass:[NSURLSession class]]) { - self.urlSession = options[@"urlSession"]; - } - - if ([options[@"urlSessionDelegate"] conformsToProtocol:@protocol(NSURLSessionDelegate)]) { - self.urlSessionDelegate = options[@"urlSessionDelegate"]; - } - - [self setBool:options[@"enableSwizzling"] - block:^(BOOL value) { self->_enableSwizzling = value; }]; - - if ([options[@"swizzleClassNameExcludes"] isKindOfClass:[NSSet class]]) { - _swizzleClassNameExcludes = - [options[@"swizzleClassNameExcludes"] filteredSetUsingPredicate:isNSString]; - } - - [self setBool:options[@"enableCoreDataTracing"] - block:^(BOOL value) { self->_enableCoreDataTracing = value; }]; - -#if SENTRY_TARGET_PROFILING_SUPPORTED - if ([options[@"profilesSampleRate"] isKindOfClass:[NSNumber class]]) { - self.profilesSampleRate = options[@"profilesSampleRate"]; - } - - if ([self isBlock:options[@"profilesSampler"]]) { - self.profilesSampler = options[@"profilesSampler"]; - } - - [self setBool:options[@"enableProfiling"] - block:^(BOOL value) { self->_enableProfiling = value; }]; - - [self setBool:options[NSStringFromSelector(@selector(enableAppLaunchProfiling))] - block:^(BOOL value) { self->_enableAppLaunchProfiling = value; }]; -#endif // SENTRY_TARGET_PROFILING_SUPPORTED - - [self setBool:options[@"sendClientReports"] - block:^(BOOL value) { self->_sendClientReports = value; }]; - - [self setBool:options[@"enableAutoBreadcrumbTracking"] - block:^(BOOL value) { self->_enableAutoBreadcrumbTracking = value; }]; - - if ([options[@"tracePropagationTargets"] isKindOfClass:[NSArray class]]) { - self.tracePropagationTargets = options[@"tracePropagationTargets"]; - } - - if ([options[@"failedRequestStatusCodes"] isKindOfClass:[NSArray class]]) { - self.failedRequestStatusCodes = options[@"failedRequestStatusCodes"]; - } - - if ([options[@"failedRequestTargets"] isKindOfClass:[NSArray class]]) { - self.failedRequestTargets = options[@"failedRequestTargets"]; - } - -#if SENTRY_HAS_METRIC_KIT - if (@available(iOS 14.0, macOS 12.0, macCatalyst 14.0, *)) { - [self setBool:options[@"enableMetricKit"] - block:^(BOOL value) { self->_enableMetricKit = value; }]; - [self setBool:options[@"enableMetricKitRawPayload"] - block:^(BOOL value) { self->_enableMetricKitRawPayload = value; }]; - } -#endif // SENTRY_HAS_METRIC_KIT - - [self setBool:options[@"enableSpotlight"] - block:^(BOOL value) { self->_enableSpotlight = value; }]; - - if ([options[@"spotlightUrl"] isKindOfClass:[NSString class]]) { - self.spotlightUrl = options[@"spotlightUrl"]; - } - - if ([options[@"experimental"] isKindOfClass:NSDictionary.class]) { - [self.experimental validateOptions:options[@"experimental"]]; - } - - return YES; -} - -- (void)setBool:(id)value block:(void (^)(BOOL))block -{ - // Entries in the dictionary can be NSNull. Especially, on React-Native, this can happen. - if (value != nil && ![value isEqual:[NSNull null]]) { - block([value boolValue]); - } -} - - (void)addInAppInclude:(NSString *)inAppInclude { _inAppIncludes = [self.inAppIncludes arrayByAddingObject:inAppInclude]; @@ -629,6 +278,7 @@ - (void)setSampleRate:(NSNumber *)sampleRate return rate >= 0 && rate <= 1.0; } +#if !SDK_V9 - (void)setEnableTracing:(BOOL)enableTracing { //`enableTracing` is basically an alias to tracesSampleRate @@ -641,6 +291,7 @@ - (void)setEnableTracing:(BOOL)enableTracing } _enableTracingManual = YES; } +#endif // !SDK_V9 - (void)setTracesSampleRate:(NSNumber *)tracesSampleRate { @@ -648,9 +299,11 @@ - (void)setTracesSampleRate:(NSNumber *)tracesSampleRate _tracesSampleRate = nil; } else if (sentry_isValidSampleRate(tracesSampleRate)) { _tracesSampleRate = tracesSampleRate; +#if !SDK_V9 if (!_enableTracingManual) { _enableTracing = YES; } +#endif // !SDK_V9 } else { _tracesSampleRate = SENTRY_DEFAULT_TRACES_SAMPLE_RATE; } @@ -659,19 +312,27 @@ - (void)setTracesSampleRate:(NSNumber *)tracesSampleRate - (void)setTracesSampler:(SentryTracesSamplerCallback)tracesSampler { _tracesSampler = tracesSampler; +#if !SDK_V9 if (_tracesSampler != nil && !_enableTracingManual) { _enableTracing = YES; } +#endif // !SDK_V9 } - (BOOL)isTracingEnabled { +#if SDK_V9 + return (_tracesSampleRate != nil && [_tracesSampleRate doubleValue] > 0) + || _tracesSampler != nil; +#else return _enableTracing && ((_tracesSampleRate != nil && [_tracesSampleRate doubleValue] > 0) || _tracesSampler != nil); +#endif // !SDK_V9 } #if SENTRY_TARGET_PROFILING_SUPPORTED +# if !SDK_V9 - (void)setProfilesSampleRate:(NSNumber *)profilesSampleRate { if (profilesSampleRate == nil) { @@ -691,65 +352,55 @@ - (BOOL)isProfilingEnabled - (BOOL)isContinuousProfilingEnabled { -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" // this looks a little weird with the `!self.enableProfiling` but that actually is the // deprecated way to say "enable trace-based profiling", which necessarily disables continuous // profiling as they are mutually exclusive modes return _profilesSampleRate == nil && _profilesSampler == nil && !self.enableProfiling; -# pragma clang diagnostic pop +# pragma clang diagnostic pop } +# endif // !SDK_V9 + - (BOOL)isContinuousProfilingV2Enabled { +# if SDK_V9 + return _profiling != nil; +# else return [self isContinuousProfilingEnabled] && _profiling != nil; +# endif // SDK_V9 } - (BOOL)isProfilingCorrelatedToTraces { +# if SDK_V9 + return _profiling != nil && _profiling.lifecycle == SentryProfileLifecycleTrace; +# else return ![self isContinuousProfilingEnabled] || (_profiling != nil && _profiling.lifecycle == SentryProfileLifecycleTrace); +# endif // SDK_V9 } +# if !SDK_V9 - (void)setEnableProfiling_DEPRECATED_TEST_ONLY:(BOOL)enableProfiling_DEPRECATED_TEST_ONLY { -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" self.enableProfiling = enableProfiling_DEPRECATED_TEST_ONLY; -# pragma clang diagnostic pop +# pragma clang diagnostic pop } - (BOOL)enableProfiling_DEPRECATED_TEST_ONLY { -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" return self.enableProfiling; -# pragma clang diagnostic pop +# pragma clang diagnostic pop } +# endif // !SDK_V9 #endif // SENTRY_TARGET_PROFILING_SUPPORTED -/** - * Checks if the passed in block is actually of type block. We can't check if the block matches a - * specific block without some complex objc runtime method calls and therefore we only check if it's - * a block or not. Assigning a wrong block to the @c SentryOptions blocks still could lead to - * crashes at runtime, but when someone uses the @c initWithDict they should better know what they - * are doing. - * @see Taken from https://gist.github.com/steipete/6ee378bd7d87f276f6e0 - */ -- (BOOL)isBlock:(nullable id)block -{ - static Class blockClass; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - blockClass = [^{ } class]; - while ([blockClass superclass] != NSObject.class) { - blockClass = [blockClass superclass]; - } - }); - - return [block isKindOfClass:blockClass]; -} - #if SENTRY_UIKIT_AVAILABLE - (void)setEnableUIViewControllerTracing:(BOOL)enableUIViewControllerTracing @@ -785,6 +436,20 @@ - (void)setAttachViewHierarchy:(BOOL)attachViewHierarchy # endif // SENTRY_HAS_UIKIT } +# if SENTRY_TARGET_REPLAY_SUPPORTED + +- (BOOL)enableViewRendererV2 +{ + return self.sessionReplay.enableViewRendererV2; +} + +- (BOOL)enableFastViewRendering +{ + return self.sessionReplay.enableFastViewRendering; +} + +# endif // SENTRY_TARGET_REPLAY_SUPPORTED + - (void)setEnableUserInteractionTracing:(BOOL)enableUserInteractionTracing { # if SENTRY_HAS_UIKIT @@ -834,15 +499,22 @@ - (void)setEnableSpotlight:(BOOL)value #if SENTRY_HAS_UIKIT - (BOOL)isAppHangTrackingV2Disabled { - return !self.enableAppHangTrackingV2 || self.appHangTimeoutInterval <= 0; +# if SDK_V9 + BOOL isV2Enabled = self.enableAppHangTracking; +# else + BOOL isV2Enabled = self.enableAppHangTrackingV2; +# endif // SDK_V9 + return !isV2Enabled || self.appHangTimeoutInterval <= 0; } #endif // SENTRY_HAS_UIKIT #if TARGET_OS_IOS && SENTRY_HAS_UIKIT - (void)setConfigureUserFeedback:(SentryUserFeedbackConfigurationBlock)configureUserFeedback { - self.userFeedbackConfiguration = [[SentryUserFeedbackConfiguration alloc] init]; - configureUserFeedback(self.userFeedbackConfiguration); + SentryUserFeedbackConfiguration *userFeedbackConfiguration = + [[SentryUserFeedbackConfiguration alloc] init]; + self.userFeedbackConfiguration = userFeedbackConfiguration; + configureUserFeedback(userFeedbackConfiguration); } #endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT diff --git a/Sources/Sentry/SentryPerformanceTracker.m b/Sources/Sentry/SentryPerformanceTracker.m index 8ecfd772433..62b3c536ef0 100644 --- a/Sources/Sentry/SentryPerformanceTracker.m +++ b/Sources/Sentry/SentryPerformanceTracker.m @@ -9,6 +9,11 @@ #import "SentryTracer.h" #import "SentryTransactionContext+Private.h" +#import "SentryProfilingConditionals.h" +#if SENTRY_TARGET_PROFILING_SUPPORTED +# import "SentryLaunchProfiling.h" +#endif // SENTRY_TARGET_PROFILING_SUPPORTED + #if SENTRY_HAS_UIKIT # import "SentryUIEventTracker.h" #endif // SENTRY_HAS_UIKIT @@ -47,8 +52,14 @@ - (SentrySpanId *)startSpanWithName:(NSString *)name origin:(NSString *)origin { id activeSpan; - @synchronized(self.activeSpanStack) { - activeSpan = [self.activeSpanStack lastObject]; +#if SENTRY_TARGET_PROFILING_SUPPORTED + activeSpan = sentry_launchTracer; +#endif // SENTRY_TARGET_PROFILING_SUPPORTED + + if (activeSpan == nil) { + @synchronized(self.activeSpanStack) { + activeSpan = [self.activeSpanStack lastObject]; + } } id newSpan; @@ -61,7 +72,7 @@ - (SentrySpanId *)startSpanWithName:(NSString *)name operation:operation origin:origin]; - id span = SentrySDK.currentHub.scope.span; + id span = SentrySDKInternal.currentHub.scope.span; BOOL bindToScope = NO; if (span == nil) { @@ -81,7 +92,7 @@ - (SentrySpanId *)startSpanWithName:(NSString *)name SENTRY_LOG_DEBUG( @"Starting new transaction for %@ with bindToScope: %d", name, bindToScope); - newSpan = [SentrySDK.currentHub + newSpan = [SentrySDKInternal.currentHub startTransactionWithContext:context bindToScope:bindToScope customSamplingContext:@{} diff --git a/Sources/Sentry/SentryPerformanceTrackingIntegration.m b/Sources/Sentry/SentryPerformanceTrackingIntegration.m index 42a2d6e12a5..efe06dd04dd 100644 --- a/Sources/Sentry/SentryPerformanceTrackingIntegration.m +++ b/Sources/Sentry/SentryPerformanceTrackingIntegration.m @@ -2,10 +2,8 @@ #if SENTRY_HAS_UIKIT -# import "SentryDefaultObjCRuntimeWrapper.h" # import "SentryDependencyContainer.h" # import "SentryLogC.h" -# import "SentryNSProcessInfoWrapper.h" # import "SentryOptions.h" # import "SentrySubClassFinder.h" # import "SentrySwift.h" @@ -34,13 +32,13 @@ - (BOOL)installWithOptions:(SentryOptions *)options SentrySubClassFinder *subClassFinder = [[SentrySubClassFinder alloc] initWithDispatchQueue:dispatchQueue - objcRuntimeWrapper:[SentryDefaultObjCRuntimeWrapper sharedInstance] + objcRuntimeWrapper:[SentryDependencyContainer.sharedInstance objcRuntimeWrapper] swizzleClassNameExcludes:options.swizzleClassNameExcludes]; self.swizzling = [[SentryUIViewControllerSwizzling alloc] initWithOptions:options dispatchQueue:dispatchQueue - objcRuntimeWrapper:[SentryDefaultObjCRuntimeWrapper sharedInstance] + objcRuntimeWrapper:[SentryDependencyContainer.sharedInstance objcRuntimeWrapper] subClassFinder:subClassFinder processInfoWrapper:[SentryDependencyContainer.sharedInstance processInfoWrapper] binaryImageCache:[SentryDependencyContainer.sharedInstance binaryImageCache]]; diff --git a/Sources/Sentry/SentryProfileCollector.mm b/Sources/Sentry/SentryProfileCollector.mm index 44efedb8b46..7c2b4aeb9d9 100644 --- a/Sources/Sentry/SentryProfileCollector.mm +++ b/Sources/Sentry/SentryProfileCollector.mm @@ -14,7 +14,7 @@ @implementation SentryProfileCollector forTrace:(SentryId *)traceId { NSMutableDictionary *payload = sentry_collectProfileDataHybridSDK( - startSystemTime, endSystemTime, traceId, [SentrySDK currentHub]); + startSystemTime, endSystemTime, traceId, [SentrySDKInternal currentHub]); if (payload != nil) { payload[@"platform"] = SentryPlatformName; diff --git a/Sources/Sentry/SentryProfileTimeseries.m b/Sources/Sentry/SentryProfileTimeseries.m index c29dea8dc91..8c0ca4b753c 100644 --- a/Sources/Sentry/SentryProfileTimeseries.m +++ b/Sources/Sentry/SentryProfileTimeseries.m @@ -1,4 +1,5 @@ #import "SentryProfileTimeseries.h" +#import "SentryInternalDefines.h" #if SENTRY_TARGET_PROFILING_SUPPORTED @@ -93,7 +94,7 @@ { NSMutableArray *slicedGPUEntries = [NSMutableArray array]; - __block NSNumber *nearestPredecessorValue; + __block NSNumber *_Nullable nearestPredecessorValue; [frameInfo enumerateObjectsUsingBlock:^( NSDictionary *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) { unsigned long long timestamp = obj[@"timestamp"].unsignedLongLongValue; @@ -112,15 +113,20 @@ } uint64_t relativeTimestamp = getDurationNs(startSystemTime, timestamp); - [slicedGPUEntries addObject:@ { - @"elapsed_since_start_ns" : sentry_stringForUInt64(relativeTimestamp), - @"value" : obj[@"value"], - }]; + NSMutableDictionary *entry = + [@ { @"elapsed_since_start_ns" : sentry_stringForUInt64(relativeTimestamp) } + mutableCopy]; + NSNumber *value = obj[@"value"]; + if (value != nil && ![value isKindOfClass:[NSNull class]]) { + entry[@"value"] = value; + } + [slicedGPUEntries addObject:entry]; }]; - if (useMostRecentRecording && slicedGPUEntries.count == 0 && nearestPredecessorValue != nil) { + if (useMostRecentRecording && slicedGPUEntries.count == 0 && nearestPredecessorValue != nil + && ![nearestPredecessorValue isKindOfClass:[NSNull class]]) { [slicedGPUEntries addObject:@ { @"elapsed_since_start_ns" : @"0", - @"value" : nearestPredecessorValue, + @"value" : SENTRY_UNWRAP_NULLABLE(NSNumber, nearestPredecessorValue), }]; } return slicedGPUEntries; diff --git a/Sources/Sentry/SentryProfiler.mm b/Sources/Sentry/SentryProfiler.mm index c06b89b62e5..e8aa20bb571 100644 --- a/Sources/Sentry/SentryProfiler.mm +++ b/Sources/Sentry/SentryProfiler.mm @@ -12,25 +12,28 @@ # import "SentryLogC.h" # import "SentryMetricProfiler.h" # import "SentryOptions+Private.h" +# import "SentryProfileConfiguration.h" # import "SentryProfilerState+ObjCpp.h" # import "SentryProfilerTestHelpers.h" +# import "SentryProfilingSwiftHelpers.h" # import "SentrySDK+Private.h" -# import "SentrySampling.h" # import "SentrySamplingProfiler.hpp" # import "SentryScreenFrames.h" -# import "SentrySwift.h" # import "SentryTime.h" +# import "SentryTracer+Private.h" # if SENTRY_HAS_UIKIT # import "SentryFramesTracker.h" -# import "SentryNSNotificationCenterWrapper.h" -# import "SentryUIViewControllerPerformanceTracker.h" # import # endif // SENTRY_HAS_UIKIT using namespace sentry::profiling; -SentrySamplerDecision *_Nullable sentry_profilerSessionSampleDecision; +/** + * The current configuration the profiler operates under for this session. Set when a launch profile + * runs, and then is updated on SDK start. + */ +SentryProfileConfiguration *_Nullable sentry_profileConfiguration; namespace { @@ -41,14 +44,32 @@ # pragma mark - Public void -sentry_reevaluateSessionSampleRate(float sessionSampleRate) +sentry_reevaluateSessionSampleRate() { - sentry_profilerSessionSampleDecision = sentry_sampleProfileSession(sessionSampleRate); + [sentry_profileConfiguration reevaluateSessionSampleRate]; +} + +BOOL +sentry_isLaunchProfileCorrelatedToTraces(void) +{ + if (nil == sentry_profileConfiguration) { + return NO; + } + + SentryProfileOptions *_Nullable nullableOptions = sentry_profileConfiguration.profileOptions; + if (nil == nullableOptions) { + return !sentry_profileConfiguration.isContinuousV1; + } + SentryProfileOptions *_Nonnull options + = SENTRY_UNWRAP_NULLABLE(SentryProfileOptions, nullableOptions); + + return sentry_profileAppStarts(options) && sentry_isTraceLifecycle(options); } void sentry_configureContinuousProfiling(SentryOptions *options) { +# if !SDK_V9 if (![options isContinuousProfilingEnabled]) { if (options.configureProfiling != nil) { SENTRY_LOG_WARN(@"In order to configure SentryProfileOptions you must remove " @@ -57,6 +78,7 @@ } return; } +# endif // !SDK_V9 if (options.configureProfiling == nil) { SENTRY_LOG_DEBUG(@"Continuous profiling V2 configuration not set by SDK consumer, nothing " @@ -64,74 +86,83 @@ return; } - options.profiling = [[SentryProfileOptions alloc] init]; - options.configureProfiling(options.profiling); + SentryProfileOptions *_Nonnull profilingOptions = sentry_getSentryProfileOptions(); + options.profiling = profilingOptions; + options.configureProfiling(profilingOptions); - if (options.profiling.lifecycle == SentryProfileLifecycleTrace && !options.isTracingEnabled) { + if (sentry_isTraceLifecycle(profilingOptions) && !options.isTracingEnabled) { SENTRY_LOG_WARN( @"Tracing must be enabled in order to configure profiling with trace lifecycle."); return; } - sentry_reevaluateSessionSampleRate(options.profiling.sessionSampleRate); + // if a launch profiler was started, sentry_profileConfiguration will have been set at that time + // with the hydrated options that were persisted from the previous SDK start, which are used to + // help determine when/how to stop the launch profile. otherwise, there won't yet be a + // SentryProfileConfiguration instance, so we'll instantiate one which will be used to access + // the profile session sample rate henceforth + if (sentry_profileConfiguration == nil) { + sentry_profileConfiguration = + [[SentryProfileConfiguration alloc] initWithProfileOptions:profilingOptions]; + } + + sentry_reevaluateSessionSampleRate(); SENTRY_LOG_DEBUG(@"Configured profiling options: <%@: {\n lifecycle: %@\n sessionSampleRate: " @"%.2f\n profileAppStarts: %@\n}", - options.profiling, - options.profiling.lifecycle == SentryProfileLifecycleTrace ? @"trace" : @"manual", - options.profiling.sessionSampleRate, options.profiling.profileAppStarts ? @"YES" : @"NO"); + options.profiling, sentry_isTraceLifecycle(profilingOptions) ? @"trace" : @"manual", + sentry_sessionSampleRate(profilingOptions), + sentry_profileAppStarts(profilingOptions) ? @"YES" : @"NO"); } void sentry_sdkInitProfilerTasks(SentryOptions *options, SentryHub *hub) { + // get the configuration options from the last time the launch config was written; it may be + // different than the new options the SDK was just started with + SentryProfileConfiguration *configurationFromLaunch = sentry_profileConfiguration; + sentry_configureContinuousProfiling(options); - [SentryDependencyContainer.sharedInstance.dispatchQueueWrapper dispatchAsyncWithBlock:^{ - // get the configuration options from the last time the launch config was written; it may be - // different than the new options the SDK was just started with - const auto configDict = sentry_appLaunchProfileConfiguration(); - const auto profileIsContinuousV1 = - [configDict[kSentryLaunchProfileConfigKeyContinuousProfiling] boolValue]; - const auto profileIsContinuousV2 = - [configDict[kSentryLaunchProfileConfigKeyContinuousProfilingV2] boolValue]; - const auto v2LifecycleValue - = configDict[kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle]; - const auto v2Lifecycle = (SentryProfileLifecycle) - [configDict[kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle] intValue]; - const auto v2LifecycleIsManual = profileIsContinuousV2 && v2LifecycleValue != nil - && v2Lifecycle == SentryProfileLifecycleManual; - - BOOL shouldStopAndTransmitLaunchProfile = YES; + sentry_dispatchAsync(SentryDependencyContainer.sharedInstance.dispatchQueueWrapper, ^{ + if (configurationFromLaunch.isProfilingThisLaunch) { + BOOL shouldStopAndTransmitLaunchProfile = YES; + + const auto profileIsContinuousV2 = configurationFromLaunch.profileOptions != nil; + const auto v2LifecycleIsManual = profileIsContinuousV2 + && !sentry_isTraceLifecycle(SENTRY_UNWRAP_NULLABLE( + SentryProfileOptions, configurationFromLaunch.profileOptions)); # if SENTRY_HAS_UIKIT - const auto v2LifecycleIsTrace = profileIsContinuousV2 && v2LifecycleValue != nil - && v2Lifecycle == SentryProfileLifecycleTrace; - const auto profileIsCorrelatedToTrace = !profileIsContinuousV2 || v2LifecycleIsTrace; - SentryUIViewControllerPerformanceTracker *performanceTracker = - [SentryDependencyContainer.sharedInstance uiViewControllerPerformanceTracker]; - if (profileIsCorrelatedToTrace && performanceTracker.alwaysWaitForFullDisplay) { - SENTRY_LOG_DEBUG(@"Will wait to stop launch profile correlated to a trace until full " - @"display reported."); - shouldStopAndTransmitLaunchProfile = NO; - } + const auto v2LifecycleIsTrace = profileIsContinuousV2 + && sentry_isTraceLifecycle(SENTRY_UNWRAP_NULLABLE( + SentryProfileOptions, configurationFromLaunch.profileOptions)); + const auto profileIsCorrelatedToTrace = !profileIsContinuousV2 || v2LifecycleIsTrace; + if (profileIsCorrelatedToTrace && configurationFromLaunch.waitForFullDisplay) { + SENTRY_LOG_DEBUG( + @"Will wait to stop launch profile correlated to a trace until full " + @"display reported."); + shouldStopAndTransmitLaunchProfile = NO; + } # endif // SENTRY_HAS_UIKIT - if (profileIsContinuousV1 || v2LifecycleIsManual) { - SENTRY_LOG_DEBUG( - @"Continuous manual launch profiles aren't stopped on calls to SentrySDK.start, " - @"not stopping profile."); - shouldStopAndTransmitLaunchProfile = NO; - } + if (configurationFromLaunch.isContinuousV1 || v2LifecycleIsManual) { + SENTRY_LOG_DEBUG(@"Continuous manual launch profiles aren't stopped on calls to " + @"SentrySDK.start, " + @"not stopping profile."); + shouldStopAndTransmitLaunchProfile = NO; + } - if (shouldStopAndTransmitLaunchProfile) { - SENTRY_LOG_DEBUG(@"Stopping launch profile in SentrySDK.start because there will " - @"be no automatic trace to attach it to."); - sentry_stopAndTransmitLaunchProfile(hub); + if (shouldStopAndTransmitLaunchProfile) { + SENTRY_LOG_DEBUG( + @"Stopping launch profile in SentrySDK.start because there is no time " + @"to display tracker to stop it."); + sentry_stopAndDiscardLaunchProfileTracer(hub); + } } - sentry_configureLaunchProfiling(options); - }]; + sentry_configureLaunchProfilingForNextLaunch(options); + }); } @implementation SentryProfiler { @@ -151,7 +182,7 @@ + (void)load // initially, however we need to make sure to remove stale versions of the file before it gets // used to potentially start a launch profile that shouldn't have started, so we check here for // this - if ([NSProcessInfo.processInfo.arguments containsObject:@"--io.sentry.wipe-data"]) { + if ([NSProcessInfo.processInfo.arguments containsObject:@"--io.sentry.special.wipe-data"]) { removeSentryStaticBasePath(); } # endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) @@ -179,10 +210,8 @@ - (instancetype)initWithMode:(SentryProfilerMode)mode # if SENTRY_HAS_UIKIT if (mode == SentryProfilerModeTrace) { - [SentryDependencyContainer.sharedInstance.notificationCenterWrapper - addObserver:self - selector:@selector(backgroundAbort) - name:UIApplicationWillResignActiveNotification]; + sentry_addObserver( + self, @selector(backgroundAbort), UIApplicationWillResignActiveNotification, nil); } # endif // SENTRY_HAS_UIKIT @@ -206,22 +235,23 @@ - (void)stopForReason:(SentryProfilerTruncationReason)reason { sentry_isTracingAppLaunch = NO; [self.metricProfiler stop]; - self.truncationReason = reason; if (![self isRunning]) { - SENTRY_LOG_WARN(@"Profiler is not currently running."); + SENTRY_LOG_DEBUG(@"Profiler is not currently running."); return; } + self.truncationReason = reason; + # if SENTRY_HAS_UIKIT // if SentryOptions.enableAutoPerformanceTracing is NO and appHangsV2Disabled, which uses the // frames tracker, is YES, then we need to stop the frames tracker from running outside of // profiles because it isn't needed for anything else BOOL autoPerformanceTracingDisabled - = ![[[[SentrySDK currentHub] getClient] options] enableAutoPerformanceTracing]; + = ![[[[SentrySDKInternal currentHub] getClient] options] enableAutoPerformanceTracing]; BOOL appHangsV2Disabled = - [[[[SentrySDK currentHub] getClient] options] isAppHangTrackingV2Disabled]; + [[[[SentrySDKInternal currentHub] getClient] options] isAppHangTrackingV2Disabled]; if (autoPerformanceTracingDisabled && appHangsV2Disabled) { [SentryDependencyContainer.sharedInstance.framesTracker stop]; @@ -264,8 +294,7 @@ - (void)start _samplingProfiler = std::make_unique( [state](auto &backtrace) { Backtrace backtraceCopy = backtrace; - backtraceCopy.absoluteTimestamp - = SentryDependencyContainer.sharedInstance.dateProvider.systemTime; + backtraceCopy.absoluteTimestamp = sentry_getSystemTime(); @autoreleasepool { [state appendBacktrace:backtraceCopy]; } diff --git a/Sources/Sentry/SentryQueueableRequestManager.m b/Sources/Sentry/SentryQueueableRequestManager.m index e139f9f95e1..bd420c210ae 100644 --- a/Sources/Sentry/SentryQueueableRequestManager.m +++ b/Sources/Sentry/SentryQueueableRequestManager.m @@ -30,7 +30,7 @@ - (BOOL)isReady #if SENTRY_TEST || SENTRY_TEST_CI // force every envelope to be cached in UI tests so we can inspect what the SDK would've sent // for a given operation - if ([NSProcessInfo.processInfo.environment[@"--io.sentry.sdk-environment"] + if ([NSProcessInfo.processInfo.environment[@"--io.sentry.scope.sdk-environment"] isEqualToString:@"ui-tests"]) { return NO; } diff --git a/Sources/Sentry/SentryRandom.m b/Sources/Sentry/SentryRandom.m deleted file mode 100644 index 9847f3039fb..00000000000 --- a/Sources/Sentry/SentryRandom.m +++ /dev/null @@ -1,18 +0,0 @@ -#import "SentryRandom.h" - -@implementation SentryRandom - -- (instancetype)init -{ - if (self = [super init]) { - srand48(time(0)); // drand seed initializer - } - return self; -} - -- (double)nextNumber -{ - return drand48(); -} - -@end diff --git a/Sources/Sentry/SentryReplayApi.m b/Sources/Sentry/SentryReplayApi.m index 5455698af09..7472e31f687 100644 --- a/Sources/Sentry/SentryReplayApi.m +++ b/Sources/Sentry/SentryReplayApi.m @@ -27,7 +27,7 @@ - (void)pause { SENTRY_LOG_INFO(@"[Session Replay] Pausing session"); SentrySessionReplayIntegration *replayIntegration - = (SentrySessionReplayIntegration *)[SentrySDK.currentHub + = (SentrySessionReplayIntegration *)[SentrySDKInternal.currentHub getInstalledIntegration:SentrySessionReplayIntegration.class]; [replayIntegration pause]; } @@ -36,7 +36,7 @@ - (void)resume { SENTRY_LOG_INFO(@"[Session Replay] Resuming session"); SentrySessionReplayIntegration *replayIntegration - = (SentrySessionReplayIntegration *)[SentrySDK.currentHub + = (SentrySessionReplayIntegration *)[SentrySDKInternal.currentHub getInstalledIntegration:SentrySessionReplayIntegration.class]; [replayIntegration resume]; } @@ -45,7 +45,7 @@ - (void)start SENTRY_DISABLE_THREAD_SANITIZER("double-checked lock produce false { SENTRY_LOG_INFO(@"[Session Replay] Starting session"); SentrySessionReplayIntegration *replayIntegration - = (SentrySessionReplayIntegration *)[SentrySDK.currentHub + = (SentrySessionReplayIntegration *)[SentrySDKInternal.currentHub getInstalledIntegration:SentrySessionReplayIntegration.class]; // Start could be misused and called multiple times, causing it to @@ -53,15 +53,15 @@ - (void)start SENTRY_DISABLE_THREAD_SANITIZER("double-checked lock produce false // Synchronizing it will prevent this problem. if (replayIntegration == nil) { @synchronized(self) { - replayIntegration = (SentrySessionReplayIntegration *)[SentrySDK.currentHub + replayIntegration = (SentrySessionReplayIntegration *)[SentrySDKInternal.currentHub getInstalledIntegration:SentrySessionReplayIntegration.class]; if (replayIntegration == nil) { SENTRY_LOG_DEBUG(@"[Session Replay] Initializing replay integration"); - SentryOptions *currentOptions = SentrySDK.currentHub.client.options; + SentryOptions *currentOptions = SentrySDKInternal.currentHub.client.options; replayIntegration = [[SentrySessionReplayIntegration alloc] initForManualUse:currentOptions]; - [SentrySDK.currentHub + [SentrySDKInternal.currentHub addInstalledIntegration:replayIntegration name:NSStringFromClass(SentrySessionReplay.class)]; } @@ -74,7 +74,7 @@ - (void)stop { SENTRY_LOG_INFO(@"[Session Replay] Stopping session"); SentrySessionReplayIntegration *replayIntegration - = (SentrySessionReplayIntegration *)[SentrySDK.currentHub + = (SentrySessionReplayIntegration *)[SentrySDKInternal.currentHub getInstalledIntegration:SentrySessionReplayIntegration.class]; [replayIntegration stop]; } @@ -89,7 +89,7 @@ - (void)showMaskPreview:(CGFloat)opacity { SENTRY_LOG_DEBUG(@"[Session Replay] Showing mask preview with opacity: %f", opacity); SentrySessionReplayIntegration *replayIntegration - = (SentrySessionReplayIntegration *)[SentrySDK.currentHub + = (SentrySessionReplayIntegration *)[SentrySDKInternal.currentHub getInstalledIntegration:SentrySessionReplayIntegration.class]; [replayIntegration showMaskPreview:opacity]; @@ -99,7 +99,7 @@ - (void)hideMaskPreview { SENTRY_LOG_DEBUG(@"[Session Replay] Hiding mask preview"); SentrySessionReplayIntegration *replayIntegration - = (SentrySessionReplayIntegration *)[SentrySDK.currentHub + = (SentrySessionReplayIntegration *)[SentrySDKInternal.currentHub getInstalledIntegration:SentrySessionReplayIntegration.class]; [replayIntegration hideMaskPreview]; diff --git a/Sources/Sentry/SentryRequestOperation.m b/Sources/Sentry/SentryRequestOperation.m index f4acb708d0b..e7aa5e9f608 100644 --- a/Sources/Sentry/SentryRequestOperation.m +++ b/Sources/Sentry/SentryRequestOperation.m @@ -2,6 +2,7 @@ #import "SentryClient.h" #import "SentryError.h" #import "SentryHub.h" +#import "SentryInternalDefines.h" #import "SentryLogC.h" #import "SentryOptions.h" #import "SentrySDK+Private.h" @@ -25,30 +26,33 @@ - (instancetype)initWithSession:(NSURLSession *)session self = [super init]; if (self) { self.request = request; - self.task = [session dataTaskWithRequest:self.request - completionHandler:^(NSData *_Nullable data, - NSURLResponse *_Nullable response, NSError *_Nullable error) { - NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; - NSInteger statusCode = [httpResponse statusCode]; + self.task = [session + dataTaskWithRequest:self.request + completionHandler:^(NSData *_Nullable data, NSURLResponse *_Nullable response, + NSError *_Nullable error) { + NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; + NSInteger statusCode = [httpResponse statusCode]; - // We only have these if's here because of performance reasons - SENTRY_LOG_DEBUG(@"Request status: %ld", (long)statusCode); - if ([SentrySDK.currentHub getClient].options.debug == YES) { - SENTRY_LOG_DEBUG(@"Request response: %@", - [[NSString alloc] initWithData:data - encoding:NSUTF8StringEncoding]); - } + // We only have these if's here because of performance reasons + SENTRY_LOG_DEBUG(@"Request status: %ld", (long)statusCode); + if ([SentrySDKInternal.currentHub getClient].options.debug == YES) { + SENTRY_LOG_DEBUG(@"Request response: %@", + data != nil + ? [[NSString alloc] initWithData:SENTRY_UNWRAP_NULLABLE(NSData, data) + encoding:NSUTF8StringEncoding] + : @""); + } - if (nil != error) { - SENTRY_LOG_ERROR(@"Request failed: %@", error); - } + if (nil != error) { + SENTRY_LOG_ERROR(@"Request failed: %@", error); + } - if (completionHandler) { - completionHandler(httpResponse, error); - } + if (completionHandler) { + completionHandler(httpResponse, error); + } - [self completeOperation]; - }]; + [self completeOperation]; + }]; } return self; } diff --git a/Sources/Sentry/SentryRetryAfterHeaderParser.m b/Sources/Sentry/SentryRetryAfterHeaderParser.m index 5186207ab2a..5884dbea60a 100644 --- a/Sources/Sentry/SentryRetryAfterHeaderParser.m +++ b/Sources/Sentry/SentryRetryAfterHeaderParser.m @@ -1,5 +1,6 @@ #import "SentryRetryAfterHeaderParser.h" #import "SentryHttpDateParser.h" +#import "SentryInternalDefines.h" #import "SentrySwift.h" NS_ASSUME_NONNULL_BEGIN @@ -35,7 +36,8 @@ - (NSDate *_Nullable)parse:(NSString *_Nullable)retryAfterHeader } // parsing as double/seconds failed, try to parse as date - NSDate *retryAfterDate = [self.httpDateParser dateFromString:retryAfterHeader]; + NSDate *retryAfterDate = + [self.httpDateParser dateFromString:SENTRY_UNWRAP_NULLABLE(NSString, retryAfterHeader)]; return retryAfterDate; } diff --git a/Sources/Sentry/SentrySDK.m b/Sources/Sentry/SentrySDKInternal.m similarity index 66% rename from Sources/Sentry/SentrySDK.m rename to Sources/Sentry/SentrySDKInternal.m index cae4238ec07..1aa33ec6d20 100644 --- a/Sources/Sentry/SentrySDK.m +++ b/Sources/Sentry/SentrySDKInternal.m @@ -1,21 +1,19 @@ -#import "SentrySDK.h" +#import "SentrySDKInternal.h" #import "PrivateSentrySDKOnly.h" #import "SentryANRTrackingIntegration.h" #import "SentryAppStartMeasurement.h" #import "SentryAppStateManager.h" -#import "SentryBinaryImageCache.h" #import "SentryBreadcrumb.h" #import "SentryClient+Private.h" #import "SentryCrash.h" -#import "SentryCrashWrapper.h" #import "SentryDependencyContainer.h" #import "SentryFileManager.h" #import "SentryHub+Private.h" #import "SentryInternalDefines.h" #import "SentryLogC.h" #import "SentryMeta.h" -#import "SentryNSProcessInfoWrapper.h" #import "SentryOptions+Private.h" +#import "SentryOptionsInternal.h" #import "SentryProfilingConditionals.h" #import "SentryReplayApi.h" #import "SentrySamplerDecision.h" @@ -24,7 +22,6 @@ #import "SentrySerialization.h" #import "SentrySwift.h" #import "SentryTransactionContext.h" -#import "SentryUIApplication.h" #import "SentryUseNSExceptionCallstackWrapper.h" #import "SentryUserFeedbackIntegration.h" @@ -33,7 +30,6 @@ #endif // TARGET_OS_MAC #if SENTRY_HAS_UIKIT -# import "SentryUIDeviceWrapper.h" # import "SentryUIViewControllerPerformanceTracker.h" # if TARGET_OS_IOS # import "SentryFeedbackAPI.h" @@ -42,23 +38,51 @@ #if SENTRY_TARGET_PROFILING_SUPPORTED # import "SentryContinuousProfiler.h" +# import "SentryProfileConfiguration.h" # import "SentryProfiler+Private.h" #endif // SENTRY_TARGET_PROFILING_SUPPORTED +@implementation SentryIdWrapper + +- (instancetype)initWithId:(NSString *)sentryIdString +{ + if (self = [super init]) { + self.sentryIdString = sentryIdString; + return self; + } + return nil; +} + +- (SentryId *)sentryId +{ + return [[SentryId alloc] initWithUUIDString:self.sentryIdString]; +} + +@end + +@implementation SentryId (Wrapper) + +- (SentryIdWrapper *)wrapper +{ + return [[SentryIdWrapper alloc] initWithId:self.sentryIdString]; +} + +@end + NSString *const SENTRY_XCODE_PREVIEW_ENVIRONMENT_KEY = @"XCODE_RUNNING_FOR_PREVIEWS"; -@interface SentrySDK () +@interface SentrySDKInternal () @property (class) SentryHub *currentHub; @end NS_ASSUME_NONNULL_BEGIN -@implementation SentrySDK +@implementation SentrySDKInternal static SentryHub *_Nullable currentHub; static NSObject *currentHubLock; static BOOL crashedLastRunCalled; -static SentryAppStartMeasurement *sentrySDKappStartMeasurement; +static SentryAppStartMeasurement *_Nullable sentrySDKappStartMeasurement; static NSObject *sentrySDKappStartMeasurementLock; static BOOL _detectedStartUpCrash; static SentryOptions *_Nullable startOption; @@ -77,7 +101,7 @@ @implementation SentrySDK + (void)initialize { - if (self == [SentrySDK class]) { + if (self == [SentrySDKInternal class]) { sentrySDKappStartMeasurementLock = [[NSObject alloc] init]; currentHubLock = [[NSObject alloc] init]; startOptionsLock = [[NSObject alloc] init]; @@ -92,7 +116,7 @@ + (SentryHub *)currentHub if (nil == currentHub) { currentHub = [[SentryHub alloc] initWithClient:nil andScope:nil]; } - return currentHub; + return SENTRY_UNWRAP_NULLABLE(SentryHub, currentHub); } } @@ -111,6 +135,7 @@ + (SentryReplayApi *)replay return replay; } #endif + /** Internal, only needed for testing. */ + (void)setCurrentHub:(nullable SentryHub *)hub { @@ -136,11 +161,6 @@ + (BOOL)isEnabled return currentHub != nil && [currentHub getClient] != nil; } -+ (SentryMetricsAPI *)metrics -{ - return currentHub.metrics; -} - + (BOOL)crashedLastRunCalled { return crashedLastRunCalled; @@ -233,6 +253,9 @@ + (void)startWithOptions:(SentryOptions *)options // Reference to SentryCrashExceptionApplication to prevent compiler from stripping it [SentryCrashExceptionApplication class]; #endif + // These classes must be referenced somewhere for their files to not be stripped. + [PlaceholderSentryApplication class]; + [PlaceholderProcessInfoClass class]; startInvocations++; startTimestamp = [SentryDependencyContainer.sharedInstance.dateProvider date]; @@ -259,12 +282,12 @@ + (void)startWithOptions:(SentryOptions *)options // The Hub needs to be initialized with a client so that closing a session // can happen. SentryHub *hub = [[SentryHub alloc] initWithClient:newClient andScope:scope]; - [SentrySDK setCurrentHub:hub]; + [SentrySDKInternal setCurrentHub:hub]; - [SentryCrashWrapper.sharedInstance startBinaryImageCache]; - [SentryDependencyContainer.sharedInstance.binaryImageCache start]; + [SentryDependencyContainer.sharedInstance.crashWrapper startBinaryImageCache]; + [SentryDependencyContainer.sharedInstance.binaryImageCache start:options.debug]; - [SentrySDK installIntegrations]; + [SentrySDKInternal installIntegrations]; #if SENTRY_TARGET_PROFILING_SUPPORTED sentry_sdkInitProfilerTasks(options, hub); @@ -278,120 +301,122 @@ + (void)startWithConfigureOptions:(void (^)(SentryOptions *options))configureOpt { SentryOptions *options = [[SentryOptions alloc] init]; configureOptions(options); - [SentrySDK startWithOptions:options]; + [SentrySDKInternal startWithOptions:options]; } + (void)captureFatalEvent:(SentryEvent *)event { - [SentrySDK.currentHub captureFatalEvent:event]; + [SentrySDKInternal.currentHub captureFatalEvent:event]; } + (void)captureFatalEvent:(SentryEvent *)event withScope:(SentryScope *)scope { - [SentrySDK.currentHub captureFatalEvent:event withScope:scope]; + [SentrySDKInternal.currentHub captureFatalEvent:event withScope:scope]; } #if SENTRY_HAS_UIKIT + (void)captureFatalAppHangEvent:(SentryEvent *)event { - [SentrySDK.currentHub captureFatalAppHangEvent:event]; + [SentrySDKInternal.currentHub captureFatalAppHangEvent:event]; } #endif // SENTRY_HAS_UIKIT -+ (SentryId *)captureEvent:(SentryEvent *)event ++ (SentryIdWrapper *)captureEvent:(SentryEvent *)event { - return [SentrySDK captureEvent:event withScope:SentrySDK.currentHub.scope]; + return [SentrySDKInternal captureEvent:event withScope:SentrySDKInternal.currentHub.scope]; } -+ (SentryId *)captureEvent:(SentryEvent *)event withScopeBlock:(void (^)(SentryScope *))block ++ (SentryIdWrapper *)captureEvent:(SentryEvent *)event withScopeBlock:(void (^)(SentryScope *))block { - SentryScope *scope = [[SentryScope alloc] initWithScope:SentrySDK.currentHub.scope]; + SentryScope *scope = [[SentryScope alloc] initWithScope:SentrySDKInternal.currentHub.scope]; block(scope); - return [SentrySDK captureEvent:event withScope:scope]; + return [SentrySDKInternal captureEvent:event withScope:scope]; } -+ (SentryId *)captureEvent:(SentryEvent *)event withScope:(SentryScope *)scope ++ (SentryIdWrapper *)captureEvent:(SentryEvent *)event withScope:(SentryScope *)scope { - return [SentrySDK.currentHub captureEvent:event withScope:scope]; + return [SentrySDKInternal.currentHub captureEvent:event withScope:scope].wrapper; } + (id)startTransactionWithName:(NSString *)name operation:(NSString *)operation { - return [SentrySDK.currentHub startTransactionWithName:name operation:operation]; + return [SentrySDKInternal.currentHub startTransactionWithName:name operation:operation]; } + (id)startTransactionWithName:(NSString *)name operation:(NSString *)operation bindToScope:(BOOL)bindToScope { - return [SentrySDK.currentHub startTransactionWithName:name - operation:operation - bindToScope:bindToScope]; + return [SentrySDKInternal.currentHub startTransactionWithName:name + operation:operation + bindToScope:bindToScope]; } + (id)startTransactionWithContext:(SentryTransactionContext *)transactionContext { - return [SentrySDK.currentHub startTransactionWithContext:transactionContext]; + return [SentrySDKInternal.currentHub startTransactionWithContext:transactionContext]; } + (id)startTransactionWithContext:(SentryTransactionContext *)transactionContext bindToScope:(BOOL)bindToScope { - return [SentrySDK.currentHub startTransactionWithContext:transactionContext - bindToScope:bindToScope]; + return [SentrySDKInternal.currentHub startTransactionWithContext:transactionContext + bindToScope:bindToScope]; } + (id)startTransactionWithContext:(SentryTransactionContext *)transactionContext bindToScope:(BOOL)bindToScope customSamplingContext:(NSDictionary *)customSamplingContext { - return [SentrySDK.currentHub startTransactionWithContext:transactionContext - bindToScope:bindToScope - customSamplingContext:customSamplingContext]; + return [SentrySDKInternal.currentHub startTransactionWithContext:transactionContext + bindToScope:bindToScope + customSamplingContext:customSamplingContext]; } + (id)startTransactionWithContext:(SentryTransactionContext *)transactionContext customSamplingContext:(NSDictionary *)customSamplingContext { - return [SentrySDK.currentHub startTransactionWithContext:transactionContext - customSamplingContext:customSamplingContext]; + return [SentrySDKInternal.currentHub startTransactionWithContext:transactionContext + customSamplingContext:customSamplingContext]; } -+ (SentryId *)captureError:(NSError *)error ++ (SentryIdWrapper *)captureError:(NSError *)error { - return [SentrySDK captureError:error withScope:SentrySDK.currentHub.scope]; + return [SentrySDKInternal captureError:error withScope:SentrySDKInternal.currentHub.scope]; } -+ (SentryId *)captureError:(NSError *)error withScopeBlock:(void (^)(SentryScope *_Nonnull))block ++ (SentryIdWrapper *)captureError:(NSError *)error + withScopeBlock:(void (^)(SentryScope *_Nonnull))block { - SentryScope *scope = [[SentryScope alloc] initWithScope:SentrySDK.currentHub.scope]; + SentryScope *scope = [[SentryScope alloc] initWithScope:SentrySDKInternal.currentHub.scope]; block(scope); - return [SentrySDK captureError:error withScope:scope]; + return [SentrySDKInternal captureError:error withScope:scope]; } -+ (SentryId *)captureError:(NSError *)error withScope:(SentryScope *)scope ++ (SentryIdWrapper *)captureError:(NSError *)error withScope:(SentryScope *)scope { - return [SentrySDK.currentHub captureError:error withScope:scope]; + return [SentrySDKInternal.currentHub captureError:error withScope:scope].wrapper; } -+ (SentryId *)captureException:(NSException *)exception ++ (SentryIdWrapper *)captureException:(NSException *)exception { - return [SentrySDK captureException:exception withScope:SentrySDK.currentHub.scope]; + return [SentrySDKInternal captureException:exception + withScope:SentrySDKInternal.currentHub.scope]; } -+ (SentryId *)captureException:(NSException *)exception - withScopeBlock:(void (^)(SentryScope *))block ++ (SentryIdWrapper *)captureException:(NSException *)exception + withScopeBlock:(void (^)(SentryScope *))block { - SentryScope *scope = [[SentryScope alloc] initWithScope:SentrySDK.currentHub.scope]; + SentryScope *scope = [[SentryScope alloc] initWithScope:SentrySDKInternal.currentHub.scope]; block(scope); - return [SentrySDK captureException:exception withScope:scope]; + return [SentrySDKInternal captureException:exception withScope:scope]; } -+ (SentryId *)captureException:(NSException *)exception withScope:(SentryScope *)scope ++ (SentryIdWrapper *)captureException:(NSException *)exception withScope:(SentryScope *)scope { - return [SentrySDK.currentHub captureException:exception withScope:scope]; + return [SentrySDKInternal.currentHub captureException:exception withScope:scope].wrapper; } #if TARGET_OS_OSX @@ -404,26 +429,29 @@ + (SentryId *)captureCrashOnException:(NSException *)exception reason:exception.reason userInfo:exception.userInfo callStackReturnAddresses:exception.callStackReturnAddresses]; - return [SentrySDK captureException:wrappedException withScope:SentrySDK.currentHub.scope]; + return [SentrySDKInternal captureException:wrappedException + withScope:SentrySDKInternal.currentHub.scope] + .sentryId; } #endif // TARGET_OS_OSX -+ (SentryId *)captureMessage:(NSString *)message ++ (SentryIdWrapper *)captureMessage:(NSString *)message { - return [SentrySDK captureMessage:message withScope:SentrySDK.currentHub.scope]; + return [SentrySDKInternal captureMessage:message withScope:SentrySDKInternal.currentHub.scope]; } -+ (SentryId *)captureMessage:(NSString *)message withScopeBlock:(void (^)(SentryScope *))block ++ (SentryIdWrapper *)captureMessage:(NSString *)message + withScopeBlock:(void (^)(SentryScope *))block { - SentryScope *scope = [[SentryScope alloc] initWithScope:SentrySDK.currentHub.scope]; + SentryScope *scope = [[SentryScope alloc] initWithScope:SentrySDKInternal.currentHub.scope]; block(scope); - return [SentrySDK captureMessage:message withScope:scope]; + return [SentrySDKInternal captureMessage:message withScope:scope]; } -+ (SentryId *)captureMessage:(NSString *)message withScope:(SentryScope *)scope ++ (SentryIdWrapper *)captureMessage:(NSString *)message withScope:(SentryScope *)scope { - return [SentrySDK.currentHub captureMessage:message withScope:scope]; + return [SentrySDKInternal.currentHub captureMessage:message withScope:scope].wrapper; } /** @@ -431,7 +459,7 @@ + (SentryId *)captureMessage:(NSString *)message withScope:(SentryScope *)scope */ + (void)captureEnvelope:(SentryEnvelope *)envelope { - [SentrySDK.currentHub captureEnvelope:envelope]; + [SentrySDKInternal.currentHub captureEnvelope:envelope]; } /** @@ -439,19 +467,23 @@ + (void)captureEnvelope:(SentryEnvelope *)envelope */ + (void)storeEnvelope:(SentryEnvelope *)envelope { - [SentrySDK.currentHub storeEnvelope:envelope]; + [SentrySDKInternal.currentHub storeEnvelope:envelope]; } #if !SDK_V9 + (void)captureUserFeedback:(SentryUserFeedback *)userFeedback { - [SentrySDK.currentHub captureUserFeedback:userFeedback]; + [SentrySDKInternal.currentHub captureUserFeedback:userFeedback]; } #endif // !SDK_V9 -+ (void)captureFeedback:(SentryFeedback *)feedback ++ (void)captureSerializedFeedback:(NSDictionary *)serializedFeedback + withEventId:(NSString *)feedbackEventId + attachments:(NSArray *)feedbackAttachments { - [SentrySDK.currentHub captureFeedback:feedback]; + [SentrySDKInternal.currentHub captureSerializedFeedback:serializedFeedback + withEventId:feedbackEventId + attachments:feedbackAttachments]; } #if TARGET_OS_IOS && SENTRY_HAS_UIKIT @@ -468,17 +500,28 @@ + (SentryFeedbackAPI *)feedback + (void)addBreadcrumb:(SentryBreadcrumb *)crumb { - [SentrySDK.currentHub addBreadcrumb:crumb]; + if (![SentrySDKInternal isEnabled]) { + // We must log with level fatal because only fatal messages get logged even when the SDK + // isn't started. We've seen multiple times that users try to add a breadcrumb before + // starting the SDK, and it confuses them. Ideally, we would do something to store the user + // and set it once we start the SDK, but this is a breaking change, so we live with the + // workaround for now. + SENTRY_LOG_FATAL( + @"The SDK is disabled, so addBreadcrumb doesn't work. Please ensure to start " + @"the SDK before adding breadcrumbs."); + } + + [SentrySDKInternal.currentHub addBreadcrumb:crumb]; } + (void)configureScope:(void (^)(SentryScope *scope))callback { - [SentrySDK.currentHub configureScope:callback]; + [SentrySDKInternal.currentHub configureScope:callback]; } + (void)setUser:(SentryUser *_Nullable)user { - if (![SentrySDK isEnabled]) { + if (![SentrySDKInternal isEnabled]) { // We must log with level fatal because only fatal messages get logged even when the SDK // isn't started. We've seen multiple times that users try to set the user before starting // the SDK, and it confuses them. Ideally, we would do something to store the user and set @@ -488,7 +531,7 @@ + (void)setUser:(SentryUser *_Nullable)user @"the SDK before setting the user."); } - [SentrySDK.currentHub setUser:user]; + [SentrySDKInternal.currentHub setUser:user]; } + (BOOL)crashedLastRun @@ -508,12 +551,12 @@ + (void)setDetectedStartUpCrash:(BOOL)value + (void)startSession { - [SentrySDK.currentHub startSession]; + [SentrySDKInternal.currentHub startSession]; } + (void)endSession { - [SentrySDK.currentHub endSession]; + [SentrySDKInternal.currentHub endSession]; } /** @@ -521,15 +564,22 @@ + (void)endSession */ + (void)installIntegrations { - if (nil == [SentrySDK.currentHub getClient]) { + if (nil == [SentrySDKInternal.currentHub getClient]) { // Gatekeeper return; } - SentryOptions *options = [SentrySDK.currentHub getClient].options; + SentryOptions *options = [SentrySDKInternal.currentHub getClient].options; +#if SDK_V9 + NSMutableArray *integrationNames = [SentryOptions defaultIntegrations].mutableCopy; +#else +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" NSMutableArray *integrationNames = - [SentrySDK.currentHub getClient].options.integrations.mutableCopy; + [SentrySDKInternal.currentHub getClient].options.integrations.mutableCopy; +# pragma clang diagnostic pop +#endif // SDK_V9 - NSArray *defaultIntegrations = SentryOptions.defaultIntegrationClasses; + NSArray *defaultIntegrations = SentryOptionsInternal.defaultIntegrationClasses; // Since 8.22.0, we use a precompiled XCFramework for SPM, which can lead to Sentry's // definition getting duplicated in the app with a warning “SentrySDK is defined in both @@ -556,7 +606,7 @@ + (void)installIntegrations @"couldn't find \"%@\" -> skipping.", integrationName); continue; - } else if ([SentrySDK.currentHub isIntegrationInstalled:integrationClass]) { + } else if ([SentrySDKInternal.currentHub isIntegrationInstalled:integrationClass]) { SENTRY_LOG_ERROR( @"[SentryHub doInstallIntegrations] already installed \"%@\" -> skipping.", integrationName); @@ -567,20 +617,21 @@ + (void)installIntegrations if (shouldInstall) { SENTRY_LOG_DEBUG(@"Integration installed: %@", integrationName); - [SentrySDK.currentHub addInstalledIntegration:integrationInstance name:integrationName]; + [SentrySDKInternal.currentHub addInstalledIntegration:integrationInstance + name:integrationName]; } } } + (void)reportFullyDisplayed { - [SentrySDK.currentHub reportFullyDisplayed]; + [SentrySDKInternal.currentHub reportFullyDisplayed]; } + (void)pauseAppHangTracking { SentryANRTrackingIntegration *anrTrackingIntegration - = (SentryANRTrackingIntegration *)[SentrySDK.currentHub + = (SentryANRTrackingIntegration *)[SentrySDKInternal.currentHub getInstalledIntegration:[SentryANRTrackingIntegration class]]; [anrTrackingIntegration pauseAppHangTracking]; @@ -589,7 +640,7 @@ + (void)pauseAppHangTracking + (void)resumeAppHangTracking { SentryANRTrackingIntegration *anrTrackingIntegration - = (SentryANRTrackingIntegration *)[SentrySDK.currentHub + = (SentryANRTrackingIntegration *)[SentrySDKInternal.currentHub getInstalledIntegration:[SentryANRTrackingIntegration class]]; [anrTrackingIntegration resumeAppHangTracking]; @@ -597,7 +648,7 @@ + (void)resumeAppHangTracking + (void)flush:(NSTimeInterval)timeout { - [SentrySDK.currentHub flush:timeout]; + [SentrySDKInternal.currentHub flush:timeout]; } /** @@ -613,7 +664,7 @@ + (void)close startTimestamp = nil; - SentryHub *hub = SentrySDK.currentHub; + SentryHub *hub = SentrySDKInternal.currentHub; [hub removeAllIntegrations]; SENTRY_LOG_DEBUG(@"Uninstalled all integrations."); @@ -627,9 +678,11 @@ + (void)close [hub close]; [hub bindClient:nil]; - [SentrySDK setCurrentHub:nil]; + [SentrySDKInternal setCurrentHub:nil]; + + [SentrySDK clearLogger]; - [SentryCrashWrapper.sharedInstance stopBinaryImageCache]; + [SentryDependencyContainer.sharedInstance.crashWrapper stopBinaryImageCache]; [SentryDependencyContainer.sharedInstance.binaryImageCache stop]; #if TARGET_OS_IOS && SENTRY_HAS_UIKIT @@ -653,6 +706,7 @@ + (void)crash + (void)startProfiler { SentryOptions *options = currentHub.client.options; +# if !SDK_V9 if (![options isContinuousProfilingEnabled]) { SENTRY_LOG_WARN( @"You must disable trace profiling by setting SentryOptions.profilesSampleRate and " @@ -662,6 +716,7 @@ + (void)startProfiler @"relies on deprecated options and will change in a future version."); return; } +# endif // !SDK_V9 if (options.profiling != nil) { if (options.profiling.lifecycle == SentryProfileLifecycleTrace) { @@ -671,7 +726,8 @@ + (void)startProfiler return; } - if (sentry_profilerSessionSampleDecision.decision != kSentrySampleDecisionYes) { + if (sentry_profileConfiguration.profilerSessionSampleDecision.decision + != kSentrySampleDecisionYes) { SENTRY_LOG_DEBUG( @"The profiling session has been sampled out, no profiling will take place."); return; @@ -688,7 +744,37 @@ + (void)startProfiler + (void)stopProfiler { + // check if we'd be stopping a launch profiler, because then we need to check the hydrated + // configuration options, not the current ones + if (sentry_profileConfiguration.isProfilingThisLaunch) { + if (sentry_profileConfiguration.isContinuousV1) { + SENTRY_LOG_DEBUG(@"Stopping continuous v1 launch profile."); + [SentryContinuousProfiler stop]; + return; + } + + if (sentry_profileConfiguration.profileOptions == nil) { + SENTRY_LOG_WARN( + @"The current profiler was started on app launch and was configured as a " + @"transaction profiler, which cannot be stopped manually. Transaction profiling is " + @"deprecated and will be removed in a future SDK version."); + return; + } + + if (sentry_profileConfiguration.profileOptions.lifecycle == SentryProfileLifecycleTrace) { + SENTRY_LOG_WARN( + @"The launch profile lifecycle was set to trace, so you cannot stop profile " + @"sessions manually. See SentryProfileLifecycle for more information."); + return; + } + + SENTRY_LOG_DEBUG(@"Stopping launch UI profiler with manual lifecycle."); + [SentryContinuousProfiler stop]; + return; + } + SentryOptions *options = currentHub.client.options; +# if !SDK_V9 if (![options isContinuousProfilingEnabled]) { SENTRY_LOG_WARN( @"You must disable trace profiling by setting SentryOptions.profilesSampleRate and " @@ -698,6 +784,7 @@ + (void)stopProfiler @"relies on deprecated options and will change in a future version."); return; } +# endif // !SDK_V9 if (options.profiling != nil && options.profiling.lifecycle == SentryProfileLifecycleTrace) { SENTRY_LOG_WARN( diff --git a/Sources/Sentry/SentrySampling.m b/Sources/Sentry/SentrySampling.m index 4e674062456..91dc5d5c1e3 100644 --- a/Sources/Sentry/SentrySampling.m +++ b/Sources/Sentry/SentrySampling.m @@ -2,10 +2,10 @@ #import "SentryDependencyContainer.h" #import "SentryInternalDefines.h" #import "SentryOptions.h" -#import "SentryRandom.h" #import "SentrySampleDecision.h" #import "SentrySamplerDecision.h" #import "SentrySamplingContext.h" +#import "SentrySwift.h" #import "SentryTransactionContext.h" #import @@ -87,6 +87,7 @@ #if SENTRY_TARGET_PROFILING_SUPPORTED +# if !SDK_V9 SentrySamplerDecision * sentry_sampleTraceProfile(SentrySamplingContext *context, SentrySamplerDecision *tracesSamplerDecision, SentryOptions *options) @@ -101,23 +102,27 @@ } // Backward compatibility for clients that are still using the enableProfiling option. -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wdeprecated-declarations" +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" if (options.enableProfiling) { return [[SentrySamplerDecision alloc] initWithDecision:kSentrySampleDecisionYes forSampleRate:@1.0 withSampleRand:@1.0]; } -# pragma clang diagnostic pop NSNumber *callbackRate = _sentry_samplerCallbackRate( options.profilesSampler, context, SENTRY_DEFAULT_PROFILES_SAMPLE_RATE); +# pragma clang diagnostic pop if (callbackRate != nil) { return _sentry_calcSample(callbackRate); } +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" return _sentry_calcSampleFromNumericalRate(options.profilesSampleRate); +# pragma clang diagnostic pop } +# endif // !SDK_V9 SentrySamplerDecision * sentry_sampleProfileSession(float sessionSampleRate) diff --git a/Sources/Sentry/SentryScope.m b/Sources/Sentry/SentryScope.m index 32835f3ed9c..c7a0a4b53d6 100644 --- a/Sources/Sentry/SentryScope.m +++ b/Sources/Sentry/SentryScope.m @@ -1,18 +1,21 @@ #import "NSMutableDictionary+Sentry.h" #import "SentryAttachment+Private.h" #import "SentryBreadcrumb.h" -#import "SentryEnvelopeItemType.h" +#import "SentryDefines.h" #import "SentryEvent+Private.h" +#import "SentryInternalDefines.h" #import "SentryLevelMapper.h" #import "SentryLogC.h" +#import "SentryModels+Serializable.h" #import "SentryPropagationContext.h" #import "SentryScope+Private.h" +#import "SentryScope+PrivateSwift.h" #import "SentryScopeObserver.h" -#import "SentrySession.h" #import "SentrySpan.h" #import "SentrySwift.h" #import "SentryTracer.h" #import "SentryTransactionContext.h" +#import "SentryUser+Serialize.h" #import "SentryUser.h" NS_ASSUME_NONNULL_BEGIN @@ -150,11 +153,13 @@ - (void)setPropagationContext:(SentryPropagationContext *)propagationContext } } +#if !SDK_V9 - (void)useSpan:(SentrySpanCallback)callback { id localSpan = [self span]; callback(localSpan); } +#endif // !SDK_V9 - (void)clear { @@ -231,6 +236,13 @@ - (void)setContextValue:(NSDictionary *)value forKey:(NSString * } } +- (nullable NSDictionary *)getContextForKey:(NSString *)key +{ + @synchronized(_contextDictionary) { + return [_contextDictionary objectForKey:key]; + } +} + - (void)removeContextForKey:(NSString *)key { @synchronized(_contextDictionary) { @@ -277,7 +289,8 @@ - (void)setExtras:(NSDictionary *_Nullable)extras return; } @synchronized(_extraDictionary) { - [_extraDictionary addEntriesFromDictionary:extras]; + [_extraDictionary + addEntriesFromDictionary:SENTRY_UNWRAP_NULLABLE_DICT(NSString *, id, extras)]; for (id observer in self.observers) { [observer setExtras:_extraDictionary]; @@ -320,7 +333,8 @@ - (void)setTags:(NSDictionary *_Nullable)tags return; } @synchronized(_tagDictionary) { - [_tagDictionary addEntriesFromDictionary:tags]; + [_tagDictionary + addEntriesFromDictionary:SENTRY_UNWRAP_NULLABLE_DICT(NSString *, NSString *, tags)]; for (id observer in self.observers) { [observer setTags:_tagDictionary]; @@ -369,7 +383,8 @@ - (void)setFingerprint:(NSArray *_Nullable)fingerprint @synchronized(_fingerprintArray) { [_fingerprintArray removeAllObjects]; if (fingerprint != nil) { - [_fingerprintArray addObjectsFromArray:fingerprint]; + [_fingerprintArray + addObjectsFromArray:SENTRY_UNWRAP_NULLABLE(NSArray, fingerprint)]; } for (id observer in self.observers) { @@ -385,7 +400,7 @@ - (void)setFingerprint:(NSArray *_Nullable)fingerprint } } -- (void)setCurrentScreen:(nullable NSString *)currentScreen +- (void)setCurrentScreen:(NSString *_Nullable)currentScreen { _currentScreen = currentScreen; @@ -532,7 +547,8 @@ - (SentryEvent *__nullable)applyToEvent:(SentryEvent *)event } else { NSMutableDictionary *newTags = [NSMutableDictionary new]; [newTags addEntriesFromDictionary:[self tags]]; - [newTags addEntriesFromDictionary:event.tags]; + [newTags addEntriesFromDictionary:SENTRY_UNWRAP_NULLABLE_DICT( + NSString *, NSString *, event.tags)]; event.tags = newTags; } @@ -541,7 +557,8 @@ - (SentryEvent *__nullable)applyToEvent:(SentryEvent *)event } else { NSMutableDictionary *newExtra = [NSMutableDictionary new]; [newExtra addEntriesFromDictionary:[self extras]]; - [newExtra addEntriesFromDictionary:event.extra]; + [newExtra + addEntriesFromDictionary:SENTRY_UNWRAP_NULLABLE_DICT(NSString *, id, event.extra)]; event.extra = newExtra; } @@ -590,7 +607,7 @@ - (SentryEvent *__nullable)applyToEvent:(SentryEvent *)event // Span could be nil as we do the first check outside the synchronize if (span != nil) { - if (![event.type isEqualToString:SentryEnvelopeItemTypeTransaction] && + if (![event.type isEqualToString:SentryEnvelopeItemTypes.transaction] && [span isKindOfClass:[SentryTracer class]]) { event.transaction = [[(SentryTracer *)span transactionContext] name]; } @@ -599,7 +616,9 @@ - (SentryEvent *__nullable)applyToEvent:(SentryEvent *)event NSMutableDictionary *newContext = [self context].mutableCopy; if (event.context != nil) { - [SentryDictionary mergeEntriesFromDictionary:event.context intoDictionary:newContext]; + [SentryDictionary mergeEntriesFromDictionary:SENTRY_UNWRAP_NULLABLE_DICT( + NSString *, NSDictionary *, event.context) + intoDictionary:newContext]; } newContext[@"trace"] = [self buildTraceContext:span]; @@ -616,12 +635,17 @@ - (void)addObserver:(id)observer - (NSDictionary *)buildTraceContext:(nullable id)span { if (span != nil) { - return [span serialize]; + return [SENTRY_UNWRAP_NULLABLE_VALUE(id, span) serialize]; } else { return [self.propagationContext traceContextForEvent]; } } +- (NSString *)propagationContextTraceIdString +{ + return [self.propagationContext.traceId sentryIdString]; +} + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryScreenshotIntegration.m b/Sources/Sentry/SentryScreenshotIntegration.m index acdaf3ca2fc..f86357e5bf3 100644 --- a/Sources/Sentry/SentryScreenshotIntegration.m +++ b/Sources/Sentry/SentryScreenshotIntegration.m @@ -20,7 +20,9 @@ saveScreenShot(const char *path) { NSString *reportPath = [NSString stringWithUTF8String:path]; - [SentryDependencyContainer.sharedInstance.screenshot saveScreenShots:reportPath]; + SentryScreenshotSource *screenshotSource + = SentryDependencyContainer.sharedInstance.screenshotSource; + [screenshotSource saveScreenShots:reportPath]; } @interface SentryScreenshotIntegration () @@ -39,7 +41,7 @@ - (BOOL)installWithOptions:(nonnull SentryOptions *)options return NO; } - SentryClient *client = [SentrySDK.currentHub getClient]; + SentryClient *client = [SentrySDKInternal.currentHub getClient]; [client addAttachmentProcessor:self]; sentrycrash_setSaveScreenshots(&saveScreenShot); @@ -56,7 +58,7 @@ - (void)uninstall { sentrycrash_setSaveScreenshots(NULL); - SentryClient *client = [SentrySDK.currentHub getClient]; + SentryClient *client = [SentrySDKInternal.currentHub getClient]; [client removeAttachmentProcessor:self]; } @@ -87,12 +89,11 @@ - (void)uninstall return attachments; } - NSArray *screenshot = - [SentryDependencyContainer.sharedInstance.screenshot appScreenshotDatasFromMainThread]; + NSMutableArray *result = [NSMutableArray arrayWithArray:attachments]; - NSMutableArray *result = - [NSMutableArray arrayWithCapacity:attachments.count + screenshot.count]; - [result addObjectsFromArray:attachments]; + SentryScreenshotSource *screenshotSource + = SentryDependencyContainer.sharedInstance.screenshotSource; + NSArray *screenshot = [screenshotSource appScreenshotDatasFromMainThread]; for (int i = 0; i < screenshot.count; i++) { NSString *name diff --git a/Sources/Sentry/SentrySdkInfo.m b/Sources/Sentry/SentrySdkInfo.m deleted file mode 100644 index c29e7005e0d..00000000000 --- a/Sources/Sentry/SentrySdkInfo.m +++ /dev/null @@ -1,130 +0,0 @@ -#import "SentrySdkInfo.h" -#import "SentryClient+Private.h" -#import "SentryHub+Private.h" -#import "SentryMeta.h" -#import "SentryOptions.h" -#import "SentrySDK+Private.h" -#import "SentrySwift.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface SentrySdkInfo () -@end - -@implementation SentrySdkInfo - -+ (instancetype)global -{ - SentryClient *_Nullable client = [SentrySDK.currentHub getClient]; - return [[SentrySdkInfo alloc] initWithOptions:client.options]; -} - -- (instancetype)initWithOptions:(SentryOptions *_Nullable)options -{ - - NSArray *features = - [SentryEnabledFeaturesBuilder getEnabledFeaturesWithOptions:options]; - - NSMutableArray *integrations = - [SentrySDK.currentHub trimmedInstalledIntegrationNames]; - -#if SENTRY_HAS_UIKIT - if (options.enablePreWarmedAppStartTracing) { - [integrations addObject:@"PreWarmedAppStartTracing"]; - } -#endif - - NSMutableSet *> *packages = - [SentryExtraPackages getPackages]; - NSDictionary *sdkPackage = [SentrySdkPackage global]; - if (sdkPackage != nil) { - [packages addObject:sdkPackage]; - } - - return [self initWithName:SentryMeta.sdkName - version:SentryMeta.versionString - integrations:integrations - features:features - packages:[packages allObjects]]; -} - -- (instancetype)initWithName:(NSString *)name - version:(NSString *)version - integrations:(NSArray *)integrations - features:(NSArray *)features - packages:(NSArray *> *)packages -{ - if (self = [super init]) { - _name = name ?: @""; - _version = version ?: @""; - _integrations = integrations ?: @[]; - _features = features ?: @[]; - _packages = packages ?: @[]; - } - - return self; -} - -- (instancetype)initWithDict:(NSDictionary *)dict -{ - NSString *name = @""; - NSString *version = @""; - NSMutableSet *integrations = [[NSMutableSet alloc] init]; - NSMutableSet *features = [[NSMutableSet alloc] init]; - NSMutableSet *> *packages = [[NSMutableSet alloc] init]; - - if ([dict[@"name"] isKindOfClass:[NSString class]]) { - name = dict[@"name"]; - } - - if ([dict[@"version"] isKindOfClass:[NSString class]]) { - version = dict[@"version"]; - } - - if ([dict[@"integrations"] isKindOfClass:[NSArray class]]) { - for (id item in dict[@"integrations"]) { - if ([item isKindOfClass:[NSString class]]) { - [integrations addObject:item]; - } - } - } - - if ([dict[@"features"] isKindOfClass:[NSArray class]]) { - for (id item in dict[@"features"]) { - if ([item isKindOfClass:[NSString class]]) { - [features addObject:item]; - } - } - } - - if ([dict[@"packages"] isKindOfClass:[NSArray class]]) { - for (id item in dict[@"packages"]) { - if ([item isKindOfClass:[NSDictionary class]] && - [item[@"name"] isKindOfClass:[NSString class]] && - [item[@"version"] isKindOfClass:[NSString class]]) { - [packages addObject:@{ @"name" : item[@"name"], @"version" : item[@"version"] }]; - } - } - } - - return [self initWithName:name - version:version - integrations:[integrations allObjects] - features:[features allObjects] - packages:[packages allObjects]]; -} - -- (NSDictionary *)serialize -{ - return @{ - @"name" : self.name, - @"version" : self.version, - @"integrations" : self.integrations, - @"features" : self.features, - @"packages" : self.packages, - }; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentrySerialization.m b/Sources/Sentry/SentrySerialization.m index 6f18578c95c..edbb6516c5a 100644 --- a/Sources/Sentry/SentrySerialization.m +++ b/Sources/Sentry/SentrySerialization.m @@ -1,14 +1,11 @@ #import "SentrySerialization.h" -#import "SentryAppState.h" #import "SentryDateUtils.h" -#import "SentryEnvelope+Private.h" #import "SentryEnvelopeAttachmentHeader.h" -#import "SentryEnvelopeItemType.h" #import "SentryError.h" +#import "SentryInternalDefines.h" #import "SentryLevelMapper.h" #import "SentryLogC.h" -#import "SentrySdkInfo.h" -#import "SentrySession.h" +#import "SentryModels+Serializable.h" #import "SentrySwift.h" #import "SentryTraceContext.h" @@ -61,8 +58,9 @@ + (NSData *_Nullable)dataWithEnvelope:(SentryEnvelope *)envelope } [envelopeData appendData:header]; + NSData *_Nonnull const newLineData = [NSData dataWithBytes:"\n" length:1]; for (int i = 0; i < envelope.items.count; ++i) { - [envelopeData appendData:[@"\n" dataUsingEncoding:NSUTF8StringEncoding]]; + [envelopeData appendData:newLineData]; NSDictionary *serializedItemHeaderData = [envelope.items[i].header serialize]; NSData *itemHeader = [SentrySerialization dataWithJSONObject:serializedItemHeaderData]; @@ -71,7 +69,7 @@ + (NSData *_Nullable)dataWithEnvelope:(SentryEnvelope *)envelope return nil; } [envelopeData appendData:itemHeader]; - [envelopeData appendData:[@"\n" dataUsingEncoding:NSUTF8StringEncoding]]; + [envelopeData appendData:newLineData]; [envelopeData appendData:envelope.items[i].data]; } @@ -110,21 +108,27 @@ + (SentryEnvelope *_Nullable)envelopeWithData:(NSData *)data } SentrySdkInfo *sdkInfo = nil; - if (nil != headerDictionary[@"sdk"]) { - sdkInfo = [[SentrySdkInfo alloc] initWithDict:headerDictionary[@"sdk"]]; + if (nil != headerDictionary[@"sdk"] && + [headerDictionary[@"sdk"] isKindOfClass:[NSDictionary class]]) { + sdkInfo = [[SentrySdkInfo alloc] + initWithDict:SENTRY_UNWRAP_NULLABLE(NSDictionary, headerDictionary[@"sdk"])]; } SentryTraceContext *traceContext = nil; - if (nil != headerDictionary[@"trace"]) { - traceContext = [[SentryTraceContext alloc] initWithDict:headerDictionary[@"trace"]]; + if (nil != headerDictionary[@"trace"] && + [headerDictionary[@"trace"] isKindOfClass:[NSDictionary class]]) { + traceContext = [[SentryTraceContext alloc] + initWithDict:SENTRY_UNWRAP_NULLABLE(NSDictionary, headerDictionary[@"trace"])]; } envelopeHeader = [[SentryEnvelopeHeader alloc] initWithId:eventId sdkInfo:sdkInfo traceContext:traceContext]; - if (headerDictionary[@"sent_at"] != nil) { - envelopeHeader.sentAt = sentry_fromIso8601String(headerDictionary[@"sent_at"]); + if (headerDictionary[@"sent_at"] != nil && + [headerDictionary[@"sent_at"] isKindOfClass:[NSString class]]) { + envelopeHeader.sentAt = sentry_fromIso8601String( + SENTRY_UNWRAP_NULLABLE(NSString, headerDictionary[@"sent_at"])); } break; @@ -165,11 +169,13 @@ + (SentryEnvelope *_Nullable)envelopeWithData:(NSData *)data SENTRY_LOG_ERROR(@"Failed to parse envelope item header %@", error); return nil; } - NSString *_Nullable type = [headerDictionary valueForKey:@"type"]; - if (nil == type) { + NSString *_Nullable nullableType = [headerDictionary valueForKey:@"type"]; + if (nil == nullableType) { SENTRY_LOG_ERROR(@"Envelope item type is required."); break; } + NSString *_Nonnull type = SENTRY_UNWRAP_NULLABLE(NSString, nullableType); + NSNumber *bodyLengthNumber = [headerDictionary valueForKey:@"length"]; NSUInteger bodyLength = [bodyLengthNumber unsignedIntegerValue]; if (endOfEnvelope == i && bodyLength != 0) { @@ -259,16 +265,6 @@ + (SentrySession *_Nullable)sessionWithData:(NSData *)sessionData return session; } -+ (NSData *)dataWithReplayRecording:(SentryReplayRecording *)replayRecording -{ - NSMutableData *recording = [NSMutableData data]; - [recording appendData:[SentrySerialization - dataWithJSONObject:[replayRecording headerForReplayRecording]]]; - [recording appendData:[@"\n" dataUsingEncoding:NSUTF8StringEncoding]]; - [recording appendData:[SentrySerialization dataWithJSONObject:[replayRecording serialize]]]; - return recording; -} - + (SentryAppState *_Nullable)appStateWithData:(NSData *)data { NSError *error = nil; diff --git a/Sources/Sentry/SentrySession.m b/Sources/Sentry/SentrySessionInternal.m similarity index 95% rename from Sources/Sentry/SentrySession.m rename to Sources/Sentry/SentrySessionInternal.m index 16bde7f54de..47a5a76f062 100644 --- a/Sources/Sentry/SentrySession.m +++ b/Sources/Sentry/SentrySessionInternal.m @@ -1,8 +1,8 @@ +#import "SentrySessionInternal.h" #import "NSMutableDictionary+Sentry.h" #import "SentryDateUtils.h" #import "SentryDependencyContainer.h" #import "SentryLogC.h" -#import "SentrySession+Private.h" #import "SentrySwift.h" NS_ASSUME_NONNULL_BEGIN @@ -11,19 +11,19 @@ nameForSentrySessionStatus(SentrySessionStatus status) { switch (status) { - case kSentrySessionStatusOk: + case SentrySessionStatusOk: return @"ok"; - case kSentrySessionStatusExited: + case SentrySessionStatusExited: return @"exited"; - case kSentrySessionStatusCrashed: + case SentrySessionStatusCrashed: return @"crashed"; break; - case kSentrySessionStatusAbnormal: + case SentrySessionStatusAbnormal: return @"abnormal"; } } -@implementation SentrySession +@implementation SentrySessionInternal @synthesize flagInit = _init; @@ -251,9 +251,9 @@ - (void)incrementErrors } } -- (id)copyWithZone:(nullable NSZone *)zone +- (SentrySessionInternal *)safeCopyWithZone:(nullable NSZone *)zone { - SentrySession *copy = [[[self class] allocWithZone:zone] init]; + SentrySessionInternal *copy = [[[self class] allocWithZone:zone] init]; if (copy != nil) { copy->_sessionId = _sessionId; diff --git a/Sources/Sentry/SentrySessionReplayIntegration.m b/Sources/Sentry/SentrySessionReplayIntegration.m index ab8de864c40..aa6d8bb7a04 100644 --- a/Sources/Sentry/SentrySessionReplayIntegration.m +++ b/Sources/Sentry/SentrySessionReplayIntegration.m @@ -3,8 +3,8 @@ #if SENTRY_TARGET_REPLAY_SUPPORTED # import "SentryClient+Private.h" -# import "SentryCrashWrapper.h" # import "SentryDependencyContainer.h" +# import "SentryDispatchFactory.h" # import "SentryDispatchQueueProviderProtocol.h" # import "SentryDisplayLinkWrapper.h" # import "SentryEvent+Private.h" @@ -12,9 +12,7 @@ # import "SentryGlobalEventProcessor.h" # import "SentryHub+Private.h" # import "SentryLogC.h" -# import "SentryNSNotificationCenterWrapper.h" # import "SentryOptions.h" -# import "SentryRandom.h" # import "SentryRateLimits.h" # import "SentryReachability.h" # import "SentrySDK+Private.h" @@ -23,7 +21,6 @@ # import "SentrySessionReplaySyncC.h" # import "SentrySwift.h" # import "SentrySwizzle.h" -# import "SentryUIApplication.h" # import NS_ASSUME_NONNULL_BEGIN @@ -56,7 +53,7 @@ - (void)newSceneActivate; @implementation SentrySessionReplayIntegration { BOOL _startedAsFullSession; SentryReplayOptions *_replayOptions; - SentryNSNotificationCenterWrapper *_notificationCenter; + id _notificationCenter; id _rateLimits; id _currentScreenshotProvider; id _currentBreadcrumbConverter; @@ -140,7 +137,7 @@ - (void)setupWith:(SentryReplayOptions *)replayOptions // We use the dispatch queue provider as a factory to create the queues, but store the queues // directly in this instance, so they get deallocated when the integration is deallocated. id dispatchQueueProvider - = SentryDependencyContainer.sharedInstance.dispatchQueueProvider; + = SentryDependencyContainer.sharedInstance.dispatchFactory; // The asset worker queue is used to work on video and frames data. // Use a relative priority of -1 to make it lower than the default background priority. @@ -159,13 +156,20 @@ - (void)setupWith:(SentryReplayOptions *)replayOptions [self moveCurrentReplay]; [self cleanUp]; - [SentrySDK.currentHub registerSessionListener:self]; + [SentrySDKInternal.currentHub registerSessionListener:self]; + + __weak SentrySessionReplayIntegration *weakSelf = self; [SentryDependencyContainer.sharedInstance.globalEventProcessor addEventProcessor:^SentryEvent *_Nullable(SentryEvent *_Nonnull event) { + if (weakSelf == nil) { + SENTRY_LOG_DEBUG(@"WeakSelf is nil. Not doing anything."); + return event; + } + if (event.isFatalEvent) { - [self resumePreviousSessionReplay:event]; + [weakSelf resumePreviousSessionReplay:event]; } else { - [self.sessionReplay captureReplayForEvent:event]; + [weakSelf.sessionReplay captureReplayForEvent:event]; } return event; }]; @@ -296,9 +300,9 @@ - (void)captureVideo:(SentryVideoInfo *)video video:video extraEvents:@[]]; - [SentrySDK.currentHub captureReplayEvent:replayEvent - replayRecording:recording - video:video.path]; + [SentrySDKInternal.currentHub captureReplayEvent:replayEvent + replayRecording:recording + video:video.path]; NSError *error = nil; if (![[NSFileManager defaultManager] removeItemAtURL:video.path error:&error]) { @@ -325,7 +329,7 @@ - (void)startSession - (void)runReplayForAvailableWindow { - if (SentryDependencyContainer.sharedInstance.application.windows.count > 0) { + if ([SentryDependencyContainer.sharedInstance.application getWindows].count > 0) { SENTRY_LOG_DEBUG(@"[Session Replay] Running replay for available window"); // If a window its already available start replay right away [self startWithOptions:_replayOptions fullSession:_startedAsFullSession]; @@ -335,7 +339,8 @@ - (void)runReplayForAvailableWindow // Wait for a scene to be available to started the replay [_notificationCenter addObserver:self selector:@selector(newSceneActivate) - name:UISceneDidActivateNotification]; + name:UISceneDidActivateNotification + object:nil]; } } @@ -345,7 +350,8 @@ - (void)newSceneActivate SENTRY_LOG_DEBUG(@"[Session Replay] Scene is available, starting replay"); [SentryDependencyContainer.sharedInstance.notificationCenterWrapper removeObserver:self - name:UISceneDidActivateNotification]; + name:UISceneDidActivateNotification + object:nil]; [self startWithOptions:_replayOptions fullSession:_startedAsFullSession]; } } @@ -406,7 +412,8 @@ - (void)startWithOptions:(SentryReplayOptions *)replayOptions displayLinkWrapper:displayLinkWrapper]; [self.sessionReplay - startWithRootView:SentryDependencyContainer.sharedInstance.application.windows.firstObject + startWithRootView:[SentryDependencyContainer.sharedInstance.application getWindows] + .firstObject fullSession:shouldReplayFullSession]; [_notificationCenter addObserver:self @@ -626,7 +633,7 @@ - (SentryIntegrationOption)integrationOptions - (void)uninstall { SENTRY_LOG_DEBUG(@"[Session Replay] Uninstalling"); - [SentrySDK.currentHub unregisterSessionListener:self]; + [SentrySDKInternal.currentHub unregisterSessionListener:self]; _touchTracker = nil; [self pause]; } @@ -705,7 +712,7 @@ - (SentryTouchTracker *)getTouchTracker - (BOOL)sessionReplayShouldCaptureReplayForError { - return SentryDependencyContainer.sharedInstance.random.nextNumber + return [SentryDependencyContainer.sharedInstance.random nextNumber] <= _replayOptions.onErrorSampleRate; } @@ -724,9 +731,9 @@ - (void)sessionReplayNewSegmentWithReplayEvent:(SentryReplayEvent *)replayEvent return; } - [SentrySDK.currentHub captureReplayEvent:replayEvent - replayRecording:replayRecording - video:videoUrl]; + [SentrySDKInternal.currentHub captureReplayEvent:replayEvent + replayRecording:replayRecording + video:videoUrl]; sentrySessionReplaySync_updateInfo( (unsigned int)replayEvent.segmentId, replayEvent.timestamp.timeIntervalSinceReferenceDate); @@ -735,21 +742,21 @@ - (void)sessionReplayNewSegmentWithReplayEvent:(SentryReplayEvent *)replayEvent - (void)sessionReplayStartedWithReplayId:(SentryId *)replayId { SENTRY_LOG_DEBUG(@"[Session Replay] Session replay started with replay id: %@", replayId); - [SentrySDK.currentHub configureScope:^( + [SentrySDKInternal.currentHub configureScope:^( SentryScope *_Nonnull scope) { scope.replayId = [replayId sentryIdString]; }]; } - (NSArray *)breadcrumbsForSessionReplay { __block NSArray *result; - [SentrySDK.currentHub + [SentrySDKInternal.currentHub configureScope:^(SentryScope *_Nonnull scope) { result = scope.breadcrumbs; }]; return result; } - (nullable NSString *)currentScreenNameForSessionReplay { - return SentrySDK.currentHub.scope.currentScreen + return SentrySDKInternal.currentHub.scope.currentScreen ?: [SentryDependencyContainer.sharedInstance.application relevantViewControllersNames] .firstObject; } @@ -762,7 +769,8 @@ - (void)showMaskPreview:(CGFloat)opacity return; } - UIWindow *window = SentryDependencyContainer.sharedInstance.application.windows.firstObject; + UIWindow *window = + [SentryDependencyContainer.sharedInstance.application getWindows].firstObject; if (window == nil) { SENTRY_LOG_WARN(@"[Session Replay] No UIWindow available to display preview"); return; diff --git a/Sources/Sentry/SentrySessionTracker.m b/Sources/Sentry/SentrySessionTracker.m index 6d9865f0bf3..c49155285e8 100644 --- a/Sources/Sentry/SentrySessionTracker.m +++ b/Sources/Sentry/SentrySessionTracker.m @@ -1,12 +1,11 @@ #import "SentrySessionTracker.h" -#import "SentryApplication.h" #import "SentryClient+Private.h" #import "SentryClient.h" #import "SentryFileManager.h" #import "SentryHub+Private.h" #import "SentryInternalNotificationNames.h" #import "SentryLogC.h" -#import "SentryNSNotificationCenterWrapper.h" +#import "SentryNotificationNames.h" #import "SentryOptions+Private.h" #import "SentrySDK+Private.h" #import "SentrySwift.h" @@ -29,7 +28,7 @@ @interface SentrySessionTracker () @property (nonatomic, strong) id application; @property (nonatomic, strong) id dateProvider; -@property (nonatomic, strong) SentryNSNotificationCenterWrapper *notificationCenter; +@property (nonatomic, strong) id notificationCenter; @end @@ -38,7 +37,7 @@ @implementation SentrySessionTracker - (instancetype)initWithOptions:(SentryOptions *)options application:(id)application dateProvider:(id)dateProvider - notificationCenter:(SentryNSNotificationCenterWrapper *)notificationCenter + notificationCenter:(id)notificationCenter { if (self = [super init]) { self.options = options; @@ -74,23 +73,27 @@ - (void)start [self.notificationCenter addObserver:self selector:@selector(didBecomeActive) - name:SentryDidBecomeActiveNotification]; + name:SentryDidBecomeActiveNotification + object:nil]; [self.notificationCenter addObserver:self selector:@selector(didBecomeActive) - name:SentryHybridSdkDidBecomeActiveNotificationName]; + name:SentryHybridSdkDidBecomeActiveNotificationName + object:nil]; [self.notificationCenter addObserver:self selector:@selector(willResignActive) - name:SentryWillResignActiveNotification]; + name:SentryWillResignActiveNotification + object:nil]; [self.notificationCenter addObserver:self selector:@selector(willTerminate) - name:SentryWillTerminateNotification]; + name:SentryWillTerminateNotification + object:nil]; // Edge case: When starting the SDK after the app did become active, we need to call // didBecomeActive manually to start the session. This is the case when // closing the SDK and starting it again. - if (self.application.isActive) { + if (self.application.mainThread_isActive) { [self startSession]; } #else @@ -100,7 +103,7 @@ - (void)start - (void)stop { - [[SentrySDK currentHub] endSession]; + [[SentrySDKInternal currentHub] endSession]; [self removeObservers]; @@ -114,11 +117,14 @@ - (void)removeObservers #if SENTRY_HAS_UIKIT || SENTRY_TARGET_MACOS_HAS_UI // Remove the observers with the most specific detail possible, see // https://developer.apple.com/documentation/foundation/nsnotificationcenter/1413994-removeobserver - [self.notificationCenter removeObserver:self name:SentryDidBecomeActiveNotification]; + [self.notificationCenter removeObserver:self name:SentryDidBecomeActiveNotification object:nil]; [self.notificationCenter removeObserver:self - name:SentryHybridSdkDidBecomeActiveNotificationName]; - [self.notificationCenter removeObserver:self name:SentryWillResignActiveNotification]; - [self.notificationCenter removeObserver:self name:SentryWillTerminateNotification]; + name:SentryHybridSdkDidBecomeActiveNotificationName + object:nil]; + [self.notificationCenter removeObserver:self + name:SentryWillResignActiveNotification + object:nil]; + [self.notificationCenter removeObserver:self name:SentryWillTerminateNotification object:nil]; #endif } @@ -128,7 +134,7 @@ - (void)dealloc // In dealloc it's safe to unsubscribe for all, see // https://developer.apple.com/documentation/foundation/nsnotificationcenter/1413994-removeobserver - [self.notificationCenter removeObserver:self]; + [self.notificationCenter removeObserver:self name:nil object:nil]; } /** @@ -138,7 +144,7 @@ - (void)dealloc */ - (void)endCachedSession { - SentryHub *hub = [SentrySDK currentHub]; + SentryHub *hub = [SentrySDKInternal currentHub]; NSDate *_Nullable lastInForeground = [[[hub getClient] fileManager] readTimestampLastInForeground]; if (nil != lastInForeground) { @@ -177,7 +183,7 @@ - (void)startSession self.wasStartSessionCalled = YES; } - SentryHub *hub = [SentrySDK currentHub]; + SentryHub *hub = [SentrySDKInternal currentHub]; self.lastInForeground = [[[hub getClient] fileManager] readTimestampLastInForeground]; if (nil == self.lastInForeground) { @@ -208,7 +214,7 @@ - (void)startSession #if SENTRY_TARGET_PROFILING_SUPPORTED if (hub.client.options.profiling != nil) { - sentry_reevaluateSessionSampleRate(hub.client.options.profiling.sessionSampleRate); + sentry_reevaluateSessionSampleRate(); } #endif // SENTRY_TARGET_PROFILING_SUPPORTED } @@ -222,7 +228,7 @@ - (void)startSession - (void)willResignActive { self.lastInForeground = [self.dateProvider date]; - SentryHub *hub = [SentrySDK currentHub]; + SentryHub *hub = [SentrySDKInternal currentHub]; [[[hub getClient] fileManager] storeTimestampLastInForeground:self.lastInForeground]; self.wasStartSessionCalled = NO; } @@ -234,7 +240,7 @@ - (void)willTerminate { NSDate *sessionEnded = nil == self.lastInForeground ? [self.dateProvider date] : self.lastInForeground; - SentryHub *hub = [SentrySDK currentHub]; + SentryHub *hub = [SentrySDKInternal currentHub]; [hub endSessionWithTimestamp:sessionEnded]; [[[hub getClient] fileManager] deleteTimestampLastInForeground]; self.wasStartSessionCalled = NO; diff --git a/Sources/Sentry/SentrySpan.m b/Sources/Sentry/SentrySpan.m index fd183e9ed0f..ae4300b8bcf 100644 --- a/Sources/Sentry/SentrySpan.m +++ b/Sources/Sentry/SentrySpan.m @@ -4,7 +4,7 @@ #import "SentryFrame.h" #import "SentryInternalDefines.h" #import "SentryLogC.h" -#import "SentryMeasurementValue.h" +#import "SentryModels+Serializable.h" #import "SentryNSDictionarySanitize.h" #import "SentryNoOpSpan.h" #import "SentrySampleDecision+Private.h" @@ -25,7 +25,6 @@ #if SENTRY_TARGET_PROFILING_SUPPORTED # import "SentryContinuousProfiler.h" -# import "SentryNSNotificationCenterWrapper.h" # import "SentryOptions+Private.h" # import "SentryProfilingConditionals.h" # import "SentrySDK+Private.h" @@ -49,9 +48,9 @@ @implementation SentrySpan { SentryFramesTracker *_framesTracker; #endif // SENTRY_HAS_UIKIT -#if SENTRY_TARGET_PROFILING_SUPPORTED +#if SENTRY_TARGET_PROFILING_SUPPORTED && !SDK_V9 BOOL _isContinuousProfiling; -#endif // SENTRY_TARGET_PROFILING_SUPPORTED +#endif // SENTRY_TARGET_PROFILING_SUPPORTED && !SDK_V9 } - (instancetype)initWithContext:(SentrySpanContext *)context @@ -98,16 +97,21 @@ - (instancetype)initWithContext:(SentrySpanContext *)context _origin = context.origin; #if SENTRY_TARGET_PROFILING_SUPPORTED - _isContinuousProfiling = [SentrySDK.options isContinuousProfilingEnabled]; +# if !SDK_V9 + _isContinuousProfiling = [SentrySDKInternal.options isContinuousProfilingEnabled]; if (_isContinuousProfiling) { +# endif // !SDK_V9 _profileSessionID = SentryContinuousProfiler.currentProfilerID.sentryIdString; if (_profileSessionID == nil) { [SentryDependencyContainer.sharedInstance.notificationCenterWrapper addObserver:self selector:@selector(linkProfiler) - name:kSentryNotificationContinuousProfileStarted]; + name:kSentryNotificationContinuousProfileStarted + object:nil]; } +# if !SDK_V9 } +# endif // !SDK_V9 #endif // SENTRY_TARGET_PROFILING_SUPPORTED } @@ -134,11 +138,16 @@ - (void)linkProfiler - (void)stopObservingContinuousProfiling { +# if !SDK_V9 if (_isContinuousProfiling) { +# endif // !SDK_V9 [SentryDependencyContainer.sharedInstance.notificationCenterWrapper removeObserver:self - name:kSentryNotificationContinuousProfileStarted]; + name:kSentryNotificationContinuousProfileStarted + object:nil]; +# if !SDK_V9 } +# endif // !SDK_V9 } #endif // SENTRY_TARGET_PROFILING_SUPPORTED @@ -191,10 +200,12 @@ - (void)setDataValue:(nullable id)value forKey:(NSString *)key } } +#if !SDK_V9 - (void)setExtraValue:(nullable id)value forKey:(NSString *)key { [self setDataValue:value forKey:key]; } +#endif // !SDK_V9 - (void)removeDataForKey:(NSString *)key { diff --git a/Sources/Sentry/SentrySpotlightTransport.m b/Sources/Sentry/SentrySpotlightTransport.m index 585ae0d6215..82c83bf6219 100644 --- a/Sources/Sentry/SentrySpotlightTransport.m +++ b/Sources/Sentry/SentrySpotlightTransport.m @@ -1,11 +1,11 @@ #import "SentrySpotlightTransport.h" -#import "SentryEnvelope.h" #import "SentryEnvelopeItemHeader.h" -#import "SentryEnvelopeItemType.h" +#import "SentryInternalDefines.h" #import "SentryLogC.h" #import "SentryNSURLRequestBuilder.h" #import "SentryOptions.h" #import "SentrySerialization.h" +#import "SentrySwift.h" #import "SentryTransport.h" NS_ASSUME_NONNULL_BEGIN @@ -52,10 +52,10 @@ - (void)sendEnvelope:(SentryEnvelope *)envelope // Not removing them leads to an error and events won't get displayed. NSMutableArray *allowedEnvelopeItems = [NSMutableArray new]; for (SentryEnvelopeItem *item in envelope.items) { - if ([item.header.type isEqualToString:SentryEnvelopeItemTypeEvent]) { + if ([item.header.type isEqualToString:SentryEnvelopeItemTypes.event]) { [allowedEnvelopeItems addObject:item]; } - if ([item.header.type isEqualToString:SentryEnvelopeItemTypeTransaction]) { + if ([item.header.type isEqualToString:SentryEnvelopeItemTypes.transaction]) { [allowedEnvelopeItems addObject:item]; } } @@ -64,9 +64,10 @@ - (void)sendEnvelope:(SentryEnvelope *)envelope items:allowedEnvelopeItems]; NSError *requestError = nil; - NSURLRequest *request = [self.requestBuilder createEnvelopeRequest:envelopeToSend - url:self.apiURL - didFailWithError:&requestError]; + NSURLRequest *request = + [self.requestBuilder createEnvelopeRequest:envelopeToSend + url:SENTRY_UNWRAP_NULLABLE(NSURL, self.apiURL) + didFailWithError:&requestError]; if (nil == request || nil != requestError) { if (nil != requestError) { diff --git a/Sources/Sentry/SentryStacktrace.m b/Sources/Sentry/SentryStacktrace.m index 6892a363138..1cd44e03ec5 100644 --- a/Sources/Sentry/SentryStacktrace.m +++ b/Sources/Sentry/SentryStacktrace.m @@ -2,6 +2,7 @@ #import "NSMutableDictionary+Sentry.h" #import "SentryFrame.h" #import "SentryLogC.h" +#import "SentryModels+Serializable.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Sources/Sentry/SentrySubClassFinder.m b/Sources/Sentry/SentrySubClassFinder.m index 9084e737269..f2734641d33 100644 --- a/Sources/Sentry/SentrySubClassFinder.m +++ b/Sources/Sentry/SentrySubClassFinder.m @@ -1,6 +1,6 @@ #import "SentrySubClassFinder.h" +#import "SentryInternalDefines.h" #import "SentryLogC.h" -#import "SentryObjCRuntimeWrapper.h" #import "SentrySwift.h" #import #import @@ -43,9 +43,14 @@ - (void)actOnSubclassesOfViewControllerInImage:(NSString *)imageName block:(void return; } + const char *_Nullable cImageName = [imageName cStringUsingEncoding:NSUTF8StringEncoding]; + if (cImageName == nil) { + return; + } + unsigned int count = 0; const char **classes = [self.objcRuntimeWrapper - copyClassNamesForImage:[imageName cStringUsingEncoding:NSUTF8StringEncoding] + copyClassNamesForImage:SENTRY_UNWRAP_NULLABLE(const char, cImageName) amount:&count]; SENTRY_LOG_DEBUG(@"Found %u number of classes in image: %@.", count, imageName); diff --git a/Sources/Sentry/SentrySystemEventBreadcrumbs.m b/Sources/Sentry/SentrySystemEventBreadcrumbs.m index 524469b231d..6414fb7f615 100644 --- a/Sources/Sentry/SentrySystemEventBreadcrumbs.m +++ b/Sources/Sentry/SentrySystemEventBreadcrumbs.m @@ -4,7 +4,6 @@ #import "SentryDefines.h" #import "SentryDependencyContainer.h" #import "SentryLogC.h" -#import "SentryNSNotificationCenterWrapper.h" #import "SentrySwift.h" #if TARGET_OS_IOS && SENTRY_HAS_UIKIT @@ -14,13 +13,13 @@ @interface SentrySystemEventBreadcrumbs () @property (nonatomic, weak) id delegate; @property (nonatomic, strong) SentryFileManager *fileManager; -@property (nonatomic, strong) SentryNSNotificationCenterWrapper *notificationCenterWrapper; +@property (nonatomic, strong) id notificationCenterWrapper; @end @implementation SentrySystemEventBreadcrumbs - (instancetype)initWithFileManager:(SentryFileManager *)fileManager - andNotificationCenterWrapper:(SentryNSNotificationCenterWrapper *)notificationCenterWrapper + andNotificationCenterWrapper:(id)notificationCenterWrapper { if (self = [super init]) { _fileManager = fileManager; @@ -39,25 +38,34 @@ - (void)stop { // Remove the observers with the most specific detail possible, see // https://developer.apple.com/documentation/foundation/nsnotificationcenter/1413994-removeobserver - [self.notificationCenterWrapper removeObserver:self name:UIKeyboardDidShowNotification]; - [self.notificationCenterWrapper removeObserver:self name:UIKeyboardDidHideNotification]; [self.notificationCenterWrapper removeObserver:self - name:UIApplicationUserDidTakeScreenshotNotification]; + name:UIKeyboardDidShowNotification + object:nil]; [self.notificationCenterWrapper removeObserver:self - name:UIDeviceBatteryLevelDidChangeNotification]; + name:UIKeyboardDidHideNotification + object:nil]; [self.notificationCenterWrapper removeObserver:self - name:UIDeviceBatteryStateDidChangeNotification]; + name:UIApplicationUserDidTakeScreenshotNotification + object:nil]; [self.notificationCenterWrapper removeObserver:self - name:UIDeviceOrientationDidChangeNotification]; + name:UIDeviceBatteryLevelDidChangeNotification + object:nil]; [self.notificationCenterWrapper removeObserver:self - name:UIDeviceOrientationDidChangeNotification]; + name:UIDeviceBatteryStateDidChangeNotification + object:nil]; + [self.notificationCenterWrapper removeObserver:self + name:UIDeviceOrientationDidChangeNotification + object:nil]; + [self.notificationCenterWrapper removeObserver:self + name:UIApplicationSignificantTimeChangeNotification + object:nil]; } - (void)dealloc { // In dealloc it's safe to unsubscribe for all, see // https://developer.apple.com/documentation/foundation/nsnotificationcenter/1413994-removeobserver - [self.notificationCenterWrapper removeObserver:self]; + [self.notificationCenterWrapper removeObserver:self name:nil object:nil]; } /** @@ -77,6 +85,7 @@ - (void)startWithDelegate:(id)delegate [self initKeyboardVisibilityObserver]; [self initScreenshotObserver]; [self initTimezoneObserver]; + [self initSignificantTimeChangeObserver]; } - (void)initBatteryObserver:(UIDevice *)currentDevice @@ -188,12 +197,14 @@ - (void)initKeyboardVisibilityObserver // Posted immediately after the display of the keyboard. [self.notificationCenterWrapper addObserver:self selector:@selector(systemEventTriggered:) - name:UIKeyboardDidShowNotification]; + name:UIKeyboardDidShowNotification + object:nil]; // Posted immediately after the dismissal of the keyboard. [self.notificationCenterWrapper addObserver:self selector:@selector(systemEventTriggered:) - name:UIKeyboardDidHideNotification]; + name:UIKeyboardDidHideNotification + object:nil]; } - (void)systemEventTriggered:(NSNotification *)notification @@ -210,7 +221,8 @@ - (void)initScreenshotObserver // it's only about the action, but not the SS itself [self.notificationCenterWrapper addObserver:self selector:@selector(systemEventTriggered:) - name:UIApplicationUserDidTakeScreenshotNotification]; + name:UIApplicationUserDidTakeScreenshotNotification + object:nil]; } - (void)initTimezoneObserver @@ -229,7 +241,8 @@ - (void)initTimezoneObserver // Posted when the timezone of the device changed [self.notificationCenterWrapper addObserver:self selector:@selector(timezoneEventTriggered) - name:NSSystemTimeZoneDidChangeNotification]; + name:NSSystemTimeZoneDidChangeNotification + object:nil]; } - (void)timezoneEventTriggered @@ -269,6 +282,35 @@ - (void)updateStoredTimezone storeTimezoneOffset:SentryDependencyContainer.sharedInstance.dateProvider.timezoneOffset]; } +- (void)initSignificantTimeChangeObserver +{ + + [self.notificationCenterWrapper addObserver:self + selector:@selector(significantTimeChangeTriggered:) + name:UIApplicationSignificantTimeChangeNotification + object:nil]; +} + +/** + * The system posts this notification when, for example, there’s a change to a new day (midnight), a + * carrier time update, or a change to, or from, daylight savings time. The notification doesn’t + * contain a user info dictionary. + * + * @see + * https://developer.apple.com/documentation/uikit/uiapplication/significanttimechangenotification#Discussion + */ +- (void)significantTimeChangeTriggered:(NSNotification *)notification +{ + SentryBreadcrumb *crumb = [[SentryBreadcrumb alloc] initWithLevel:kSentryLevelInfo + category:@"device.event"]; + crumb.type = @"system"; + + // We don't add the timezone here, because we already add it in timezoneEventTriggered. + crumb.data = @{ @"action" : @"SIGNIFICANT_TIME_CHANGE" }; + + [_delegate addBreadcrumb:crumb]; +} + @end #endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT diff --git a/Sources/Sentry/SentrySystemWrapper.mm b/Sources/Sentry/SentrySystemWrapper.mm index 08b64c925cc..5dfc9f6d7dc 100644 --- a/Sources/Sentry/SentrySystemWrapper.mm +++ b/Sources/Sentry/SentrySystemWrapper.mm @@ -1,19 +1,20 @@ #import "SentrySystemWrapper.h" -#import "SentryDependencyContainer.h" -#import "SentryError.h" -#import "SentryNSProcessInfoWrapper.h" -#import -#include + +#if SENTRY_TARGET_PROFILING_SUPPORTED + +# import "SentryDependencyContainer.h" +# import "SentryError.h" +# import +# include @implementation SentrySystemWrapper { float processorCount; } -- (instancetype)init +- (instancetype)initWithProcessorCount:(long)count { if ((self = [super init])) { - processorCount - = (float)SentryDependencyContainer.sharedInstance.processInfoWrapper.processorCount; + processorCount = count; } return self; } @@ -84,6 +85,8 @@ - (NSNumber *)cpuUsageWithError:(NSError **)error return @(usage); } +// Only these architectures support `task_energy` +# if defined(__arm__) || defined(__arm64__) - (NSNumber *)cpuEnergyUsageWithError:(NSError **)error { struct task_power_info_v2 powerInfo; @@ -99,7 +102,10 @@ - (NSNumber *)cpuEnergyUsageWithError:(NSError **)error ; } } - return @(powerInfo.cpu_energy.total_system + powerInfo.cpu_energy.total_user); + return @(powerInfo.task_energy); } +# endif @end + +#endif // SENTRY_TARGET_PROFILING_SUPPORTED diff --git a/Sources/Sentry/SentryThread.mm b/Sources/Sentry/SentryThread.mm index e7254f301fa..f8a35a7f4c4 100644 --- a/Sources/Sentry/SentryThread.mm +++ b/Sources/Sentry/SentryThread.mm @@ -1,5 +1,6 @@ #import "SentryThread.h" #import "NSMutableDictionary+Sentry.h" +#import "SentryModels+Serializable.h" #include "SentryProfilingConditionals.h" #import "SentryStacktrace.h" diff --git a/Sources/Sentry/SentryThreadInspector.m b/Sources/Sentry/SentryThreadInspector.m index f92045f3359..8f85e8d5252 100644 --- a/Sources/Sentry/SentryThreadInspector.m +++ b/Sources/Sentry/SentryThreadInspector.m @@ -5,10 +5,10 @@ #import "SentryCrashStackEntryMapper.h" #include "SentryCrashSymbolicator.h" #import "SentryFrame.h" -#import "SentryInAppLogic.h" #import "SentryOptions.h" #import "SentryStacktrace.h" #import "SentryStacktraceBuilder.h" +#import "SentrySwift.h" #import "SentryThread.h" #include @@ -28,9 +28,11 @@ @interface SentryThreadInspector () // We need a C function to retrieve information from the stack trace in order to avoid // calling into not async-signal-safe code while there are suspended threads. +// If asyncUnsafeSymbolicate is `true` the stack will be symbolicated but the function is no longer +// async-signal-safe. unsigned int getStackEntriesFromThread(SentryCrashThread thread, struct SentryCrashMachineContext *context, - SentryCrashStackEntry *buffer, unsigned int maxEntries, bool symbolicate) + SentryCrashStackEntry *buffer, unsigned int maxEntries, bool asyncUnsafeSymbolicate) { sentrycrashmc_getContextForThread(thread, context, NO); SentryCrashStackCursor stackCursor; @@ -41,7 +43,7 @@ @interface SentryThreadInspector () while (stackCursor.advanceCursor(&stackCursor)) { if (entries == maxEntries) break; - if (symbolicate == false || stackCursor.symbolicate(&stackCursor)) { + if (asyncUnsafeSymbolicate == false || stackCursor.symbolicate(&stackCursor)) { buffer[entries] = stackCursor.stackEntry; entries++; } diff --git a/Sources/Sentry/SentryTimeToDisplayTracker.m b/Sources/Sentry/SentryTimeToDisplayTracker.m index 2047a4326c3..7df8db59f04 100644 --- a/Sources/Sentry/SentryTimeToDisplayTracker.m +++ b/Sources/Sentry/SentryTimeToDisplayTracker.m @@ -5,7 +5,6 @@ # import "SentryDependencyContainer.h" # import "SentryFramesTracker.h" # import "SentryLogC.h" -# import "SentryMeasurementValue.h" # import "SentryOptions+Private.h" # import "SentryProfilingConditionals.h" # import "SentrySDK+Private.h" @@ -21,6 +20,7 @@ # if SENTRY_TARGET_PROFILING_SUPPORTED # import "SentryLaunchProfiling.h" +# import "SentryProfiler+Private.h" # endif // SENTRY_TARGET_PROFILING_SUPPORTED @interface SentryTimeToDisplayTracker () @@ -61,16 +61,16 @@ - (BOOL)startForTracer:(SentryTracer *)tracer } SENTRY_LOG_DEBUG(@"Starting initial display span"); - self.initialDisplaySpan = - [tracer startChildWithOperation:SentrySpanOperationUiLoadInitialDisplay - description:[NSString stringWithFormat:@"%@ initial display", _name]]; + self.initialDisplaySpan = (SentrySpan *)[tracer + startChildWithOperation:SentrySpanOperationUiLoadInitialDisplay + description:[NSString stringWithFormat:@"%@ initial display", _name]]; self.initialDisplaySpan.origin = SentryTraceOriginAutoUITimeToDisplay; if (self.waitForFullDisplay) { SENTRY_LOG_DEBUG(@"Starting full display span"); - self.fullDisplaySpan = - [tracer startChildWithOperation:SentrySpanOperationUiLoadFullDisplay - description:[NSString stringWithFormat:@"%@ full display", _name]]; + self.fullDisplaySpan = (SentrySpan *)[tracer + startChildWithOperation:SentrySpanOperationUiLoadFullDisplay + description:[NSString stringWithFormat:@"%@ full display", _name]]; self.fullDisplaySpan.origin = SentryTraceOriginManualUITimeToDisplay; // By concept TTID and TTFD spans should have the same beginning, @@ -175,8 +175,8 @@ - (void)framesTrackerHasNewFrame:(NSDate *)newFrameDate if (!_waitForFullDisplay) { [SentryDependencyContainer.sharedInstance.framesTracker removeListener:self]; # if SENTRY_TARGET_PROFILING_SUPPORTED - if ([SentrySDK.options isProfilingCorrelatedToTraces]) { - sentry_stopAndDiscardLaunchProfileTracer(); + if (sentry_isLaunchProfileCorrelatedToTraces()) { + sentry_stopAndDiscardLaunchProfileTracer(SentrySDKInternal.currentHub); } # endif // SENTRY_TARGET_PROFILING_SUPPORTED } @@ -187,8 +187,8 @@ - (void)framesTrackerHasNewFrame:(NSDate *)newFrameDate self.fullDisplaySpan.timestamp = newFrameDate; [self.fullDisplaySpan finish]; # if SENTRY_TARGET_PROFILING_SUPPORTED - if ([SentrySDK.options isProfilingCorrelatedToTraces]) { - sentry_stopAndDiscardLaunchProfileTracer(); + if (sentry_isLaunchProfileCorrelatedToTraces()) { + sentry_stopAndDiscardLaunchProfileTracer(SentrySDKInternal.currentHub); } # endif // SENTRY_TARGET_PROFILING_SUPPORTED } diff --git a/Sources/Sentry/SentryTraceContext.m b/Sources/Sentry/SentryTraceContext.m index 98610eb5b91..a007c48bfbd 100644 --- a/Sources/Sentry/SentryTraceContext.m +++ b/Sources/Sentry/SentryTraceContext.m @@ -2,10 +2,12 @@ #import "SentryBaggage.h" #import "SentryDefines.h" #import "SentryDsn.h" +#import "SentryInternalDefines.h" #import "SentryLogC.h" #import "SentryOptions+Private.h" #import "SentrySampleDecision.h" #import "SentryScope+Private.h" +#import "SentryScope+PrivateSwift.h" #import "SentrySerialization.h" #import "SentrySwift.h" #import "SentryTracer.h" @@ -21,7 +23,9 @@ - (instancetype)initWithTraceId:(SentryId *)traceId releaseName:(nullable NSString *)releaseName environment:(nullable NSString *)environment transaction:(nullable NSString *)transaction +#if !SDK_V9 userSegment:(nullable NSString *)userSegment +#endif sampleRate:(nullable NSString *)sampleRate sampled:(nullable NSString *)sampled replayId:(nullable NSString *)replayId @@ -31,7 +35,9 @@ - (instancetype)initWithTraceId:(SentryId *)traceId releaseName:releaseName environment:environment transaction:transaction +#if !SDK_V9 userSegment:userSegment +#endif sampleRate:sampleRate sampleRand:nil sampled:sampled @@ -43,7 +49,9 @@ - (instancetype)initWithTraceId:(SentryId *)traceId releaseName:(nullable NSString *)releaseName environment:(nullable NSString *)environment transaction:(nullable NSString *)transaction +#if !SDK_V9 userSegment:(nullable NSString *)userSegment +#endif sampleRate:(nullable NSString *)sampleRate sampleRand:(nullable NSString *)sampleRand sampled:(nullable NSString *)sampled @@ -55,7 +63,9 @@ - (instancetype)initWithTraceId:(SentryId *)traceId _environment = environment; _releaseName = releaseName; _transaction = transaction; +#if !SDK_V9 _userSegment = userSegment; +#endif _sampleRand = sampleRand; _sampleRate = sampleRate; _sampled = sampled; @@ -69,26 +79,27 @@ - (nullable instancetype)initWithScope:(SentryScope *)scope options:(SentryOptio SentryTracer *tracer = [SentryTracer getTracer:scope.span]; if (tracer == nil) { return nil; - } else { - return [self initWithTracer:tracer scope:scope options:options]; } + return [self initWithTracer:tracer scope:scope options:options]; } - (nullable instancetype)initWithTracer:(SentryTracer *)tracer scope:(nullable SentryScope *)scope options:(SentryOptions *)options { - if (tracer.traceId == nil || options.parsedDsn == nil) + if (tracer.traceId == nil || options.parsedDsn == nil) { return nil; + } - NSString *userSegment; - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#if !SDK_V9 + NSString *userSegment = nil; +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" if (scope.userObject.segment) { userSegment = scope.userObject.segment; } -#pragma clang diagnostic pop +# pragma clang diagnostic pop +#endif // !SDK_V9 NSString *serializedSampleRand = nil; NSNumber *sampleRand = [tracer.transactionContext sampleRand]; @@ -112,7 +123,9 @@ - (nullable instancetype)initWithTracer:(SentryTracer *)tracer releaseName:options.releaseName environment:options.environment transaction:tracer.transactionContext.name +#if !SDK_V9 userSegment:userSegment +#endif sampleRate:serializedSampleRate sampleRand:serializedSampleRand sampled:sampled @@ -121,7 +134,9 @@ - (nullable instancetype)initWithTracer:(SentryTracer *)tracer - (instancetype)initWithTraceId:(SentryId *)traceId options:(SentryOptions *)options +#if !SDK_V9 userSegment:(nullable NSString *)userSegment +#endif replayId:(nullable NSString *)replayId; { return [[SentryTraceContext alloc] initWithTraceId:traceId @@ -129,7 +144,9 @@ - (instancetype)initWithTraceId:(SentryId *)traceId releaseName:options.releaseName environment:options.environment transaction:nil +#if !SDK_V9 userSegment:userSegment +#endif sampleRate:nil sampleRand:nil sampled:nil @@ -138,11 +155,19 @@ - (instancetype)initWithTraceId:(SentryId *)traceId - (nullable instancetype)initWithDict:(NSDictionary *)dictionary { - SentryId *traceId = [[SentryId alloc] initWithUUIDString:dictionary[@"trace_id"]]; + NSString *_Nullable rawTraceId = dictionary[@"trace_id"]; + if (rawTraceId == nil || ![rawTraceId isKindOfClass:[NSString class]]) { + SENTRY_LOG_ERROR(@"Invalid trace_id: %@", rawTraceId); + return nil; + } + + SentryId *traceId = + [[SentryId alloc] initWithUUIDString:SENTRY_UNWRAP_NULLABLE(NSString, rawTraceId)]; NSString *publicKey = dictionary[@"public_key"]; if (traceId == nil || publicKey == nil) return nil; +#if !SDK_V9 NSString *userSegment; if (dictionary[@"user"] != nil) { NSDictionary *userInfo = dictionary[@"user"]; @@ -151,13 +176,16 @@ - (nullable instancetype)initWithDict:(NSDictionary *)dictionary } else { userSegment = dictionary[@"user_segment"]; } +#endif return [self initWithTraceId:traceId publicKey:publicKey releaseName:dictionary[@"release"] environment:dictionary[@"environment"] transaction:dictionary[@"transaction"] +#if !SDK_V9 userSegment:userSegment +#endif sampleRate:dictionary[@"sample_rate"] sampleRand:dictionary[@"sample_rand"] sampled:dictionary[@"sampled"] @@ -171,7 +199,9 @@ - (SentryBaggage *)toBaggage releaseName:_releaseName environment:_environment transaction:_transaction +#if !SDK_V9 userSegment:_userSegment +#endif sampleRate:_sampleRate sampleRand:_sampleRand sampled:_sampled @@ -196,9 +226,11 @@ - (SentryBaggage *)toBaggage [result setValue:_transaction forKey:@"transaction"]; } +#if !SDK_V9 if (_userSegment != nil) { [result setValue:_userSegment forKey:@"user_segment"]; } +#endif if (_sampleRand != nil) { [result setValue:_sampleRand forKey:@"sample_rand"]; diff --git a/Sources/Sentry/SentryTracer.m b/Sources/Sentry/SentryTracer.m index c0e4b3a5b2c..03cf957d7b3 100644 --- a/Sources/Sentry/SentryTracer.m +++ b/Sources/Sentry/SentryTracer.m @@ -12,7 +12,6 @@ #import "SentryNoOpSpan.h" #import "SentryOptions+Private.h" #import "SentryProfilingConditionals.h" -#import "SentryRandom.h" #import "SentrySDK+Private.h" #import "SentrySamplerDecision.h" #import "SentryScope+Private.h" @@ -28,9 +27,7 @@ #import "SentryTracer+Private.h" #import "SentryTransaction.h" #import "SentryTransactionContext.h" -#import "SentryUIApplication.h" #import -#import #if SENTRY_TARGET_PROFILING_SUPPORTED # import "SentryProfiledTracerConcurrency.h" @@ -145,7 +142,7 @@ - (instancetype)initWithTransactionContext:(SentryTransactionContext *)transacti #if SENTRY_HAS_UIKIT [hub configureScope:^(SentryScope *scope) { if (scope.currentScreen != nil) { - self->viewNames = @[ scope.currentScreen ]; + self->viewNames = @[ SENTRY_UNWRAP_NULLABLE(NSString, scope.currentScreen) ]; } }]; @@ -437,8 +434,8 @@ - (nullable SentryTraceContext *)traceContext _traceContext = [[SentryTraceContext alloc] initWithTracer:self scope:_hub.scope options:_hub.client.options - ?: SentrySDK.options]; // We should remove static classes and always - // inject dependencies. + ?: SentrySDKInternal.options]; // We should remove static classes and always + // inject dependencies. } } } @@ -751,12 +748,14 @@ - (SentryTransaction *)toTransaction NSMutableArray *framesOfAllSpans = [NSMutableArray array]; if ([(SentrySpan *)self frames]) { - [framesOfAllSpans addObjectsFromArray:[(SentrySpan *)self frames]]; + [framesOfAllSpans addObjectsFromArray:SENTRY_UNWRAP_NULLABLE(NSArray, + [(SentrySpan *)self frames])]; } for (SentrySpan *span in spans) { if (span.frames) { - [framesOfAllSpans addObjectsFromArray:span.frames]; + [framesOfAllSpans + addObjectsFromArray:SENTRY_UNWRAP_NULLABLE(NSArray, span.frames)]; } } @@ -812,7 +811,7 @@ - (nullable SentryAppStartMeasurement *)getAppStartMeasurement SENTRY_DISABLE_TH return nil; } - measurement = [SentrySDK getAppStartMeasurement]; + measurement = [SentrySDKInternal getAppStartMeasurement]; if (measurement == nil) { SENTRY_LOG_DEBUG(@"No app start measurement available."); return nil; @@ -917,14 +916,14 @@ + (void)resetAppStartMeasurementRead } } -+ (nullable SentryTracer *)getTracer:(id)span ++ (nullable SentryTracer *)getTracer:(id _Nullable)span { if (span == nil) { return nil; } if ([span isKindOfClass:[SentryTracer class]]) { - return span; + return (SentryTracer *)span; } else if ([span isKindOfClass:[SentrySpan class]]) { return [(SentrySpan *)span tracer]; } diff --git a/Sources/Sentry/SentryTransaction.m b/Sources/Sentry/SentryTransaction.m index 9c55a92bc4f..e7ab40b13b2 100644 --- a/Sources/Sentry/SentryTransaction.m +++ b/Sources/Sentry/SentryTransaction.m @@ -1,6 +1,6 @@ #import "SentryTransaction.h" -#import "SentryEnvelopeItemType.h" -#import "SentryMeasurementValue.h" +#import "SentryEvent+Serialize.h" +#import "SentryInternalDefines.h" #import "SentryNSDictionarySanitize.h" #import "SentryProfilingConditionals.h" #import "SentrySpan+Private.h" @@ -18,7 +18,7 @@ - (instancetype)initWithTrace:(SentryTracer *)trace children:(NSArray *mutableContext = [[NSMutableDictionary alloc] init]; - if (serializedData[@"contexts"] != nil) { - [mutableContext addEntriesFromDictionary:serializedData[@"contexts"]]; + if (serializedData[@"contexts"] != nil && + [serializedData[@"contexts"] isKindOfClass:NSDictionary.class]) { + [mutableContext addEntriesFromDictionary:SENTRY_UNWRAP_NULLABLE( + NSDictionary, serializedData[@"contexts"])]; } #if SENTRY_TARGET_PROFILING_SUPPORTED @@ -50,13 +52,13 @@ - (instancetype)initWithTrace:(SentryTracer *)trace children:(NSArray *traceTags = [sentry_sanitize(self.trace.tags) mutableCopy]; - [traceTags addEntriesFromDictionary:sentry_sanitize(self.trace.tags)]; // Adding tags from Trace to serializedData dictionary if (serializedData[@"tags"] != nil && [serializedData[@"tags"] isKindOfClass:NSDictionary.class]) { NSMutableDictionary *tags = [NSMutableDictionary new]; - [tags addEntriesFromDictionary:serializedData[@"tags"]]; + [tags + addEntriesFromDictionary:SENTRY_UNWRAP_NULLABLE(NSDictionary, serializedData[@"tags"])]; [tags addEntriesFromDictionary:traceTags]; serializedData[@"tags"] = tags; } else { @@ -69,7 +71,8 @@ - (instancetype)initWithTrace:(SentryTracer *)trace children:(NSArray)rateLimits { - NSURLSession *session; - - if (options.urlSession) { - session = options.urlSession; - } else { - NSURLSessionConfiguration *configuration = - [NSURLSessionConfiguration ephemeralSessionConfiguration]; - session = [NSURLSession sessionWithConfiguration:configuration - delegate:options.urlSessionDelegate - delegateQueue:nil]; - } + NSMutableArray> *transports = [NSMutableArray array]; + NSURLSession *session = [self getUrlSession:options]; id requestManager = [[SentryQueueableRequestManager alloc] initWithSession:session]; - SentryEnvelopeRateLimit *envelopeRateLimit = [[SentryEnvelopeRateLimit alloc] initWithRateLimits:rateLimits]; - - dispatch_queue_attr_t attributes = dispatch_queue_attr_make_with_qos_class( - DISPATCH_QUEUE_SERIAL, DISPATCH_QUEUE_PRIORITY_LOW, 0); - SentryDispatchQueueWrapper *dispatchQueueWrapper = - [[SentryDispatchQueueWrapper alloc] initWithName:"io.sentry.http-transport" - attributes:attributes]; + SentryDispatchQueueWrapper *dispatchQueueWrapper = [self createDispatchQueueWrapper]; SentryNSURLRequestBuilder *requestBuilder = [[SentryNSURLRequestBuilder alloc] init]; - SentryHttpTransport *httpTransport = - [[SentryHttpTransport alloc] initWithOptions:options + if (options.enableSpotlight) { + SENTRY_LOG_DEBUG(@"Spotlight is enabled, creating Spotlight transport."); + SentrySpotlightTransport *spotlightTransport = + [[SentrySpotlightTransport alloc] initWithOptions:options + requestManager:requestManager + requestBuilder:requestBuilder + dispatchQueueWrapper:dispatchQueueWrapper]; + + [transports addObject:spotlightTransport]; + } else { + SENTRY_LOG_DEBUG(@"Spotlight is disabled in options, not adding Spotlight transport."); + } + + if (options.parsedDsn) { + SENTRY_LOG_DEBUG(@"Options contain parsed DSN, creating HTTP transport."); + SentryDsn *_Nonnull dsn = SENTRY_UNWRAP_NULLABLE(SentryDsn, options.parsedDsn); + + SentryHttpTransport *httpTransport = + [[SentryHttpTransport alloc] initWithDsn:dsn + sendClientReports:options.sendClientReports cachedEnvelopeSendDelay:0.1 dateProvider:dateProvider fileManager:sentryFileManager @@ -64,18 +69,39 @@ @implementation SentryTransportFactory envelopeRateLimit:envelopeRateLimit dispatchQueueWrapper:dispatchQueueWrapper]; - if (options.enableSpotlight) { - SentrySpotlightTransport *spotlightTransport = - [[SentrySpotlightTransport alloc] initWithOptions:options - requestManager:requestManager - requestBuilder:requestBuilder - dispatchQueueWrapper:dispatchQueueWrapper]; - return @[ httpTransport, spotlightTransport ]; + [transports addObject:httpTransport]; } else { - return @[ httpTransport ]; + SENTRY_LOG_WARN( + @"Failed to create HTTP transport because the SentryOptions does not contain " + @"a parsed DSN."); } + + return transports; } ++ (NSURLSession *)getUrlSession:(SentryOptions *_Nonnull)options +{ + if (options.urlSession) { + SENTRY_LOG_DEBUG(@"Using URL session provided in SDK options for HTTP transport."); + return SENTRY_UNWRAP_NULLABLE(NSURLSession, options.urlSession); + } + + NSURLSessionConfiguration *configuration = + [NSURLSessionConfiguration ephemeralSessionConfiguration]; + return [NSURLSession sessionWithConfiguration:configuration + delegate:options.urlSessionDelegate + delegateQueue:nil]; +} + ++ (SentryDispatchQueueWrapper *)createDispatchQueueWrapper +{ + dispatch_queue_attr_t attributes = dispatch_queue_attr_make_with_qos_class( + DISPATCH_QUEUE_SERIAL, DISPATCH_QUEUE_PRIORITY_LOW, 0); + SentryDispatchQueueWrapper *dispatchQueueWrapper = + [[SentryDispatchQueueWrapper alloc] initWithName:"io.sentry.http-transport" + attributes:attributes]; + return dispatchQueueWrapper; +} @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryUIApplication.m b/Sources/Sentry/SentryUIApplication.m deleted file mode 100644 index 4bc9c88a385..00000000000 --- a/Sources/Sentry/SentryUIApplication.m +++ /dev/null @@ -1,278 +0,0 @@ -#import "SentryUIApplication.h" -#import "SentryLogC.h" -#import "SentryNSNotificationCenterWrapper.h" -#import "SentrySwift.h" - -#if SENTRY_HAS_UIKIT - -# import - -@interface SentryUIApplication () - -@property (nonatomic, assign) UIApplicationState appState; -@property (nonatomic, strong) SentryNSNotificationCenterWrapper *notificationCenterWrapper; -@property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueueWrapper; - -@end - -@implementation SentryUIApplication - -- (instancetype)initWithNotificationCenterWrapper: - (SentryNSNotificationCenterWrapper *)notificationCenterWrapper - dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper -{ - if (self = [super init]) { - self.notificationCenterWrapper = notificationCenterWrapper; - self.dispatchQueueWrapper = dispatchQueueWrapper; - - [self.notificationCenterWrapper addObserver:self - selector:@selector(didEnterBackground) - name:UIApplicationDidEnterBackgroundNotification]; - - [self.notificationCenterWrapper addObserver:self - selector:@selector(didBecomeActive) - name:UIApplicationDidBecomeActiveNotification]; - - // We store the application state when the app is initialized - // and we keep track of its changes by the notifications - // this way we avoid calling sharedApplication in a background thread - [self.dispatchQueueWrapper - dispatchAsyncOnMainQueue:^{ self.appState = self.sharedApplication.applicationState; }]; - } - return self; -} - -- (void)dealloc -{ - [self.notificationCenterWrapper removeObserver:self]; -} - -- (UIApplication *)sharedApplication -{ - if (![UIApplication respondsToSelector:@selector(sharedApplication)]) - return nil; - - return [UIApplication performSelector:@selector(sharedApplication)]; -} - -- (nullable id)getApplicationDelegate:(UIApplication *)application -{ - return application.delegate; -} - -- (NSArray *)getApplicationConnectedScenes:(UIApplication *)application - API_AVAILABLE(ios(13.0), tvos(13.0)) -{ - if (application && [application respondsToSelector:@selector(connectedScenes)]) { - return [application.connectedScenes allObjects]; - } - - return @[]; -} - -- (NSArray *)windows -{ - __block NSArray *windows = nil; - [_dispatchQueueWrapper - dispatchSyncOnMainQueue:^{ - UIApplication *app = [self sharedApplication]; - NSMutableSet *result = [NSMutableSet set]; - - if (@available(iOS 13.0, tvOS 13.0, *)) { - NSArray *scenes = [self getApplicationConnectedScenes:app]; - for (UIScene *scene in scenes) { - if (scene.activationState == UISceneActivationStateForegroundActive - && scene.delegate && - [scene.delegate respondsToSelector:@selector(window)]) { - id window = [scene.delegate performSelector:@selector(window)]; - if (window) { - [result addObject:window]; - } - } - } - } - - id appDelegate = [self getApplicationDelegate:app]; - - if ([appDelegate respondsToSelector:@selector(window)] && appDelegate.window != nil) { - [result addObject:appDelegate.window]; - } - - windows = [result allObjects]; - } - timeout:0.01]; - return windows ?: @[]; -} - -- (NSArray *)relevantViewControllers -{ - NSArray *windows = [self windows]; - if ([windows count] == 0) { - return nil; - } - - NSMutableArray *result = [NSMutableArray array]; - - for (UIWindow *window in windows) { - NSArray *vcs = [self relevantViewControllerFromWindow:window]; - if (vcs != nil) { - [result addObjectsFromArray:vcs]; - } - } - - return result; -} - -- (nullable NSArray *)relevantViewControllersNames -{ - __block NSArray *result = nil; - __weak SentryUIApplication *weakSelf = self; - - [_dispatchQueueWrapper - dispatchSyncOnMainQueue:^{ - if (weakSelf == nil) { - SENTRY_LOG_DEBUG(@"WeakSelf is nil. Not doing anything."); - return; - } - - NSArray *viewControllers = weakSelf.relevantViewControllers; - NSMutableArray *vcsNames = - [[NSMutableArray alloc] initWithCapacity:viewControllers.count]; - for (UIViewController *vc in viewControllers) { - [vcsNames addObject:[SwiftDescriptor getViewControllerClassName:vc]]; - } - result = [NSArray arrayWithArray:vcsNames]; - } - timeout:0.01]; - - return result; -} - -- (NSArray *)relevantViewControllerFromWindow:(UIWindow *)window -{ - UIViewController *rootViewController = window.rootViewController; - if (rootViewController == nil) { - return nil; - } - - NSMutableArray *result = - [NSMutableArray arrayWithObject:rootViewController]; - NSUInteger index = 0; - - while (index < result.count) { - UIViewController *topVC = result[index]; - // If the view controller is presenting another one, usually in a modal form. - if (topVC.presentedViewController != nil) { - - if ([topVC.presentationController isKindOfClass:UIAlertController.class]) { - // If the view controller being presented is an Alert, we know that - // we reached the end of the view controller stack and the presenter is - // the top view controller. - break; - } - - [result replaceObjectAtIndex:index withObject:topVC.presentedViewController]; - - continue; - } - - // The top view controller is meant for navigation and not content - if ([self isContainerViewController:topVC]) { - NSArray *contentViewController = - [self relevantViewControllerFromContainer:topVC]; - if (contentViewController != nil && contentViewController.count > 0) { - [result removeObjectAtIndex:index]; - [result addObjectsFromArray:contentViewController]; - } else { - break; - } - continue; - } - - UIViewController *relevantChild = nil; - for (UIViewController *childVC in topVC.childViewControllers) { - // Sometimes a view controller is used as container for a navigation controller - // If the navigation is occupying the whole view controller we will consider this the - // case. - if ([self isContainerViewController:childVC] && childVC.isViewLoaded - && CGRectEqualToRect(childVC.view.frame, topVC.view.bounds)) { - relevantChild = childVC; - break; - } - } - - if (relevantChild != nil) { - [result replaceObjectAtIndex:index withObject:relevantChild]; - continue; - } - - index++; - } - - return result; -} - -- (BOOL)isContainerViewController:(UIViewController *)viewController -{ - return [viewController isKindOfClass:UINavigationController.class] || - [viewController isKindOfClass:UITabBarController.class] || - [viewController isKindOfClass:UISplitViewController.class] || - [viewController isKindOfClass:UIPageViewController.class]; -} - -- (nullable NSArray *)relevantViewControllerFromContainer: - (UIViewController *)containerVC -{ - if ([containerVC isKindOfClass:UINavigationController.class]) { - if ([(UINavigationController *)containerVC topViewController]) { - return @[ [(UINavigationController *)containerVC topViewController] ]; - } - return nil; - } - if ([containerVC isKindOfClass:UITabBarController.class]) { - UITabBarController *tbController = (UITabBarController *)containerVC; - NSInteger selectedIndex = tbController.selectedIndex; - if (tbController.viewControllers.count > selectedIndex) { - return @[ [tbController.viewControllers objectAtIndex:selectedIndex] ]; - } else { - return nil; - } - } - if ([containerVC isKindOfClass:UISplitViewController.class]) { - UISplitViewController *splitVC = (UISplitViewController *)containerVC; - if (splitVC.viewControllers.count > 0) { - return [splitVC viewControllers]; - } - } - if ([containerVC isKindOfClass:UIPageViewController.class]) { - UIPageViewController *pageVC = (UIPageViewController *)containerVC; - if (pageVC.viewControllers.count > 0) { - return @[ [[pageVC viewControllers] objectAtIndex:0] ]; - } - } - return nil; -} - -- (UIApplicationState)applicationState -{ - return self.appState; -} - -- (void)didEnterBackground -{ - self.appState = UIApplicationStateBackground; -} - -- (void)didBecomeActive -{ - self.appState = UIApplicationStateActive; -} - -- (BOOL)isActive -{ - return self.appState == UIApplicationStateActive; -} - -@end - -#endif // SENTRY_HAS_UIKIT diff --git a/Sources/Sentry/SentryUIDeviceWrapper.m b/Sources/Sentry/SentryUIDeviceWrapper.m deleted file mode 100644 index 62192c1e575..00000000000 --- a/Sources/Sentry/SentryUIDeviceWrapper.m +++ /dev/null @@ -1,91 +0,0 @@ -#import "SentryUIDeviceWrapper.h" -#import "SentryDependencyContainer.h" -#import "SentrySwift.h" - -#if SENTRY_HAS_UIKIT - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryUIDeviceWrapper () -@property (nonatomic) BOOL cleanupDeviceOrientationNotifications; -@property (nonatomic) BOOL cleanupBatteryMonitoring; -@property (nonatomic, copy) NSString *systemVersion; -@end - -@implementation SentryUIDeviceWrapper - -- (void)start -{ - [SentryDependencyContainer.sharedInstance.dispatchQueueWrapper dispatchAsyncOnMainQueue:^{ - -# if TARGET_OS_IOS - if (!UIDevice.currentDevice.isGeneratingDeviceOrientationNotifications) { - self.cleanupDeviceOrientationNotifications = YES; - [UIDevice.currentDevice beginGeneratingDeviceOrientationNotifications]; - } - - // Needed so we can read the battery level - if (!UIDevice.currentDevice.isBatteryMonitoringEnabled) { - self.cleanupBatteryMonitoring = YES; - UIDevice.currentDevice.batteryMonitoringEnabled = YES; - } -# endif - - self.systemVersion = [UIDevice currentDevice].systemVersion; - }]; -} - -- (void)stop -{ -# if TARGET_OS_IOS - BOOL needsCleanUp = self.cleanupDeviceOrientationNotifications; - BOOL needsDisablingBattery = self.cleanupBatteryMonitoring; - UIDevice *device = [UIDevice currentDevice]; - [SentryDependencyContainer.sharedInstance.dispatchQueueWrapper dispatchAsyncOnMainQueue:^{ - if (needsCleanUp) { - [device endGeneratingDeviceOrientationNotifications]; - } - if (needsDisablingBattery) { - device.batteryMonitoringEnabled = NO; - } - }]; -# endif // TARGET_OS_IOS -} - -- (void)dealloc -{ - [self stop]; -} - -# if TARGET_OS_IOS -- (UIDeviceOrientation)orientation -{ - return (UIDeviceOrientation)[UIDevice currentDevice].orientation; -} - -- (BOOL)isBatteryMonitoringEnabled -{ - return [UIDevice currentDevice].isBatteryMonitoringEnabled; -} - -- (UIDeviceBatteryState)batteryState -{ - return (UIDeviceBatteryState)[UIDevice currentDevice].batteryState; -} - -- (float)batteryLevel -{ - return [UIDevice currentDevice].batteryLevel; -} -# endif // TARGET_OS_IOS - -- (NSString *)getSystemVersion -{ - return self.systemVersion; -} - -@end - -NS_ASSUME_NONNULL_END - -#endif // SENTRY_HAS_UIKIT diff --git a/Sources/Sentry/SentryUIEventTracker.m b/Sources/Sentry/SentryUIEventTracker.m index 0e98d44f180..44126b5fdb6 100644 --- a/Sources/Sentry/SentryUIEventTracker.m +++ b/Sources/Sentry/SentryUIEventTracker.m @@ -1,3 +1,4 @@ +#import "SentryInternalDefines.h" #import #if SENTRY_HAS_UIKIT @@ -67,14 +68,14 @@ - (void)sendActionCallback:(NSString *)action // which is unacceptable for a transaction name. Ideally, we should somehow shorten // the long name. - NSString *targetClass = NSStringFromClass([target class]); + NSString *targetClass = NSStringFromClass([SENTRY_UNWRAP_NULLABLE_VALUE(Class, target) class]); if ([targetClass containsString:@"SwiftUI"]) { SENTRY_LOG_DEBUG(@"Won't record transaction for SwiftUI target event."); return; } NSString *actionName = [self getTransactionName:action target:targetClass]; - NSString *operation = [self getOperation:sender]; + NSString *operation = [self getOperation:SENTRY_UNWRAP_NULLABLE_VALUE(id, sender)]; NSString *accessibilityIdentifier = nil; if (_reportAccessibilityIdentifier && [[sender class] isSubclassOfClass:[UIView class]]) { diff --git a/Sources/Sentry/SentryUIEventTrackerTransactionMode.m b/Sources/Sentry/SentryUIEventTrackerTransactionMode.m index fa84010ef46..0b9e6483162 100644 --- a/Sources/Sentry/SentryUIEventTrackerTransactionMode.m +++ b/Sources/Sentry/SentryUIEventTrackerTransactionMode.m @@ -7,7 +7,7 @@ # import # import # import -# import +# import # import # import # import @@ -70,7 +70,7 @@ - (void)handleUIEvent:(NSString *)action operation:operation origin:SentryTraceOriginAutoUiEventTracker]; - id _Nullable currentSpan = [SentrySDK.currentHub.scope span]; + id _Nullable currentSpan = [SentrySDKInternal.currentHub.scope span]; BOOL ongoingScreenLoadTransaction = false; BOOL ongoingManualTransaction = false; if (currentSpan != nil) { @@ -92,7 +92,7 @@ - (void)handleUIEvent:(NSString *)action return; } - __block SentryTracer *transaction = [SentrySDK.currentHub + __block SentryTracer *transaction = [SentrySDKInternal.currentHub startTransactionWithContext:context bindToScope:YES customSamplingContext:@{} diff --git a/Sources/Sentry/SentryUIViewControllerPerformanceTracker.m b/Sources/Sentry/SentryUIViewControllerPerformanceTracker.m index 72db09fd8b5..2fddaf970ab 100644 --- a/Sources/Sentry/SentryUIViewControllerPerformanceTracker.m +++ b/Sources/Sentry/SentryUIViewControllerPerformanceTracker.m @@ -1,4 +1,5 @@ #import "SentryUIViewControllerPerformanceTracker.h" +#import "SentryInternalDefines.h" #if SENTRY_HAS_UIKIT @@ -15,7 +16,6 @@ # import "SentryTraceOrigin.h" # import "SentryTracer.h" # import "SentryWeakMap.h" -# import # import # import @@ -69,7 +69,7 @@ - (instancetype)initWithTracker:(SentryPerformanceTracker *)tracker if (self = [super init]) { self.tracker = tracker; - SentryOptions *options = [SentrySDK options]; + SentryOptions *options = [SentrySDKInternal options]; self.inAppLogic = [[SentryInAppLogic alloc] initWithInAppIncludes:options.inAppIncludes inAppExcludes:options.inAppExcludes]; @@ -94,7 +94,7 @@ - (void)viewControllerLoadView:(UIViewController *)controller return; } - SentryOptions *options = [SentrySDK options]; + SentryOptions *options = [SentrySDKInternal options]; if ([SentrySwizzleClassNameExclude shouldExcludeClassWithClassName:NSStringFromClass([controller class]) @@ -171,7 +171,7 @@ - (void)startRootSpanFor:(UIViewController *)controller if (self.tracker.activeSpanId == nil) { SENTRY_LOG_DEBUG(@"Started new transaction with id %@ to track view controller %@.", spanId.sentrySpanIdString, name); - [self.tracker pushActiveSpan:spanId]; + [self.tracker pushActiveSpan:SENTRY_UNWRAP_NULLABLE(SentrySpanId, spanId)]; } else { SENTRY_LOG_DEBUG(@"Started child span with id %@ to track view controller %@.", spanId.sentrySpanIdString, name); @@ -179,7 +179,8 @@ - (void)startRootSpanFor:(UIViewController *)controller } spanId = [self getSpanIdForViewController:controller]; - SentrySpan *_Nullable vcSpan = [self.tracker getSpan:spanId]; + SentrySpan *_Nullable vcSpan + = (SentrySpan *)[self.tracker getSpan:SENTRY_UNWRAP_NULLABLE(SentrySpanId, spanId)]; if (![vcSpan isKindOfClass:[SentryTracer self]]) { // Since TTID and TTFD are meant to the whole screen @@ -261,7 +262,8 @@ - (void)viewControllerViewWillAppear:(UIViewController *)controller @"Tracking UIViewController.viewWillAppear for controller: %@", controller); SentrySpanId *_Nullable spanId = [self getSpanIdForViewController:controller]; - if (spanId == nil || ![self.tracker isSpanAlive:spanId]) { + if (spanId == nil + || ![self.tracker isSpanAlive:SENTRY_UNWRAP_NULLABLE(SentrySpanId, spanId)]) { // We are no longer tracking this UIViewController, just call the base // method. SENTRY_LOG_DEBUG( @@ -279,7 +281,8 @@ - (void)viewControllerViewWillAppear:(UIViewController *)controller inBlock:callbackToOrigin]; }; - [self.tracker activateSpan:spanId duringBlock:duringBlock]; + [self.tracker activateSpan:SENTRY_UNWRAP_NULLABLE(SentrySpanId, spanId) + duringBlock:duringBlock]; [self reportInitialDisplayForController:controller]; }; @@ -330,9 +333,10 @@ - (void)finishTransaction:(UIViewController *)controller { SENTRY_LOG_DEBUG(@"Finishing transaction for view controller: %@", controller); void (^limitOverrideBlock)(void) = ^{ - SentrySpanId *_Nullable spanId = [self getSpanIdForViewController:controller]; + SentrySpanId *_Nullable nullableSpanId = [self getSpanIdForViewController:controller]; - if (spanId == nil || ![self.tracker isSpanAlive:spanId]) { + if (nullableSpanId == nil + || ![self.tracker isSpanAlive:SENTRY_UNWRAP_NULLABLE(SentrySpanId, nullableSpanId)]) { // We are no longer tracking this UIViewController, just call the base // method. SENTRY_LOG_DEBUG(@"Not tracking UIViewController.%@ because there is no active span.", @@ -340,6 +344,7 @@ - (void)finishTransaction:(UIViewController *)controller callbackToOrigin(); return; } + SentrySpanId *_Nonnull spanId = SENTRY_UNWRAP_NULLABLE(SentrySpanId, nullableSpanId); void (^duringBlock)(void) = ^{ [self.tracker measureSpanWithDescription:lifecycleMethod @@ -377,9 +382,10 @@ - (void)viewControllerViewWillLayoutSubViews:(UIViewController *)controller SENTRY_LOG_DEBUG( @"Tracking UIViewController.viewWillLayoutSubviews for view controller: %@", controller); void (^limitOverrideBlock)(void) = ^{ - SentrySpanId *_Nullable spanId = [self getSpanIdForViewController:controller]; + SentrySpanId *_Nullable nullableSpanId = [self getSpanIdForViewController:controller]; - if (spanId == nil || ![self.tracker isSpanAlive:spanId]) { + if (nullableSpanId == nil + || ![self.tracker isSpanAlive:SENTRY_UNWRAP_NULLABLE(SentrySpanId, nullableSpanId)]) { // We are no longer tracking this UIViewController, just call the base // method. SENTRY_LOG_DEBUG(@"Not tracking UIViewController.viewWillLayoutSubviews because there " @@ -387,6 +393,7 @@ - (void)viewControllerViewWillLayoutSubViews:(UIViewController *)controller callbackToOrigin(); return; } + SentrySpanId *_Nonnull spanId = SENTRY_UNWRAP_NULLABLE(SentrySpanId, nullableSpanId); void (^duringBlock)(void) = ^{ [self.tracker measureSpanWithDescription:@"viewWillLayoutSubviews" @@ -427,9 +434,10 @@ - (void)viewControllerViewDidLayoutSubViews:(UIViewController *)controller SENTRY_LOG_DEBUG( @"Tracking UIViewController.viewDidLayoutSubviews for view controller: %@", controller); void (^limitOverrideBlock)(void) = ^{ - SentrySpanId *_Nullable spanId = [self getSpanIdForViewController:controller]; + SentrySpanId *_Nullable nullableSpanId = [self getSpanIdForViewController:controller]; - if (spanId == nil || ![self.tracker isSpanAlive:spanId]) { + if (nullableSpanId == nil + || ![self.tracker isSpanAlive:SENTRY_UNWRAP_NULLABLE(SentrySpanId, nullableSpanId)]) { // We are no longer tracking this UIViewController, just call the base // method. SENTRY_LOG_DEBUG(@"Not tracking UIViewController.viewDidLayoutSubviews because there " @@ -437,6 +445,7 @@ - (void)viewControllerViewDidLayoutSubViews:(UIViewController *)controller callbackToOrigin(); return; } + SentrySpanId *_Nonnull spanId = SENTRY_UNWRAP_NULLABLE(SentrySpanId, nullableSpanId); void (^duringBlock)(void) = ^{ SentrySpanId *layoutSubViewId = diff --git a/Sources/Sentry/SentryUIViewControllerSwizzling.m b/Sources/Sentry/SentryUIViewControllerSwizzling.m index 2ccc69320fc..6759f4eb0de 100644 --- a/Sources/Sentry/SentryUIViewControllerSwizzling.m +++ b/Sources/Sentry/SentryUIViewControllerSwizzling.m @@ -2,19 +2,14 @@ #if SENTRY_HAS_UIKIT -# import "SentryBinaryImageCache.h" -# import "SentryDefaultObjCRuntimeWrapper.h" # import "SentryDefines.h" # import "SentryDependencyContainer.h" # import "SentryLogC.h" -# import "SentryNSProcessInfoWrapper.h" # import "SentrySubClassFinder.h" # import "SentrySwift.h" # import "SentrySwizzle.h" # import "SentryUIViewControllerPerformanceTracker.h" -# import # import -# import # import # import # import @@ -42,7 +37,7 @@ @interface SentryUIViewControllerSwizzling () @property (nonatomic, strong) id objcRuntimeWrapper; @property (nonatomic, strong) SentrySubClassFinder *subClassFinder; @property (nonatomic, strong) NSMutableSet *imagesActedOnSubclassesOfUIViewControllers; -@property (nonatomic, strong) SentryNSProcessInfoWrapper *processInfoWrapper; +@property (nonatomic, strong) id processInfoWrapper; @property (nonatomic, strong) SentryBinaryImageCache *binaryImageCache; @end @@ -53,7 +48,7 @@ - (instancetype)initWithOptions:(SentryOptions *)options dispatchQueue:(SentryDispatchQueueWrapper *)dispatchQueue objcRuntimeWrapper:(id)objcRuntimeWrapper subClassFinder:(SentrySubClassFinder *)subClassFinder - processInfoWrapper:(SentryNSProcessInfoWrapper *)processInfoWrapper + processInfoWrapper:(id)processInfoWrapper binaryImageCache:(SentryBinaryImageCache *)binaryImageCache { if (self = [super init]) { diff --git a/Sources/Sentry/SentryUseNSExceptionCallstackWrapper.m b/Sources/Sentry/SentryUseNSExceptionCallstackWrapper.m index b1ba92ed7a7..f00c79568a3 100644 --- a/Sources/Sentry/SentryUseNSExceptionCallstackWrapper.m +++ b/Sources/Sentry/SentryUseNSExceptionCallstackWrapper.m @@ -1,10 +1,10 @@ #import "SentryUseNSExceptionCallstackWrapper.h" #import "SentryCrashStackEntryMapper.h" #import "SentryCrashSymbolicator.h" -#import "SentryInAppLogic.h" #import "SentryOptions+Private.h" #import "SentrySDK+Private.h" #import "SentryStacktraceBuilder.h" +#import "SentrySwift.h" #import "SentryThread.h" #if TARGET_OS_OSX @@ -45,7 +45,7 @@ - (instancetype)initWithName:(NSExceptionName)aName enumerateObjectsUsingBlock:^(NSNumber *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) { SentryCrashStackCursor stackCursor; stackCursor.stackEntry.address = [obj unsignedLongValue]; - sentrycrashsymbolicator_symbolicate(&stackCursor); + sentrycrashsymbolicator_symbolicate_async_unsafe_sentryDlAddr(&stackCursor); [frames addObject:[crashStackToEntryMapper sentryCrashStackEntryToSentryFrame:stackCursor.stackEntry]]; @@ -58,7 +58,7 @@ - (instancetype)initWithName:(NSExceptionName)aName - (SentryCrashStackEntryMapper *)buildCrashStackToEntryMapper { - SentryOptions *options = SentrySDK.options; + SentryOptions *options = SentrySDKInternal.options; SentryInAppLogic *inAppLogic = [[SentryInAppLogic alloc] initWithInAppIncludes:options.inAppIncludes diff --git a/Sources/Sentry/SentryUser.m b/Sources/Sentry/SentryUser.m index f309d0b3237..3727d56c341 100644 --- a/Sources/Sentry/SentryUser.m +++ b/Sources/Sentry/SentryUser.m @@ -1,5 +1,7 @@ #import "SentryUser.h" #import "SentryGeo.h" +#import "SentryInternalDefines.h" +#import "SentryModels+Serializable.h" #import "SentryNSDictionarySanitize.h" NS_ASSUME_NONNULL_BEGIN @@ -31,10 +33,12 @@ - (instancetype)initWithDictionary:(NSDictionary *)dictionary } else if ([key isEqualToString:@"ip_address"] && isString) { self.ipAddress = value; } else if ([key isEqualToString:@"segment"] && isString) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#if !SDK_V9 +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" self.segment = value; -#pragma clang diagnostic pop +# pragma clang diagnostic pop +#endif // !SDK_V9 } else if ([key isEqualToString:@"data"] && isDictionary) { self.data = value; } else { @@ -71,10 +75,12 @@ - (id)copyWithZone:(nullable NSZone *)zone copy.email = self.email; copy.username = self.username; copy.ipAddress = self.ipAddress; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#if !SDK_V9 +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" copy.segment = self.segment; -#pragma clang diagnostic pop +# pragma clang diagnostic pop +#endif // !SDK_V9 copy.name = self.name; copy.geo = self.geo.copy; copy.data = self.data.copy; @@ -92,10 +98,12 @@ - (id)copyWithZone:(nullable NSZone *)zone [serializedData setValue:self.email forKey:@"email"]; [serializedData setValue:self.username forKey:@"username"]; [serializedData setValue:self.ipAddress forKey:@"ip_address"]; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#if !SDK_V9 +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" [serializedData setValue:self.segment forKey:@"segment"]; -#pragma clang diagnostic pop +# pragma clang diagnostic pop +#endif // !SDK_V9 [serializedData setValue:self.name forKey:@"name"]; [serializedData setValue:[self.geo serialize] forKey:@"geo"]; [serializedData setValue:sentry_sanitize(self.data) forKey:@"data"]; @@ -118,7 +126,7 @@ - (BOOL)isEqual:(id _Nullable)other return NO; } - return [self isEqualToUser:other]; + return [self isEqualToUser:SENTRY_UNWRAP_NULLABLE(SentryUser, other)]; } - (BOOL)isEqualToUser:(SentryUser *)user @@ -150,13 +158,15 @@ - (BOOL)isEqualToUser:(SentryUser *)user return NO; } -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#if !SDK_V9 +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" NSString *otherSegment = user.segment; if (self.segment != otherSegment && ![self.segment isEqualToString:otherSegment]) { return NO; } -#pragma clang diagnostic pop +# pragma clang diagnostic pop +#endif // !SDK_V9 NSString *otherName = user.name; if (self.name != otherName && ![self.name isEqualToString:otherName]) { @@ -189,10 +199,12 @@ - (NSUInteger)hash hash = hash * 23 + [self.email hash]; hash = hash * 23 + [self.username hash]; hash = hash * 23 + [self.ipAddress hash]; -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#if !SDK_V9 +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" hash = hash * 23 + [self.segment hash]; -#pragma clang diagnostic pop +# pragma clang diagnostic pop +#endif // !SDK_V9 hash = hash * 23 + [self.name hash]; hash = hash * 23 + [self.geo hash]; hash = hash * 23 + [self.data hash]; diff --git a/Sources/Sentry/SentryUserAccess.m b/Sources/Sentry/SentryUserAccess.m index 5f6d1a9ec1d..5335033ec1a 100644 --- a/Sources/Sentry/SentryUserAccess.m +++ b/Sources/Sentry/SentryUserAccess.m @@ -1,6 +1,9 @@ #import "SentryUserAccess.h" #import "SentryHub.h" #import "SentrySDK+Private.h" -#import "SentryScope+Private.h" +#import "SentryScope+PrivateSwift.h" -SentryUser *_Nullable sentry_getCurrentUser(void) { return SentrySDK.currentHub.scope.userObject; } +SentryUser *_Nullable sentry_getCurrentUser(void) +{ + return SentrySDKInternal.currentHub.scope.userObject; +} diff --git a/Sources/Sentry/SentryUserFeedbackIntegration.m b/Sources/Sentry/SentryUserFeedbackIntegration.m index b14188afdd9..8ec08de90db 100644 --- a/Sources/Sentry/SentryUserFeedbackIntegration.m +++ b/Sources/Sentry/SentryUserFeedbackIntegration.m @@ -1,5 +1,6 @@ #import "SentryUserFeedbackIntegration.h" #import "SentryDependencyContainer.h" +#import "SentryInternalDefines.h" #import "SentryOptions+Private.h" #import "SentrySDK+Private.h" #import "SentrySwift.h" @@ -19,10 +20,15 @@ - (BOOL)installWithOptions:(SentryOptions *)options return NO; } + // The screenshot source is coupled to the options, but due to the dependency container being + // tightly to the options anyways, it was decided to not pass it to the container. + SentryScreenshotSource *screenshotSource + = SentryDependencyContainer.sharedInstance.screenshotSource; _driver = [[SentryUserFeedbackIntegrationDriver alloc] - initWithConfiguration:options.userFeedbackConfiguration + initWithConfiguration:SENTRY_UNWRAP_NULLABLE(SentryUserFeedbackConfiguration, + options.userFeedbackConfiguration) delegate:self - screenshotProvider:SentryDependencyContainer.sharedInstance.screenshot]; + screenshotSource:screenshotSource]; return YES; } diff --git a/Sources/Sentry/SentryViewHierarchyIntegration.m b/Sources/Sentry/SentryViewHierarchyIntegration.m index 4401cad37cc..6a0cf47eeda 100644 --- a/Sources/Sentry/SentryViewHierarchyIntegration.m +++ b/Sources/Sentry/SentryViewHierarchyIntegration.m @@ -44,7 +44,7 @@ - (BOOL)installWithOptions:(nonnull SentryOptions *)options self.options = options; - SentryClient *client = [SentrySDK.currentHub getClient]; + SentryClient *client = [SentrySDKInternal.currentHub getClient]; [client addAttachmentProcessor:self]; sentrycrash_setSaveViewHierarchy(&saveViewHierarchy); @@ -63,7 +63,7 @@ - (void)uninstall { sentrycrash_setSaveViewHierarchy(NULL); - SentryClient *client = [SentrySDK.currentHub getClient]; + SentryClient *client = [SentrySDKInternal.currentHub getClient]; [client removeAttachmentProcessor:self]; } diff --git a/Sources/Sentry/SentryViewHierarchyProvider.m b/Sources/Sentry/SentryViewHierarchyProvider.m index f8e92eea5db..da5f35aa027 100644 --- a/Sources/Sentry/SentryViewHierarchyProvider.m +++ b/Sources/Sentry/SentryViewHierarchyProvider.m @@ -6,7 +6,6 @@ # import "SentryCrashJSONCodec.h" # import "SentryLogC.h" # import "SentrySwift.h" -# import "SentryUIApplication.h" # import static int @@ -47,7 +46,7 @@ - (instancetype)initWithDispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispa - (BOOL)saveViewHierarchy:(NSString *)filePath { - NSArray *windows = [self.sentryUIApplication windows]; + NSArray *windows = [self.sentryUIApplication getWindows]; const char *path = [filePath UTF8String]; int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644); @@ -80,7 +79,7 @@ - (NSData *)appViewHierarchyFromMainThread - (NSData *)appViewHierarchy { NSMutableData *result = [[NSMutableData alloc] init]; - NSArray *windows = [self.sentryUIApplication windows]; + NSArray *windows = [self.sentryUIApplication getWindows]; if (![self processViewHierarchy:windows addFunction:writeJSONDataToMemory diff --git a/Sources/Sentry/SentryWatchdogTerminationLogic.m b/Sources/Sentry/SentryWatchdogTerminationLogic.m index ba323e74aba..4491b86c25d 100644 --- a/Sources/Sentry/SentryWatchdogTerminationLogic.m +++ b/Sources/Sentry/SentryWatchdogTerminationLogic.m @@ -1,12 +1,12 @@ +#import #import #if SENTRY_HAS_UIKIT -# import # import -# import # import # import +# import @interface SentryWatchdogTerminationLogic () @@ -36,21 +36,23 @@ - (BOOL)isWatchdogTermination return NO; } - SentryAppState *previousAppState = [self.appStateManager loadPreviousAppState]; - SentryAppState *currentAppState = [self.appStateManager buildCurrentAppState]; - + SentryAppState *_Nullable nullablePreviousAppState = + [self.appStateManager loadPreviousAppState]; // If there is no previous app state, we can't do anything. - if (previousAppState == nil) { + if (nullablePreviousAppState == nil) { return NO; } + SentryAppState *_Nonnull previousAppState = (SentryAppState *_Nonnull)nullablePreviousAppState; + SentryAppState *currentAppState = [self.appStateManager buildCurrentAppState]; if (self.crashAdapter.isSimulatorBuild) { return NO; } // If the release name is different we assume it's an upgrade if (currentAppState.releaseName != nil && previousAppState.releaseName != nil - && ![currentAppState.releaseName isEqualToString:previousAppState.releaseName]) { + && ![currentAppState.releaseName + isEqualToString:SENTRY_UNWRAP_NULLABLE(NSString, previousAppState.releaseName)]) { return NO; } @@ -104,7 +106,7 @@ - (BOOL)isWatchdogTermination // When calling SentrySDK.start twice we would wrongly report a Watchdog Termination. We can // only report a Watchdog Termination when the SDK is started the first time. - if (SentrySDK.startInvocations != 1) { + if (SentrySDKInternal.startInvocations != 1) { return NO; } diff --git a/Sources/Sentry/SentryWatchdogTerminationTracker.m b/Sources/Sentry/SentryWatchdogTerminationTracker.m index d33cac75068..25b8ab5daee 100644 --- a/Sources/Sentry/SentryWatchdogTerminationTracker.m +++ b/Sources/Sentry/SentryWatchdogTerminationTracker.m @@ -2,7 +2,6 @@ #import "SentryEvent+Private.h" #import "SentryFileManager.h" #import "SentrySwift.h" -#import #import #import #import @@ -77,7 +76,7 @@ - (void)start // We don't need to update the releaseName of the event to the previous app state as we // assume it's not a watchdog termination when the releaseName changed between app // starts. - [SentrySDK captureFatalEvent:event]; + [SentrySDKInternal captureFatalEvent:event]; } }]; #else // !SENTRY_HAS_UIKIT diff --git a/Sources/Sentry/SentryWatchdogTerminationTrackingIntegration.m b/Sources/Sentry/SentryWatchdogTerminationTrackingIntegration.m index 8ac6ef6f800..0ed1399cbdf 100644 --- a/Sources/Sentry/SentryWatchdogTerminationTrackingIntegration.m +++ b/Sources/Sentry/SentryWatchdogTerminationTrackingIntegration.m @@ -1,19 +1,16 @@ #import #if SENTRY_HAS_UIKIT - # import "SentryScope+Private.h" # import -# import # import # import -# import # import # import -# import # import # import # import +# import # import # import # import @@ -35,7 +32,7 @@ @implementation SentryWatchdogTerminationTrackingIntegration - (instancetype)init { if (self = [super init]) { - SentryNSProcessInfoWrapper *processInfoWrapper + id processInfoWrapper = SentryDependencyContainer.sharedInstance.processInfoWrapper; self.testConfigurationFilePath = processInfoWrapper.environment[@"XCTestConfigurationFilePath"]; @@ -59,7 +56,7 @@ - (BOOL)installWithOptions:(SentryOptions *)options [[SentryDispatchQueueWrapper alloc] initWithName:"io.sentry.watchdog-termination-tracker" attributes:attributes]; - SentryFileManager *fileManager = [[[SentrySDK currentHub] getClient] fileManager]; + SentryFileManager *fileManager = [[[SentrySDKInternal currentHub] getClient] fileManager]; SentryAppStateManager *appStateManager = [SentryDependencyContainer sharedInstance].appStateManager; SentryCrashWrapper *crashWrapper = [SentryDependencyContainer sharedInstance].crashWrapper; @@ -79,9 +76,15 @@ - (BOOL)installWithOptions:(SentryOptions *)options [self.tracker start]; +# if SDK_V9 + BOOL isV2Enabled = YES; +# else + BOOL isV2Enabled = options.enableAppHangTrackingV2; +# endif // SDK_V9 + self.anrTracker = [SentryDependencyContainer.sharedInstance getANRTracker:options.appHangTimeoutInterval - isV2Enabled:options.enableAppHangTrackingV2]; + isV2Enabled:isV2Enabled]; [self.anrTracker addListener:self]; self.appStateManager = appStateManager; @@ -90,7 +93,7 @@ - (BOOL)installWithOptions:(SentryOptions *)options [SentryDependencyContainer.sharedInstance getWatchdogTerminationScopeObserverWithOptions:options]; - [SentrySDK.currentHub configureScope:^(SentryScope *_Nonnull outerScope) { + [SentrySDKInternal.currentHub configureScope:^(SentryScope *_Nonnull outerScope) { // Add the observer to the scope so that it can be notified when the scope changes. [outerScope addObserver:scopeObserver]; diff --git a/Sources/Sentry/SentyOptionsInternal.m b/Sources/Sentry/SentyOptionsInternal.m new file mode 100644 index 00000000000..69d3ffd46b8 --- /dev/null +++ b/Sources/Sentry/SentyOptionsInternal.m @@ -0,0 +1,464 @@ +#import "SentryANRTrackingIntegration.h" +#import "SentryAutoBreadcrumbTrackingIntegration.h" +#import "SentryAutoSessionTrackingIntegration.h" +#import "SentryCoreDataTrackingIntegration.h" +#import "SentryCrashIntegration.h" +#import "SentryDsn.h" +#import "SentryFileIOTrackingIntegration.h" +#import "SentryInternalDefines.h" +#import "SentryLevelMapper.h" +#import "SentryNetworkTrackingIntegration.h" +#import "SentryOptions+Private.h" +#import "SentryOptions.h" +#import "SentryOptionsInternal.h" +#import "SentrySessionReplayIntegration.h" +#import "SentrySwift.h" +#import "SentrySwiftAsyncIntegration.h" + +#if SENTRY_HAS_UIKIT +# import "SentryAppStartTrackingIntegration.h" +# import "SentryFramesTrackingIntegration.h" +# import "SentryPerformanceTrackingIntegration.h" +# import "SentryScreenshotIntegration.h" +# import "SentryUIEventTrackingIntegration.h" +# import "SentryUserFeedbackIntegration.h" +# import "SentryViewHierarchyIntegration.h" +# import "SentryWatchdogTerminationTrackingIntegration.h" +#endif // SENTRY_HAS_UIKIT + +#if SENTRY_HAS_METRIC_KIT +# import "SentryMetricKitIntegration.h" +#endif // SENTRY_HAS_METRIC_KIT + +@implementation SentryOptionsInternal + ++ (NSArray *)defaultIntegrationClasses +{ + // The order of integrations here is important. + // SentryCrashIntegration needs to be initialized before SentryAutoSessionTrackingIntegration. + // And SentrySessionReplayIntegration before SentryCrashIntegration. + NSMutableArray *defaultIntegrations = [NSMutableArray arrayWithObjects: +#if SENTRY_TARGET_REPLAY_SUPPORTED + [SentrySessionReplayIntegration class], +#endif // SENTRY_TARGET_REPLAY_SUPPORTED + [SentryCrashIntegration class], +#if SENTRY_HAS_UIKIT + [SentryAppStartTrackingIntegration class], [SentryFramesTrackingIntegration class], + [SentryPerformanceTrackingIntegration class], [SentryUIEventTrackingIntegration class], + [SentryViewHierarchyIntegration class], + [SentryWatchdogTerminationTrackingIntegration class], +#endif // SENTRY_HAS_UIKIT +#if SENTRY_TARGET_REPLAY_SUPPORTED + [SentryScreenshotIntegration class], +#endif // SENTRY_TARGET_REPLAY_SUPPORTED + [SentryANRTrackingIntegration class], [SentryAutoBreadcrumbTrackingIntegration class], + [SentryAutoSessionTrackingIntegration class], [SentryCoreDataTrackingIntegration class], + [SentryFileIOTrackingIntegration class], [SentryNetworkTrackingIntegration class], + [SentrySwiftAsyncIntegration class], nil]; + +#if TARGET_OS_IOS && SENTRY_HAS_UIKIT + if (@available(iOS 13.0, iOSApplicationExtension 13.0, *)) { + [defaultIntegrations addObject:[SentryUserFeedbackIntegration class]]; + } +#endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT + +#if SENTRY_HAS_METRIC_KIT + if (@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, *)) { + [defaultIntegrations addObject:[SentryMetricKitIntegration class]]; + } +#endif // SENTRY_HAS_METRIC_KIT + + return defaultIntegrations; +} + ++ (nullable SentryOptions *)initWithDict:(NSDictionary *)options + didFailWithError:(NSError *_Nullable *_Nullable)error +{ + SentryOptions *sentryOptions = [[SentryOptions alloc] init]; + if (![SentryOptionsInternal validateOptions:options + sentryOptions:sentryOptions + didFailWithError:error]) { + if (error != nil) { + SENTRY_LOG_ERROR(@"Failed to initialize SentryOptions: %@", *error); + } else { + SENTRY_LOG_ERROR(@"Failed to initialize SentryOptions"); + } + return nil; + } + return sentryOptions; +} + +/** + * Populates all @c SentryOptions values from @c options dict using fallbacks/defaults if needed. + */ ++ (BOOL)validateOptions:(NSDictionary *)options + sentryOptions:(SentryOptions *)sentryOptions + didFailWithError:(NSError *_Nullable *_Nullable)error +{ + NSPredicate *isNSString = [NSPredicate predicateWithBlock:^BOOL( + id object, NSDictionary *bindings) { return [object isKindOfClass:[NSString class]]; }]; + + [self setBool:options[@"debug"] block:^(BOOL value) { sentryOptions.debug = value; }]; + + if ([options[@"diagnosticLevel"] isKindOfClass:[NSString class]]) { + NSString *_Nonnull diagnosticLevel + = SENTRY_UNWRAP_NULLABLE(NSString, options[@"diagnosticLevel"]); + for (SentryLevel level = 0; level <= kSentryLevelFatal; level++) { + if ([nameForSentryLevel(level) isEqualToString:diagnosticLevel]) { + sentryOptions.diagnosticLevel = level; + break; + } + } + } + + if (options[@"dsn"] != [NSNull null]) { + NSString *dsn = @""; + if (nil != options[@"dsn"] && [options[@"dsn"] isKindOfClass:[NSString class]]) { + dsn = options[@"dsn"]; + } + + sentryOptions.parsedDsn = [[SentryDsn alloc] initWithString:dsn didFailWithError:error]; + if (sentryOptions.parsedDsn == nil) { + return NO; + } + } + + if ([options[@"release"] isKindOfClass:[NSString class]]) { + sentryOptions.releaseName = options[@"release"]; + } + + if ([options[@"environment"] isKindOfClass:[NSString class]]) { + NSString *_Nonnull environment = SENTRY_UNWRAP_NULLABLE(NSString, options[@"environment"]); + sentryOptions.environment = environment; + } + + if ([options[@"dist"] isKindOfClass:[NSString class]]) { + sentryOptions.dist = options[@"dist"]; + } + + [self setBool:options[@"enabled"] block:^(BOOL value) { sentryOptions.enabled = value; }]; + + if ([options[@"shutdownTimeInterval"] isKindOfClass:[NSNumber class]]) { + sentryOptions.shutdownTimeInterval = [options[@"shutdownTimeInterval"] doubleValue]; + } + + [self setBool:options[@"enableCrashHandler"] + block:^(BOOL value) { sentryOptions.enableCrashHandler = value; }]; + +#if TARGET_OS_OSX + [self setBool:options[@"enableUncaughtNSExceptionReporting"] + block:^(BOOL value) { sentryOptions.enableUncaughtNSExceptionReporting = value; }]; +#endif // TARGET_OS_OSX + +#if !TARGET_OS_WATCH + [self setBool:options[@"enableSigtermReporting"] + block:^(BOOL value) { sentryOptions.enableSigtermReporting = value; }]; +#endif // !TARGET_OS_WATCH + + if ([options[@"maxBreadcrumbs"] isKindOfClass:[NSNumber class]]) { + sentryOptions.maxBreadcrumbs = [options[@"maxBreadcrumbs"] unsignedIntValue]; + } + + [self setBool:options[@"enableNetworkBreadcrumbs"] + block:^(BOOL value) { sentryOptions.enableNetworkBreadcrumbs = value; }]; + + if ([options[@"maxCacheItems"] isKindOfClass:[NSNumber class]]) { + sentryOptions.maxCacheItems = [options[@"maxCacheItems"] unsignedIntValue]; + } + + if ([options[@"cacheDirectoryPath"] isKindOfClass:[NSString class]]) { + NSString *_Nonnull cacheDirectoryPath + = SENTRY_UNWRAP_NULLABLE(NSString, options[@"cacheDirectoryPath"]); + sentryOptions.cacheDirectoryPath = cacheDirectoryPath; + } + + if ([self isBlock:options[@"beforeSend"]]) { + sentryOptions.beforeSend = options[@"beforeSend"]; + } + + if ([self isBlock:options[@"beforeSendSpan"]]) { + sentryOptions.beforeSendSpan = options[@"beforeSendSpan"]; + } + + if ([self isBlock:options[@"beforeBreadcrumb"]]) { + sentryOptions.beforeBreadcrumb = options[@"beforeBreadcrumb"]; + } + + if ([self isBlock:options[@"beforeCaptureScreenshot"]]) { + sentryOptions.beforeCaptureScreenshot = options[@"beforeCaptureScreenshot"]; + } + + if ([self isBlock:options[@"beforeCaptureViewHierarchy"]]) { + sentryOptions.beforeCaptureViewHierarchy = options[@"beforeCaptureViewHierarchy"]; + } + + if ([self isBlock:options[@"onCrashedLastRun"]]) { + sentryOptions.onCrashedLastRun = options[@"onCrashedLastRun"]; + } + +#if !SDK_V9 + if ([options[@"integrations"] isKindOfClass:[NSArray class]]) { +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" + sentryOptions.integrations = + [[options[@"integrations"] filteredArrayUsingPredicate:isNSString] mutableCopy]; +# pragma clang diagnstic pop + } +#endif // !SDK_V9 + + if ([options[@"sampleRate"] isKindOfClass:[NSNumber class]]) { + sentryOptions.sampleRate = options[@"sampleRate"]; + } + + [self setBool:options[@"enableAutoSessionTracking"] + block:^(BOOL value) { sentryOptions.enableAutoSessionTracking = value; }]; + + [self setBool:options[@"enableGraphQLOperationTracking"] + block:^(BOOL value) { sentryOptions.enableGraphQLOperationTracking = value; }]; + + [self setBool:options[@"enableWatchdogTerminationTracking"] + block:^(BOOL value) { sentryOptions.enableWatchdogTerminationTracking = value; }]; + + [self setBool:options[@"swiftAsyncStacktraces"] + block:^(BOOL value) { sentryOptions.swiftAsyncStacktraces = value; }]; + + if ([options[@"sessionTrackingIntervalMillis"] isKindOfClass:[NSNumber class]]) { + sentryOptions.sessionTrackingIntervalMillis = + [options[@"sessionTrackingIntervalMillis"] unsignedIntValue]; + } + + [self setBool:options[@"attachStacktrace"] + block:^(BOOL value) { sentryOptions.attachStacktrace = value; }]; + + if ([options[@"maxAttachmentSize"] isKindOfClass:[NSNumber class]]) { + sentryOptions.maxAttachmentSize = [options[@"maxAttachmentSize"] unsignedIntValue]; + } + + [self setBool:options[@"sendDefaultPii"] + block:^(BOOL value) { sentryOptions.sendDefaultPii = value; }]; + + [self setBool:options[@"enableAutoPerformanceTracing"] + block:^(BOOL value) { sentryOptions.enableAutoPerformanceTracing = value; }]; + + [self setBool:options[@"enablePerformanceV2"] + block:^(BOOL value) { sentryOptions.enablePerformanceV2 = value; }]; + + [self setBool:options[@"enablePersistingTracesWhenCrashing"] + block:^(BOOL value) { sentryOptions.enablePersistingTracesWhenCrashing = value; }]; + + [self setBool:options[@"enableCaptureFailedRequests"] + block:^(BOOL value) { sentryOptions.enableCaptureFailedRequests = value; }]; + + [self setBool:options[@"enableTimeToFullDisplayTracing"] + block:^(BOOL value) { sentryOptions.enableTimeToFullDisplayTracing = value; }]; + + if ([self isBlock:options[@"initialScope"]]) { + sentryOptions.initialScope + = (SentryScope * (^_Nonnull)(SentryScope *)) options[@"initialScope"]; + } +#if SENTRY_HAS_UIKIT + [self setBool:options[@"enableUIViewControllerTracing"] + block:^(BOOL value) { sentryOptions.enableUIViewControllerTracing = value; }]; + + [self setBool:options[@"attachScreenshot"] + block:^(BOOL value) { sentryOptions.attachScreenshot = value; }]; + + [self setBool:options[@"attachViewHierarchy"] + block:^(BOOL value) { sentryOptions.attachViewHierarchy = value; }]; + + [self setBool:options[@"reportAccessibilityIdentifier"] + block:^(BOOL value) { sentryOptions.reportAccessibilityIdentifier = value; }]; + + [self setBool:options[@"enableUserInteractionTracing"] + block:^(BOOL value) { sentryOptions.enableUserInteractionTracing = value; }]; + + if ([options[@"idleTimeout"] isKindOfClass:[NSNumber class]]) { + sentryOptions.idleTimeout = [options[@"idleTimeout"] doubleValue]; + } + + [self setBool:options[@"enablePreWarmedAppStartTracing"] + block:^(BOOL value) { sentryOptions.enablePreWarmedAppStartTracing = value; }]; + +# if !SDK_V9 + [self setBool:options[@"enableAppHangTrackingV2"] + block:^(BOOL value) { sentryOptions.enableAppHangTrackingV2 = value; }]; +# endif // !SDK_V9 + + [self setBool:options[@"enableReportNonFullyBlockingAppHangs"] + block:^(BOOL value) { sentryOptions.enableReportNonFullyBlockingAppHangs = value; }]; + +#endif // SENTRY_HAS_UIKIT + +#if SENTRY_TARGET_REPLAY_SUPPORTED + if ([options[@"sessionReplay"] isKindOfClass:NSDictionary.class]) { + sentryOptions.sessionReplay = [[SentryReplayOptions alloc] + initWithDictionary:SENTRY_UNWRAP_NULLABLE(NSDictionary, options[@"sessionReplay"])]; + } +#endif // SENTRY_TARGET_REPLAY_SUPPORTED + + [self setBool:options[@"enableAppHangTracking"] + block:^(BOOL value) { sentryOptions.enableAppHangTracking = value; }]; + + if ([options[@"appHangTimeoutInterval"] isKindOfClass:[NSNumber class]]) { + sentryOptions.appHangTimeoutInterval = [options[@"appHangTimeoutInterval"] doubleValue]; + } + + [self setBool:options[@"enableNetworkTracking"] + block:^(BOOL value) { sentryOptions.enableNetworkTracking = value; }]; + + [self setBool:options[@"enableFileIOTracing"] + block:^(BOOL value) { sentryOptions.enableFileIOTracing = value; }]; + + if ([options[@"tracesSampleRate"] isKindOfClass:[NSNumber class]]) { + sentryOptions.tracesSampleRate = options[@"tracesSampleRate"]; + } + + if ([self isBlock:options[@"tracesSampler"]]) { + sentryOptions.tracesSampler = options[@"tracesSampler"]; + } +#if !SDK_V9 +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" + if ([options[@"enableTracing"] isKindOfClass:NSNumber.self]) { + sentryOptions.enableTracing = [options[@"enableTracing"] boolValue]; + } +# pragma clang diagnostic pop +#endif // !SDK_V9 + + if ([options[@"inAppIncludes"] isKindOfClass:[NSArray class]]) { + NSArray *inAppIncludes = + [options[@"inAppIncludes"] filteredArrayUsingPredicate:isNSString]; + for (NSString *include in inAppIncludes) { + [sentryOptions addInAppInclude:include]; + } + } + + if ([options[@"inAppExcludes"] isKindOfClass:[NSArray class]]) { + NSArray *inAppExcludes = + [options[@"inAppExcludes"] filteredArrayUsingPredicate:isNSString]; + for (NSString *exclude in inAppExcludes) { + [sentryOptions addInAppExclude:exclude]; + } + } + + if ([options[@"urlSession"] isKindOfClass:[NSURLSession class]]) { + sentryOptions.urlSession = options[@"urlSession"]; + } + + if ([options[@"urlSessionDelegate"] conformsToProtocol:@protocol(NSURLSessionDelegate)]) { + sentryOptions.urlSessionDelegate = options[@"urlSessionDelegate"]; + } + + [self setBool:options[@"enableSwizzling"] + block:^(BOOL value) { sentryOptions.enableSwizzling = value; }]; + + if ([options[@"swizzleClassNameExcludes"] isKindOfClass:[NSSet class]]) { + sentryOptions.swizzleClassNameExcludes = [SENTRY_UNWRAP_NULLABLE( + NSSet, options[@"swizzleClassNameExcludes"]) filteredSetUsingPredicate:isNSString]; + } + + [self setBool:options[@"enableCoreDataTracing"] + block:^(BOOL value) { sentryOptions.enableCoreDataTracing = value; }]; + +#if SENTRY_TARGET_PROFILING_SUPPORTED +# if !SDK_V9 + if ([options[@"profilesSampleRate"] isKindOfClass:[NSNumber class]]) { +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" + sentryOptions.profilesSampleRate = options[@"profilesSampleRate"]; +# pragma clang diagnostic pop + } + +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" + if ([self isBlock:options[@"profilesSampler"]]) { + sentryOptions.profilesSampler = options[@"profilesSampler"]; + } +# pragma clang diagnostic pop + +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" + [self setBool:options[@"enableProfiling"] + block:^(BOOL value) { sentryOptions.enableProfiling = value; }]; + + [self setBool:options[NSStringFromSelector(@selector(enableAppLaunchProfiling))] + block:^(BOOL value) { sentryOptions.enableAppLaunchProfiling = value; }]; +# pragma clang diagnostic pop +# endif // !SDK_V9 +#endif // SENTRY_TARGET_PROFILING_SUPPORTED + + [self setBool:options[@"sendClientReports"] + block:^(BOOL value) { sentryOptions.sendClientReports = value; }]; + + [self setBool:options[@"enableAutoBreadcrumbTracking"] + block:^(BOOL value) { sentryOptions.enableAutoBreadcrumbTracking = value; }]; + + if ([options[@"tracePropagationTargets"] isKindOfClass:[NSArray class]]) { + sentryOptions.tracePropagationTargets + = SENTRY_UNWRAP_NULLABLE(NSArray, options[@"tracePropagationTargets"]); + } + + if ([options[@"failedRequestStatusCodes"] isKindOfClass:[NSArray class]]) { + sentryOptions.failedRequestStatusCodes + = SENTRY_UNWRAP_NULLABLE(NSArray, options[@"failedRequestStatusCodes"]); + } + + if ([options[@"failedRequestTargets"] isKindOfClass:[NSArray class]]) { + sentryOptions.failedRequestTargets + = SENTRY_UNWRAP_NULLABLE(NSArray, options[@"failedRequestTargets"]); + } + +#if SENTRY_HAS_METRIC_KIT + if (@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, *)) { + [self setBool:options[@"enableMetricKit"] + block:^(BOOL value) { sentryOptions.enableMetricKit = value; }]; + [self setBool:options[@"enableMetricKitRawPayload"] + block:^(BOOL value) { sentryOptions.enableMetricKitRawPayload = value; }]; + } +#endif // SENTRY_HAS_METRIC_KIT + + [self setBool:options[@"enableSpotlight"] + block:^(BOOL value) { sentryOptions.enableSpotlight = value; }]; + + if ([options[@"spotlightUrl"] isKindOfClass:[NSString class]]) { + sentryOptions.spotlightUrl = SENTRY_UNWRAP_NULLABLE(NSString, options[@"spotlightUrl"]); + } + + if ([options[@"experimental"] isKindOfClass:NSDictionary.class]) { + [sentryOptions.experimental validateOptions:options[@"experimental"]]; + } + + return YES; +} + +/** + * Checks if the passed in block is actually of type block. We can't check if the block matches a + * specific block without some complex objc runtime method calls and therefore we only check if it's + * a block or not. Assigning a wrong block to the @c SentryOptions blocks still could lead to + * crashes at runtime, but when someone uses the @c initWithDict they should better know what they + * are doing. + * @see Taken from https://gist.github.com/steipete/6ee378bd7d87f276f6e0 + */ ++ (BOOL)isBlock:(nullable id)block +{ + static Class blockClass; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + blockClass = [^{ } class]; + while ([blockClass superclass] != NSObject.class) { + blockClass = [blockClass superclass]; + } + }); + + return [block isKindOfClass:blockClass]; +} + ++ (void)setBool:(id)value block:(void (^)(BOOL))block +{ + // Entries in the dictionary can be NSNull. Especially, on React-Native, this can happen. + if (value != nil && ![value isEqual:[NSNull null]]) { + block([value boolValue]); + } +} + +@end diff --git a/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h b/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h index 9b501ec314b..e2e6bdcc68e 100644 --- a/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h +++ b/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h @@ -56,6 +56,7 @@ typedef void (^SentryOnAppStartMeasurementAvailable)( */ + (nullable SentryEnvelope *)envelopeWithData:(NSData *)data; +#if !SDK_V9 /** * Returns the current list of debug images. Be aware that the @c SentryDebugMeta is actually * describing a debug image. @@ -73,6 +74,7 @@ typedef void (^SentryOnAppStartMeasurementAvailable)( * crash, each image's data section crash info is also included. */ + (NSArray *)getDebugImagesCrashed:(BOOL)isCrash; +#endif // !SDK_V9 /** * Override SDK information. @@ -186,7 +188,7 @@ typedef void (^SentryOnAppStartMeasurementAvailable)( /** * Allow Hybrids SDKs to set the current Screen. */ -+ (void)setCurrentScreen:(NSString *)screenName; ++ (void)setCurrentScreen:(NSString *_Nullable)screenName; #endif // SENTRY_UIKIT_AVAILABLE diff --git a/Sources/Sentry/include/HybridPublic/SentryBinaryImageCache.h b/Sources/Sentry/include/HybridPublic/SentryBinaryImageCache.h deleted file mode 100644 index d555c2ef1db..00000000000 --- a/Sources/Sentry/include/HybridPublic/SentryBinaryImageCache.h +++ /dev/null @@ -1,35 +0,0 @@ -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryBinaryImageInfo : NSObject -@property (nonatomic, strong) NSString *name; -@property (nonatomic, copy) NSString *UUID; -@property (nonatomic) uint64_t vmAddress; -@property (nonatomic) uint64_t address; -@property (nonatomic) uint64_t size; - -@end - -/** - * This class listens to `SentryCrashBinaryImageCache` to keep a copy of the loaded binaries - * information in a sorted collection that will be used to symbolicate frames with better - * performance. - */ -@interface SentryBinaryImageCache : NSObject - -- (void)start; - -- (void)stop; - -- (NSArray *)getAllBinaryImages; - -- (nullable SentryBinaryImageInfo *)imageByAddress:(const uint64_t)address; - -- (NSSet *)imagePathsForInAppInclude:(NSString *)inAppInclude; - -+ (NSString *_Nullable)convertUUID:(const unsigned char *const)value; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/HybridPublic/SentryDebugImageProvider+HybridSDKs.h b/Sources/Sentry/include/HybridPublic/SentryDebugImageProvider+HybridSDKs.h index 242e1987a9b..793468086eb 100644 --- a/Sources/Sentry/include/HybridPublic/SentryDebugImageProvider+HybridSDKs.h +++ b/Sources/Sentry/include/HybridPublic/SentryDebugImageProvider+HybridSDKs.h @@ -4,13 +4,21 @@ # import "SentryDebugImageProvider.h" #endif +#import + @class SentryDebugMeta; @class SentryThread; @class SentryFrame; NS_ASSUME_NONNULL_BEGIN +#if SDK_V9 +@interface SentryDebugImageProvider : NSObject +#else @interface SentryDebugImageProvider () +#endif + +- (instancetype)init; /** * Returns a list of debug images that are being referenced by the given frames. diff --git a/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h b/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h index 927b1cc8ff0..59500c116bf 100644 --- a/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h +++ b/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h @@ -13,11 +13,10 @@ @class SentryDispatchQueueWrapper; @class SentryExtraContextProvider; @class SentryFileManager; -@class SentryNSNotificationCenterWrapper; -@class SentryNSProcessInfoWrapper; @class SentryNSTimerFactory; @class SentrySwizzleWrapper; @class SentrySysctl; +@class SentryThreadsafeApplication; @class SentrySystemWrapper; @class SentryThreadWrapper; @class SentryThreadInspector; @@ -28,11 +27,14 @@ @class SentryGlobalEventProcessor; @protocol SentryANRTracker; -@protocol SentryRandom; +@protocol SentryRandomProtocol; @protocol SentryCurrentDateProvider; @protocol SentryRateLimits; @protocol SentryApplication; +@protocol SentryProcessInfoSource; @protocol SentryDispatchQueueProviderProtocol; +@protocol SentryNSNotificationCenterWrapper; +@protocol SentryObjCRuntimeWrapper; #if SENTRY_HAS_METRIC_KIT @class SentryMXManager; @@ -40,8 +42,7 @@ #if SENTRY_UIKIT_AVAILABLE @class SentryFramesTracker; -@class SentryScreenshot; -@class SentryUIApplication; +@class SentryScreenshotSource; @class SentryViewHierarchyProvider; @class SentryUIViewControllerPerformanceTracker; @class SentryWatchdogTerminationScopeObserver; @@ -50,7 +51,7 @@ #endif // SENTRY_UIKIT_AVAILABLE #if SENTRY_HAS_UIKIT -@class SentryUIDeviceWrapper; +@protocol SentryUIDeviceWrapper; #endif // TARGET_OS_IOS #if !TARGET_OS_WATCH @@ -82,24 +83,25 @@ SENTRY_NO_INIT #pragma mark - Init Dependencies @property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueueWrapper; -@property (nonatomic, strong) id random; +@property (nonatomic, strong) id random; @property (nonatomic, strong) SentryThreadWrapper *threadWrapper; @property (nonatomic, strong) SentryBinaryImageCache *binaryImageCache; @property (nonatomic, strong) id dateProvider; @property (nonatomic, strong) SentryExtraContextProvider *extraContextProvider; -@property (nonatomic, strong) SentryNSNotificationCenterWrapper *notificationCenterWrapper; +@property (nonatomic, strong) id notificationCenterWrapper; @property (nonatomic, strong) SentryCrashWrapper *crashWrapper; -@property (nonatomic, strong) SentryNSProcessInfoWrapper *processInfoWrapper; +@property (nonatomic, strong) id processInfoWrapper; @property (nonatomic, strong) SentrySysctl *sysctlWrapper; @property (nonatomic, strong) id rateLimits; @property (nonatomic, strong) id application; +@property (nonatomic, strong) SentryThreadsafeApplication *threadsafeApplication; #if SENTRY_HAS_REACHABILITY @property (nonatomic, strong) SentryReachability *reachability; #endif // !TARGET_OS_WATCH #if SENTRY_HAS_UIKIT -@property (nonatomic, strong) SentryUIDeviceWrapper *uiDeviceWrapper; +@property (nonatomic, strong) id uiDeviceWrapper; #endif // TARGET_OS_IOS #pragma mark - Lazy Dependencies @@ -117,24 +119,29 @@ SENTRY_NO_INIT - (id)getANRTracker:(NSTimeInterval)timeout isV2Enabled:(BOOL)isV2Enabled; #endif // SENTRY_HAS_UIKIT +#if SENTRY_TARGET_PROFILING_SUPPORTED @property (nonatomic, strong) SentrySystemWrapper *systemWrapper; +#endif // SENTRY_TARGET_PROFILING_SUPPORTED @property (nonatomic, strong) SentryDispatchFactory *dispatchFactory; -@property (nonatomic, strong) id dispatchQueueProvider; @property (nonatomic, strong) SentryNSTimerFactory *timerFactory; @property (nonatomic, strong) SentrySwizzleWrapper *swizzleWrapper; #if SENTRY_UIKIT_AVAILABLE @property (nonatomic, strong) SentryFramesTracker *framesTracker; -@property (nonatomic, strong) SentryScreenshot *screenshot; @property (nonatomic, strong) SentryViewHierarchyProvider *viewHierarchyProvider; @property (nonatomic, strong) SentryUIViewControllerPerformanceTracker *uiViewControllerPerformanceTracker; #endif // SENTRY_UIKIT_AVAILABLE +#if SENTRY_TARGET_REPLAY_SUPPORTED +@property (nonatomic, strong) SentryScreenshotSource *screenshotSource; +#endif // SENTRY_TARGET_REPLAY_SUPPORTED + #if SENTRY_HAS_METRIC_KIT @property (nonatomic, strong) SentryMXManager *metricKitManager API_AVAILABLE( ios(15.0), macos(12.0), macCatalyst(15.0)) API_UNAVAILABLE(tvos, watchos); #endif // SENTRY_HAS_METRIC_KIT +@property (nonatomic, strong) id objcRuntimeWrapper; #if SENTRY_HAS_UIKIT - (SentryWatchdogTerminationScopeObserver *)getWatchdogTerminationScopeObserverWithOptions: diff --git a/Sources/Sentry/include/HybridPublic/SentryEnvelope.h b/Sources/Sentry/include/HybridPublic/SentryEnvelope.h deleted file mode 100644 index 4b8af9921a5..00000000000 --- a/Sources/Sentry/include/HybridPublic/SentryEnvelope.h +++ /dev/null @@ -1,177 +0,0 @@ -#if __has_include() -# import -#else -# import "PrivatesHeader.h" -#endif - -#if COCOAPODS -@class SentrySdkInfo; -#else - -# if __has_include() -# import -# else -# import "SentrySdkInfo.h" -# endif - -#endif - -@class SentryAttachment; -@class SentryEnvelopeItemHeader; -@class SentryEvent; -@class SentryFeedback; -@class SentryId; -@class SentrySession; -@class SentryTraceContext; -@class SentryUserFeedback; - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryEnvelopeHeader : NSObject -SENTRY_NO_INIT - -/** - * Initializes an @c SentryEnvelopeHeader object with the specified eventId. - * @note Sets the @c sdkInfo from @c SentryMeta. - * @param eventId The identifier of the event. Can be nil if no event in the envelope or attachment - * related to event. - */ -- (instancetype)initWithId:(SentryId *_Nullable)eventId; - -/** - * Initializes a @c SentryEnvelopeHeader object with the specified @c eventId and @c traceContext. - * @param eventId The identifier of the event. Can be @c nil if no event in the envelope or - * attachment related to event. - * @param traceContext Current trace state. - */ -- (instancetype)initWithId:(nullable SentryId *)eventId - traceContext:(nullable SentryTraceContext *)traceContext; - -/** - * Initializes a @c SentryEnvelopeHeader object with the specified @c eventId, @c skdInfo and - * @c traceContext. It is recommended to use @c initWithId:traceContext: because it sets the - * @c sdkInfo for you. - * @param eventId The identifier of the event. Can be @c nil if no event in the envelope or - * attachment related to event. - * @param sdkInfo Describes the Sentry SDK. Can be @c nil for backwards compatibility. New - * instances should always provide a version. - * @param traceContext Current trace state. - */ -- (instancetype)initWithId:(nullable SentryId *)eventId - sdkInfo:(nullable SentrySdkInfo *)sdkInfo - traceContext:(nullable SentryTraceContext *)traceContext NS_DESIGNATED_INITIALIZER; - -/** - * The event identifier, if available. - * An event id exist if the envelope contains an event of items within it are related. i.e - * Attachments - */ -@property (nullable, nonatomic, readonly, copy) SentryId *eventId; - -@property (nullable, nonatomic, readonly, copy) SentrySdkInfo *sdkInfo; - -@property (nullable, nonatomic, readonly, copy) SentryTraceContext *traceContext; - -/** - * The timestamp when the event was sent from the SDK as string in RFC 3339 format. Used - * for clock drift correction of the event timestamp. The time zone must be UTC. - * - * The timestamp should be generated as close as possible to the transmision of the event, - * so that the delay between sending the envelope and receiving it on the server-side is - * minimized. - */ -@property (nullable, nonatomic, copy) NSDate *sentAt; - -+ (instancetype)empty; - -@end - -@interface SentryEnvelopeItem : NSObject -SENTRY_NO_INIT - -- (instancetype)initWithEvent:(SentryEvent *)event; -- (instancetype)initWithSession:(SentrySession *)session; - -#if !SDK_V9 -/** - * @deprecated Building the envelopes for the new @c SentryFeedback type is done directly in @c - * -[SentryClient @c captureFeedback:withScope:] - */ -- (instancetype)initWithUserFeedback:(SentryUserFeedback *)userFeedback - DEPRECATED_MSG_ATTRIBUTE( - "Building the envelopes for the new SentryFeedback type is done directly in -[SentryClient " - "captureFeedback:withScope:] so there will be no analog to this initializer for " - "SentryFeedback at this time.."); -#endif // !SDK_V9 -- (_Nullable instancetype)initWithAttachment:(SentryAttachment *)attachment - maxAttachmentSize:(NSUInteger)maxAttachmentSize; -- (instancetype)initWithHeader:(SentryEnvelopeItemHeader *)header - data:(NSData *)data NS_DESIGNATED_INITIALIZER; - -/** - * The envelope item header. - */ -@property (nonatomic, readonly, strong) SentryEnvelopeItemHeader *header; - -/** - * The envelope payload. - */ -@property (nonatomic, readonly, strong) NSData *data; - -@end - -@interface SentryEnvelope : NSObject -SENTRY_NO_INIT - -// If no event, or no data related to event, id will be null -- (instancetype)initWithId:(SentryId *_Nullable)id singleItem:(SentryEnvelopeItem *)item; - -- (instancetype)initWithHeader:(SentryEnvelopeHeader *)header singleItem:(SentryEnvelopeItem *)item; - -// If no event, or no data related to event, id will be null -- (instancetype)initWithId:(SentryId *_Nullable)id items:(NSArray *)items; - -/** - * Initializes a @c SentryEnvelope with a single session. - * @param session to init the envelope with. - */ -- (instancetype)initWithSession:(SentrySession *)session; - -/** - * Initializes a @c SentryEnvelope with a list of sessions. - * Can be used when an operation that starts a session closes an ongoing session. - * @param sessions to init the envelope with. - */ -- (instancetype)initWithSessions:(NSArray *)sessions; - -- (instancetype)initWithHeader:(SentryEnvelopeHeader *)header - items:(NSArray *)items NS_DESIGNATED_INITIALIZER; - -/** - * Convenience init for a single event. - */ -- (instancetype)initWithEvent:(SentryEvent *)event; - -#if !SDK_V9 -/** - * @deprecated Building the envelopes for the new @c SentryFeedback type is done directly in @c - * -[SentryClient @c captureFeedback:withScope:] - */ -- (instancetype)initWithUserFeedback:(SentryUserFeedback *)userFeedback - DEPRECATED_MSG_ATTRIBUTE("Building the envelopes for the new SentryFeedback type is done " - "directly in -[SentryClient captureFeedback:withScope:]."); -#endif // !SDK_V9 - -/** - * The envelope header. - */ -@property (nonatomic, readonly, strong) SentryEnvelopeHeader *header; - -/** - * The envelope items. - */ -@property (nonatomic, readonly, strong) NSArray *items; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/HybridPublic/SentryEnvelopeItemType.h b/Sources/Sentry/include/HybridPublic/SentryEnvelopeItemType.h deleted file mode 100644 index 24d150ad9ed..00000000000 --- a/Sources/Sentry/include/HybridPublic/SentryEnvelopeItemType.h +++ /dev/null @@ -1,18 +0,0 @@ -// each item type must have a data category name mapped to it; see SentryDataCategoryMapper - -// While these envelope item types might look similar to the data categories, they are not -// identical, and have slight differences. Just open them side by side and you'll see the -// differences. -static NSString *const SentryEnvelopeItemTypeEvent = @"event"; -static NSString *const SentryEnvelopeItemTypeSession = @"session"; -#if !SDK_V9 -static NSString *const SentryEnvelopeItemTypeUserFeedback = @"user_report"; -#endif // !SDK_V9 -static NSString *const SentryEnvelopeItemTypeFeedback = @"feedback"; -static NSString *const SentryEnvelopeItemTypeTransaction = @"transaction"; -static NSString *const SentryEnvelopeItemTypeAttachment = @"attachment"; -static NSString *const SentryEnvelopeItemTypeClientReport = @"client_report"; -static NSString *const SentryEnvelopeItemTypeProfile = @"profile"; -static NSString *const SentryEnvelopeItemTypeReplayVideo = @"replay_video"; -static NSString *const SentryEnvelopeItemTypeStatsd = @"statsd"; -static NSString *const SentryEnvelopeItemTypeProfileChunk = @"profile_chunk"; diff --git a/Sources/Sentry/include/HybridPublic/SentryFramesTracker.h b/Sources/Sentry/include/HybridPublic/SentryFramesTracker.h index 54468a529bb..3fb476fa324 100644 --- a/Sources/Sentry/include/HybridPublic/SentryFramesTracker.h +++ b/Sources/Sentry/include/HybridPublic/SentryFramesTracker.h @@ -15,7 +15,7 @@ @class SentryDisplayLinkWrapper; @protocol SentryCurrentDateProvider; @class SentryDispatchQueueWrapper; -@class SentryNSNotificationCenterWrapper; +@protocol SentryNSNotificationCenterWrapper; @class SentryScreenFrames; @class SentryFramesDelayResult; @@ -43,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithDisplayLinkWrapper:(SentryDisplayLinkWrapper *)displayLinkWrapper dateProvider:(id)dateProvider dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper - notificationCenter:(SentryNSNotificationCenterWrapper *)notificationCenter + notificationCenter:(id)notificationCenter keepDelayedFramesDuration:(CFTimeInterval)keepDelayedFramesDuration; - (SentryScreenFrames *)currentFrames; diff --git a/Sources/Sentry/include/HybridPublic/SentryOptions+HybridSDKs.h b/Sources/Sentry/include/HybridPublic/SentryOptions+HybridSDKs.h deleted file mode 100644 index 9709ca7c4ba..00000000000 --- a/Sources/Sentry/include/HybridPublic/SentryOptions+HybridSDKs.h +++ /dev/null @@ -1,16 +0,0 @@ -#if __has_include() -# import -#else -# import "SentryOptions.h" -#endif - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryOptions () - -- (_Nullable instancetype)initWithDict:(NSDictionary *)options - didFailWithError:(NSError *_Nullable *_Nullable)error; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/HybridPublic/SentryOptionsInternal.h b/Sources/Sentry/include/HybridPublic/SentryOptionsInternal.h new file mode 100644 index 00000000000..205f32074ee --- /dev/null +++ b/Sources/Sentry/include/HybridPublic/SentryOptionsInternal.h @@ -0,0 +1,16 @@ +#import + +@class SentryOptions; + +NS_ASSUME_NONNULL_BEGIN + +@interface SentryOptionsInternal : NSObject + +@property (nonatomic, readonly, class) NSArray *defaultIntegrationClasses; + ++ (nullable SentryOptions *)initWithDict:(NSDictionary *)options + didFailWithError:(NSError *_Nullable *_Nullable)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryAppState.h b/Sources/Sentry/include/SentryAppState.h deleted file mode 100644 index c5d2ba812dc..00000000000 --- a/Sources/Sentry/include/SentryAppState.h +++ /dev/null @@ -1,52 +0,0 @@ -#import "SentryDefines.h" -#import "SentrySerializable.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryAppState : NSObject -SENTRY_NO_INIT - -- (instancetype)initWithReleaseName:(nullable NSString *)releaseName - osVersion:(NSString *)osVersion - vendorId:(NSString *)vendorId - isDebugging:(BOOL)isDebugging - systemBootTimestamp:(NSDate *)systemBootTimestamp; - -/** - * Initializes @c SentryAppState from a JSON object. - * @param jsonObject The @c jsonObject containing the session. - * @return The @c SentrySession or @c nil if @c jsonObject contains an error. - */ -- (nullable instancetype)initWithJSONObject:(NSDictionary *)jsonObject; - -@property (nullable, readonly, nonatomic, copy) NSString *releaseName; - -@property (readonly, nonatomic, copy) NSString *osVersion; - -@property (readonly, nonatomic, copy) NSString *vendorId; - -@property (readonly, nonatomic, assign) BOOL isDebugging; - -/** - * The boot time of the system rounded down to seconds. As the precision of the serialization is - * only milliseconds and a precision of seconds is enough we round down to seconds. With this we - * avoid getting different dates before and after serialization. - * - * @warning We must not send this information off device because Apple forbids that. - * We are allowed send the amount of time that has elapsed between events that occurred within the - * app though. For more information see - * https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api#4278394. - */ -@property (readonly, nonatomic, copy) NSDate *systemBootTimestamp; - -@property (nonatomic, assign) BOOL isActive; - -@property (nonatomic, assign) BOOL wasTerminated; - -@property (nonatomic, assign) BOOL isANROngoing; - -@property (nonatomic, assign) BOOL isSDKRunning; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryAppStateManager.h b/Sources/Sentry/include/SentryAppStateManager.h index dcb2e459e22..877dd941486 100644 --- a/Sources/Sentry/include/SentryAppStateManager.h +++ b/Sources/Sentry/include/SentryAppStateManager.h @@ -4,9 +4,10 @@ @class SentryCrashWrapper; @class SentryDispatchQueueWrapper; @class SentryFileManager; -@class SentryNSNotificationCenterWrapper; @class SentryOptions; +@protocol SentryNSNotificationCenterWrapper; + NS_ASSUME_NONNULL_BEGIN @interface SentryAppStateManager : NSObject @@ -18,7 +19,7 @@ SENTRY_NO_INIT crashWrapper:(SentryCrashWrapper *)crashWrapper fileManager:(SentryFileManager *)fileManager dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper - notificationCenterWrapper:(SentryNSNotificationCenterWrapper *)notificationCenterWrapper; + notificationCenterWrapper:(id)notificationCenterWrapper; #if SENTRY_HAS_UIKIT @@ -35,7 +36,7 @@ SENTRY_NO_INIT */ - (SentryAppState *)buildCurrentAppState; -- (SentryAppState *)loadPreviousAppState; +- (nullable SentryAppState *)loadPreviousAppState; - (void)storeCurrentAppState; diff --git a/Sources/Sentry/include/SentryApplication.h b/Sources/Sentry/include/SentryApplication.h deleted file mode 100644 index 6465b5e48ca..00000000000 --- a/Sources/Sentry/include/SentryApplication.h +++ /dev/null @@ -1,62 +0,0 @@ -#import "SentryDefines.h" -#import - -@protocol SentryApplication; - -#if SENTRY_HAS_UIKIT -@class UIApplication; -@class UIScene; -@class UIWindow; -@class UIViewController; -@protocol UIApplicationDelegate; - -# import -#endif - -typedef NS_ENUM(NSInteger, UIApplicationState); - -NS_ASSUME_NONNULL_BEGIN - -/** - * Protocol used to provide cross-platform access to the application. - */ -@protocol SentryApplication - -// MARK: - Shared methods - -- (BOOL)isActive; - -// MARK: - UIKit-specific methods - -#if SENTRY_HAS_UIKIT -/** - * Returns the application state available at @c UIApplication.sharedApplication.applicationState - */ -@property (nonatomic, readonly) UIApplicationState applicationState; - -/** - * All windows connected to scenes. - */ -@property (nonatomic, readonly, nullable) NSArray *windows; - -/** - * Retrieves the application delegate for given UIApplication - */ -- (nullable id)getApplicationDelegate:(UIApplication *)application; - -/** - * Retrieves connected scenes for given UIApplication - */ -- (NSArray *)getApplicationConnectedScenes:(UIApplication *)application - API_AVAILABLE(ios(13.0), tvos(13.0)); - -/** - * Use @c [SentryUIApplication relevantViewControllers] and convert the - * result to a string array with the class name of each view controller. - */ -- (nullable NSArray *)relevantViewControllersNames; -#endif // SENTRY_HAS_UIKIT - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/NSArray+SentrySanitize.h b/Sources/Sentry/include/SentryArray.h similarity index 100% rename from Sources/Sentry/include/NSArray+SentrySanitize.h rename to Sources/Sentry/include/SentryArray.h diff --git a/Sources/Sentry/include/SentryAsyncLog.h b/Sources/Sentry/include/SentryAsyncLog.h index 1626e1a417f..c460fe24564 100644 --- a/Sources/Sentry/include/SentryAsyncLog.h +++ b/Sources/Sentry/include/SentryAsyncLog.h @@ -21,4 +21,4 @@ NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END -#endif // SentryAsyncLog_h \ No newline at end of file +#endif // SentryAsyncLog_h diff --git a/Sources/Sentry/include/SentryBinaryImageCacheCallbacks.h b/Sources/Sentry/include/SentryBinaryImageCacheCallbacks.h new file mode 100644 index 00000000000..c966ef3e076 --- /dev/null +++ b/Sources/Sentry/include/SentryBinaryImageCacheCallbacks.h @@ -0,0 +1,14 @@ +#import "SentryCrashDynamicLinker.h" +#import + +#ifdef __cplusplus +extern "C" { +#endif + +void binaryImageWasAdded(const SentryCrashBinaryImage *_Nullable image); + +void binaryImageWasRemoved(const SentryCrashBinaryImage *_Nullable image); + +#ifdef __cplusplus +} +#endif diff --git a/Sources/Sentry/include/SentryClient+Logs.h b/Sources/Sentry/include/SentryClient+Logs.h new file mode 100644 index 00000000000..b25c951d5a0 --- /dev/null +++ b/Sources/Sentry/include/SentryClient+Logs.h @@ -0,0 +1,14 @@ +#import "SentryClient.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface SentryClient () + +/** + * Helper to capture encoded logs, as SentryEnvelope can't be used in the Swift SDK. + */ +- (void)captureLogsData:(NSData *)data with:(NSNumber *)itemCount; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryClient+Private.h b/Sources/Sentry/include/SentryClient+Private.h index 30085282ff3..9507886100d 100644 --- a/Sources/Sentry/include/SentryClient+Private.h +++ b/Sources/Sentry/include/SentryClient+Private.h @@ -41,6 +41,11 @@ NS_ASSUME_NONNULL_BEGIN withSession:(SentrySession *)session withScope:(SentryScope *)scope; +- (void)captureSerializedFeedback:(NSDictionary *)serializedFeedback + withEventId:(NSString *)feedbackEventId + attachments:(NSArray *)feedbackAttachments + scope:(SentryScope *)scope; + - (void)saveCrashTransaction:(SentryTransaction *)transaction withScope:(SentryScope *)scope NS_SWIFT_NAME(saveCrashTransaction(transaction:scope:)); diff --git a/Sources/Sentry/include/SentryClientReport.h b/Sources/Sentry/include/SentryClientReport.h deleted file mode 100644 index 30d4a3044d0..00000000000 --- a/Sources/Sentry/include/SentryClientReport.h +++ /dev/null @@ -1,22 +0,0 @@ -#import "SentrySerializable.h" -#import - -@class SentryDiscardedEvent; - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryClientReport : NSObject -SENTRY_NO_INIT - -- (instancetype)initWithDiscardedEvents:(NSArray *)discardedEvents; - -/** - * The timestamp of when the client report was created. - */ -@property (nonatomic, strong, readonly) NSDate *timestamp; - -@property (nonatomic, strong, readonly) NSArray *discardedEvents; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryConcurrentRateLimitsDictionary.h b/Sources/Sentry/include/SentryConcurrentRateLimitsDictionary.h index b6ea0889261..b5e713fe1f6 100644 --- a/Sources/Sentry/include/SentryConcurrentRateLimitsDictionary.h +++ b/Sources/Sentry/include/SentryConcurrentRateLimitsDictionary.h @@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)addRateLimit:(SentryDataCategory)category validUntil:(NSDate *)date; /** Returns the date until the rate limit is active. */ -- (NSDate *)getRateLimitForCategory:(SentryDataCategory)category; +- (nullable NSDate *)getRateLimitForCategory:(SentryDataCategory)category; @end diff --git a/Sources/Sentry/include/SentryCoreDataTracker.h b/Sources/Sentry/include/SentryCoreDataTracker.h index 5b4e415cc38..19bdf58a0da 100644 --- a/Sources/Sentry/include/SentryCoreDataTracker.h +++ b/Sources/Sentry/include/SentryCoreDataTracker.h @@ -3,14 +3,14 @@ NS_ASSUME_NONNULL_BEGIN -@class SentryNSProcessInfoWrapper; +@protocol SentryProcessInfoSource; @class SentryThreadInspector; @interface SentryCoreDataTracker : NSObject SENTRY_NO_INIT - (instancetype)initWithThreadInspector:(SentryThreadInspector *)threadInspector - processInfoWrapper:(SentryNSProcessInfoWrapper *)processInfoWrapper; + processInfoWrapper:(id)processInfoWrapper; - (NSArray *)managedObjectContext:(NSManagedObjectContext *)context executeFetchRequest:(NSFetchRequest *)request diff --git a/Sources/SentryCrash/Recording/SentryCrash.h b/Sources/Sentry/include/SentryCrash.h similarity index 99% rename from Sources/SentryCrash/Recording/SentryCrash.h rename to Sources/Sentry/include/SentryCrash.h index fe924aa82e3..b2604595ee3 100644 --- a/Sources/SentryCrash/Recording/SentryCrash.h +++ b/Sources/Sentry/include/SentryCrash.h @@ -45,8 +45,6 @@ typedef enum { static NSString *const SENTRYCRASH_REPORT_ATTACHMENTS_ITEM = @"attachments"; -@class SentryNSNotificationCenterWrapper; - /** * Reports any crashes that occur in the application. * diff --git a/Sources/SentryCrash/Recording/SentryCrashBinaryImageCache.h b/Sources/Sentry/include/SentryCrashBinaryImageCache.h similarity index 94% rename from Sources/SentryCrash/Recording/SentryCrashBinaryImageCache.h rename to Sources/Sentry/include/SentryCrashBinaryImageCache.h index 4c8ee11db31..01fbe576b54 100644 --- a/Sources/SentryCrash/Recording/SentryCrashBinaryImageCache.h +++ b/Sources/Sentry/include/SentryCrashBinaryImageCache.h @@ -4,6 +4,10 @@ #include "SentryCrashDynamicLinker.h" #include +#ifdef __cplusplus +extern "C" { +#endif + typedef void (*sentrycrashbic_imageIteratorCallback)(SentryCrashBinaryImage *, void *context); typedef void (*sentrycrashbic_cacheChangeCallback)(const SentryCrashBinaryImage *binaryImage); @@ -33,4 +37,8 @@ void sentrycrashbic_registerAddedCallback(sentrycrashbic_cacheChangeCallback cal */ void sentrycrashbic_registerRemovedCallback(sentrycrashbic_cacheChangeCallback callback); +#ifdef __cplusplus +} +#endif + #endif /* SentryCrashBinaryImageCache_h */ diff --git a/Sources/Sentry/include/SentryCrashBinaryImageProvider.h b/Sources/Sentry/include/SentryCrashBinaryImageProvider.h index ee3c16ae892..293d0565a7a 100644 --- a/Sources/Sentry/include/SentryCrashBinaryImageProvider.h +++ b/Sources/Sentry/include/SentryCrashBinaryImageProvider.h @@ -1,5 +1,7 @@ -#import "SentryCrashDynamicLinker.h" -#import +#if !SDK_V9 + +# import "SentryCrashDynamicLinker.h" +# import NS_ASSUME_NONNULL_BEGIN @@ -21,3 +23,5 @@ NS_ASSUME_NONNULL_BEGIN @end NS_ASSUME_NONNULL_END + +#endif // !SDK_V9 diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashDebug.h b/Sources/Sentry/include/SentryCrashDebug.h similarity index 100% rename from Sources/SentryCrash/Recording/Tools/SentryCrashDebug.h rename to Sources/Sentry/include/SentryCrashDebug.h diff --git a/Sources/Sentry/include/SentryCrashDefaultBinaryImageProvider.h b/Sources/Sentry/include/SentryCrashDefaultBinaryImageProvider.h index 343cec1ab98..12aff9832aa 100644 --- a/Sources/Sentry/include/SentryCrashDefaultBinaryImageProvider.h +++ b/Sources/Sentry/include/SentryCrashDefaultBinaryImageProvider.h @@ -1,5 +1,6 @@ -#import "SentryCrashBinaryImageProvider.h" -#import +#if !SDK_V9 +# import "SentryCrashBinaryImageProvider.h" +# import NS_ASSUME_NONNULL_BEGIN @@ -8,3 +9,5 @@ NS_ASSUME_NONNULL_BEGIN @end NS_ASSUME_NONNULL_END + +#endif // !SDK_V9 diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashDynamicLinker.h b/Sources/Sentry/include/SentryCrashDynamicLinker.h similarity index 99% rename from Sources/SentryCrash/Recording/Tools/SentryCrashDynamicLinker.h rename to Sources/Sentry/include/SentryCrashDynamicLinker.h index 7b23e287784..faf8fb529c2 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashDynamicLinker.h +++ b/Sources/Sentry/include/SentryCrashDynamicLinker.h @@ -28,14 +28,14 @@ #ifndef HDR_SentryCrashDynamicLinker_h #define HDR_SentryCrashDynamicLinker_h -#ifdef __cplusplus -extern "C" { -#endif - #include #include #include +#ifdef __cplusplus +extern "C" { +#endif + #define SENTRY_DYLD_INDEX UINT_MAX - 1 #if __LP64__ @@ -63,6 +63,7 @@ typedef struct { uintptr_t size; } SentrySegmentAddress; +#if !SDK_V9 /** Get the number of loaded binary images. */ int sentrycrashdl_imageCount(void); @@ -76,6 +77,7 @@ int sentrycrashdl_imageCount(void); * @return True if the image was successfully queried. */ bool sentrycrashdl_getBinaryImage(int index, SentryCrashBinaryImage *buffer, bool isCrash); +#endif // !SDK_V9 /** Get information about a binary image based on mach_header. * diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor.h b/Sources/Sentry/include/SentryCrashMonitor.h similarity index 100% rename from Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor.h rename to Sources/Sentry/include/SentryCrashMonitor.h diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitorType.h b/Sources/Sentry/include/SentryCrashMonitorType.h similarity index 100% rename from Sources/SentryCrash/Recording/Monitors/SentryCrashMonitorType.h rename to Sources/Sentry/include/SentryCrashMonitorType.h diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_AppState.h b/Sources/Sentry/include/SentryCrashMonitor_AppState.h similarity index 100% rename from Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_AppState.h rename to Sources/Sentry/include/SentryCrashMonitor_AppState.h index e00da4e74d0..2fe1eb87575 100644 --- a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_AppState.h +++ b/Sources/Sentry/include/SentryCrashMonitor_AppState.h @@ -32,14 +32,14 @@ #ifndef HDR_SentryCrashMonitor_AppState_h #define HDR_SentryCrashMonitor_AppState_h -#ifdef __cplusplus -extern "C" { -#endif - #include "SentryCrashMonitor.h" #include +#ifdef __cplusplus +extern "C" { +#endif + typedef struct { // Saved data diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_System.h b/Sources/Sentry/include/SentryCrashMonitor_System.h similarity index 100% rename from Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_System.h rename to Sources/Sentry/include/SentryCrashMonitor_System.h index 51f4630d43a..6aef870caa0 100644 --- a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_System.h +++ b/Sources/Sentry/include/SentryCrashMonitor_System.h @@ -28,13 +28,13 @@ #ifndef SentryCrashMonitor_System_h #define SentryCrashMonitor_System_h +#include "SentryCrashMonitor.h" +#import "SentryInternalCDefines.h" + #ifdef __cplusplus extern "C" { #endif -#include "SentryCrashMonitor.h" -#import "SentryInternalCDefines.h" - /** Access the Monitor API. */ SentryCrashMonitorAPI *sentrycrashcm_system_getAPI(void); diff --git a/Sources/SentryCrash/Reporting/Filters/SentryCrashReportFilter.h b/Sources/Sentry/include/SentryCrashReportFilter.h similarity index 100% rename from Sources/SentryCrash/Reporting/Filters/SentryCrashReportFilter.h rename to Sources/Sentry/include/SentryCrashReportFilter.h diff --git a/Sources/SentryCrash/Recording/SentryCrashReportWriter.h b/Sources/Sentry/include/SentryCrashReportWriter.h similarity index 100% rename from Sources/SentryCrash/Recording/SentryCrashReportWriter.h rename to Sources/Sentry/include/SentryCrashReportWriter.h index 2cacc25add5..f087ff1b93a 100644 --- a/Sources/SentryCrash/Recording/SentryCrashReportWriter.h +++ b/Sources/Sentry/include/SentryCrashReportWriter.h @@ -32,13 +32,13 @@ #ifndef HDR_SentryCrashReportWriter_h #define HDR_SentryCrashReportWriter_h +#include +#include + #ifdef __cplusplus extern "C" { #endif -#include -#include - /** * Encapsulates report writing functionality. */ diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashThread.h b/Sources/Sentry/include/SentryCrashThread.h similarity index 100% rename from Sources/SentryCrash/Recording/Tools/SentryCrashThread.h rename to Sources/Sentry/include/SentryCrashThread.h diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashUUIDConversion.h b/Sources/Sentry/include/SentryCrashUUIDConversion.h similarity index 100% rename from Sources/SentryCrash/Recording/Tools/SentryCrashUUIDConversion.h rename to Sources/Sentry/include/SentryCrashUUIDConversion.h diff --git a/Sources/Sentry/include/SentryCrashWrapper.h b/Sources/Sentry/include/SentryCrashWrapper.h deleted file mode 100644 index a1736bec06b..00000000000 --- a/Sources/Sentry/include/SentryCrashWrapper.h +++ /dev/null @@ -1,40 +0,0 @@ -#import "SentryDefines.h" -#import "SentryInternalCDefines.h" - -NS_ASSUME_NONNULL_BEGIN - -@class SentryScope; - -/** A wrapper around SentryCrash for testability. - */ -@interface SentryCrashWrapper : NSObject - -+ (instancetype)sharedInstance; - -- (void)startBinaryImageCache; - -- (void)stopBinaryImageCache; - -- (BOOL)crashedLastLaunch; - -- (NSTimeInterval)durationFromCrashStateInitToLastCrash; - -- (NSTimeInterval)activeDurationSinceLastCrash; - -- (BOOL)isBeingTraced; - -- (BOOL)isSimulatorBuild; - -- (BOOL)isApplicationInForeground; - -- (NSDictionary *)systemInfo; - -- (bytes)freeMemorySize; - -- (bytes)appMemorySize; - -- (void)enrichScope:(SentryScope *)scope; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryDataCategory.h b/Sources/Sentry/include/SentryDataCategory.h index 63b18153c1b..dcc56841159 100644 --- a/Sources/Sentry/include/SentryDataCategory.h +++ b/Sources/Sentry/include/SentryDataCategory.h @@ -19,5 +19,6 @@ typedef NS_ENUM(NSUInteger, SentryDataCategory) { kSentryDataCategoryProfileChunk = 10, kSentryDataCategorySpan = 11, kSentryDataCategoryFeedback = 12, - kSentryDataCategoryUnknown = 13, + kSentryDataCategoryLogItem = 13, + kSentryDataCategoryUnknown = 14, }; diff --git a/Sources/Sentry/include/SentryDataCategoryMapper.h b/Sources/Sentry/include/SentryDataCategoryMapper.h index 0454463b399..00692e63124 100644 --- a/Sources/Sentry/include/SentryDataCategoryMapper.h +++ b/Sources/Sentry/include/SentryDataCategoryMapper.h @@ -13,6 +13,7 @@ FOUNDATION_EXPORT NSString *const kSentryDataCategoryNameProfile; FOUNDATION_EXPORT NSString *const kSentryDataCategoryNameProfileChunk; FOUNDATION_EXPORT NSString *const kSentryDataCategoryNameReplay; FOUNDATION_EXPORT NSString *const kSentryDataCategoryNameFeedback; +FOUNDATION_EXPORT NSString *const kSentryDataCategoryNameLogItem; FOUNDATION_EXPORT NSString *const kSentryDataCategoryNameMetricBucket; FOUNDATION_EXPORT NSString *const kSentryDataCategoryNameSpan; FOUNDATION_EXPORT NSString *const kSentryDataCategoryNameUnknown; diff --git a/Sources/Sentry/include/SentryDefaultObjCRuntimeWrapper.h b/Sources/Sentry/include/SentryDefaultObjCRuntimeWrapper.h deleted file mode 100644 index 96dc40e3da4..00000000000 --- a/Sources/Sentry/include/SentryDefaultObjCRuntimeWrapper.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "SentryDefines.h" -#import "SentryObjCRuntimeWrapper.h" - -/** - * A wrapper around the objc runtime functions for testability. - */ -@interface SentryDefaultObjCRuntimeWrapper : NSObject -SENTRY_NO_INIT - -+ (instancetype)sharedInstance; - -@end diff --git a/Sources/Sentry/include/SentryDependencyContainerSwiftHelper.h b/Sources/Sentry/include/SentryDependencyContainerSwiftHelper.h index 4f41b45d6bc..ce1cb36c9ab 100644 --- a/Sources/Sentry/include/SentryDependencyContainerSwiftHelper.h +++ b/Sources/Sentry/include/SentryDependencyContainerSwiftHelper.h @@ -5,12 +5,18 @@ # import #endif // SENTRY_HAS_UIKIT +@protocol SentryObjCRuntimeWrapper; +@protocol SentryUIDeviceWrapper; +@class SentryHub; +@class SentryCrash; +@class SentryNSProcessInfoWrapper; + NS_ASSUME_NONNULL_BEGIN -// Some Swift code needs to access SentryDependencyContainer. To -// make that possible without requiring all of SentryDependencyContainer -// to be exposed to Swift this class is exposed to Swift -// and bridges some functionality from SentryDependencyContainer +// Some Swift code needs to access Sentry types that we don’t want to completely +// expose to Swift. This class is exposed to Swift +// and bridges some functionality from without importing large amounts of the +// codebase to Swift. @interface SentryDependencyContainerSwiftHelper : NSObject #if SENTRY_HAS_UIKIT @@ -20,6 +26,9 @@ NS_ASSUME_NONNULL_BEGIN #endif // SENTRY_HAS_UIKIT + (void)dispatchSyncOnMainQueue:(void (^)(void))block; ++ (id)objcRuntimeWrapper; ++ (SentryHub *)currentHub; ++ (SentryCrash *)crashReporter; @end diff --git a/Sources/Sentry/include/SentryDiscardedEvent.h b/Sources/Sentry/include/SentryDiscardedEvent.h deleted file mode 100644 index f2c0b85a4d4..00000000000 --- a/Sources/Sentry/include/SentryDiscardedEvent.h +++ /dev/null @@ -1,20 +0,0 @@ -#import "SentryDataCategory.h" -#import "SentryDiscardReason.h" -#import "SentrySerializable.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryDiscardedEvent : NSObject -SENTRY_NO_INIT - -- (instancetype)initWithReason:(SentryDiscardReason)reason - category:(SentryDataCategory)category - quantity:(NSUInteger)quantity; - -@property (nonatomic, assign, readonly) SentryDiscardReason reason; -@property (nonatomic, assign, readonly) SentryDataCategory category; -@property (nonatomic, assign, readonly) NSUInteger quantity; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryEnvelope+Private.h b/Sources/Sentry/include/SentryEnvelope+Private.h deleted file mode 100644 index 9d97fe9ac31..00000000000 --- a/Sources/Sentry/include/SentryEnvelope+Private.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "SentryEnvelope.h" - -NS_ASSUME_NONNULL_BEGIN - -@class SentryReplayEvent; -@class SentryReplayRecording; -@class SentryClientReport; - -@interface SentryEnvelopeItem () - -- (instancetype)initWithClientReport:(SentryClientReport *)clientReport; - -- (nullable instancetype)initWithReplayEvent:(SentryReplayEvent *)replayEvent - replayRecording:(SentryReplayRecording *)replayRecording - video:(NSURL *)videoURL; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryEnvelopeHeaderHelper.h b/Sources/Sentry/include/SentryEnvelopeHeaderHelper.h new file mode 100644 index 00000000000..83ce3690fa0 --- /dev/null +++ b/Sources/Sentry/include/SentryEnvelopeHeaderHelper.h @@ -0,0 +1,18 @@ +@import Foundation; + +@class SentryIdWrapper; +@class SentryEvent; + +NS_ASSUME_NONNULL_BEGIN + +// This class allows creation of SentryEnvelopeHeader from SentryEvent. We can't do +// this in Swift because SentryEvent is written in ObjC but SentryId is in Swift. +// Once SentryEvent gets converted to Swift we wouldn't need this class because we +// could do it directly in Swift. +@interface SentryEnvelopeHeaderHelper : NSObject + ++ (SentryIdWrapper *)headerIdFromEvent:(SentryEvent *)event; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryEvent+Serialize.h b/Sources/Sentry/include/SentryEvent+Serialize.h new file mode 100644 index 00000000000..c5adca2fa13 --- /dev/null +++ b/Sources/Sentry/include/SentryEvent+Serialize.h @@ -0,0 +1,8 @@ +#if SDK_V9 +# import "SentryEvent.h" +# import "SentrySerializable.h" + +@interface SentryEvent () + +@end +#endif // SDK_V9 diff --git a/Sources/Sentry/include/SentryFileIOTracker.h b/Sources/Sentry/include/SentryFileIOTracker.h index 4c023f1a5c7..d99f9c2ca8b 100644 --- a/Sources/Sentry/include/SentryFileIOTracker.h +++ b/Sources/Sentry/include/SentryFileIOTracker.h @@ -2,7 +2,7 @@ NS_ASSUME_NONNULL_BEGIN -@class SentryNSProcessInfoWrapper; +@protocol SentryProcessInfoSource; @class SentryThreadInspector; @interface SentryFileIOTracker : NSObject @@ -19,7 +19,7 @@ SENTRY_NO_INIT + (instancetype _Nullable)sharedInstance; - (instancetype)initWithThreadInspector:(SentryThreadInspector *)threadInspector - processInfoWrapper:(SentryNSProcessInfoWrapper *)processInfoWrapper; + processInfoWrapper:(id)processInfoWrapper; - (void)enable; diff --git a/Sources/Sentry/include/SentryFileManager.h b/Sources/Sentry/include/SentryFileManager.h index 5ca6c5fa0b3..ecc99d5a5a2 100644 --- a/Sources/Sentry/include/SentryFileManager.h +++ b/Sources/Sentry/include/SentryFileManager.h @@ -15,6 +15,7 @@ NS_ASSUME_NONNULL_BEGIN @class SentryOptions; @class SentrySession; +@protocol SentryCurrentDateProvider; @protocol SentryFileManagerDelegate - (void)envelopeItemDeleted:(SentryEnvelopeItem *)envelopeItem @@ -34,9 +35,8 @@ SENTRY_NO_INIT @property (nonatomic, readonly) NSString *previousBreadcrumbsFilePathOne; @property (nonatomic, readonly) NSString *previousBreadcrumbsFilePathTwo; -- (nullable instancetype)initWithOptions:(SentryOptions *)options error:(NSError **)error; - - (nullable instancetype)initWithOptions:(SentryOptions *)options + dateProvider:(id)dateProvider dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper error:(NSError **)error NS_DESIGNATED_INITIALIZER; @@ -154,8 +154,8 @@ SENTRY_EXTERN BOOL appLaunchProfileConfigFileExists(void); * Retrieve the contents of the launch profile config file, which stores the sample rates used to * decide whether or not to profile this launch. */ -SENTRY_EXTERN NSDictionary *_Nullable sentry_appLaunchProfileConfiguration( - void); +SENTRY_EXTERN NSDictionary + *_Nullable sentry_persistedLaunchProfileConfigurationOptions(void); /** * Write a config file that stores the sample rates used to determine whether this launch should diff --git a/Sources/Sentry/include/SentryHttpTransport.h b/Sources/Sentry/include/SentryHttpTransport.h index 8b279603f5a..c27bf1ac5bc 100644 --- a/Sources/Sentry/include/SentryHttpTransport.h +++ b/Sources/Sentry/include/SentryHttpTransport.h @@ -7,7 +7,7 @@ @class SentryDispatchQueueWrapper; @class SentryNSURLRequestBuilder; -@class SentryOptions; +@class SentryDsn; @protocol SentryCurrentDateProvider; NS_ASSUME_NONNULL_BEGIN @@ -16,7 +16,8 @@ NS_ASSUME_NONNULL_BEGIN : NSObject SENTRY_NO_INIT -- (id)initWithOptions:(SentryOptions *)options +- (id)initWithDsn:(SentryDsn *)dsn + sendClientReports:(BOOL)sendClientReports cachedEnvelopeSendDelay:(NSTimeInterval)cachedEnvelopeSendDelay dateProvider:(id)dateProvider fileManager:(SentryFileManager *)fileManager diff --git a/Sources/Sentry/include/SentryHub+Private.h b/Sources/Sentry/include/SentryHub+Private.h index e25c7a14ff5..2904c9d6db1 100644 --- a/Sources/Sentry/include/SentryHub+Private.h +++ b/Sources/Sentry/include/SentryHub+Private.h @@ -11,6 +11,7 @@ @class SentryTracer; @class SentryTracerConfiguration; @class SentryReplayEvent; +@class SentryAttachment; @class SentryReplayRecording; @protocol SentryIntegrationProtocol; @@ -33,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN * Every integration starts with "Sentry" and ends with "Integration". To keep the payload of the * event small we remove both. */ -- (NSMutableArray *)trimmedInstalledIntegrationNames; +- (NSArray *)trimmedInstalledIntegrationNames; - (void)addInstalledIntegration:(id)integration name:(NSString *)name; - (void)removeAllIntegrations; @@ -64,6 +65,10 @@ NS_ASSUME_NONNULL_BEGIN additionalEnvelopeItems:(NSArray *)additionalEnvelopeItems NS_SWIFT_NAME(capture(event:scope:additionalEnvelopeItems:)); +- (void)captureSerializedFeedback:(NSDictionary *)serializedFeedback + withEventId:(NSString *)feedbackEventId + attachments:(NSArray *)feedbackAttachments; + - (void)captureTransaction:(SentryTransaction *)transaction withScope:(SentryScope *)scope; - (void)captureTransaction:(SentryTransaction *)transaction diff --git a/Sources/Sentry/include/SentryInAppLogic.h b/Sources/Sentry/include/SentryInAppLogic.h deleted file mode 100644 index 683271c7bfd..00000000000 --- a/Sources/Sentry/include/SentryInAppLogic.h +++ /dev/null @@ -1,80 +0,0 @@ -#import "SentryDefines.h" - -NS_ASSUME_NONNULL_BEGIN - -/** - * This class detects whether a framework belongs to the app or not. We differentiate between three - * different types of frameworks. - * - * First, the main executable of the app, which's name can be retrieved by @c CFBundleExecutable. To - * mark this framework as "in-app" the caller needs to pass in the @c CFBundleExecutable to - * @c inAppIncludes. - * - * Next, there are private frameworks embedded in the application bundle. Both app supporting - * frameworks as CocoaLumberJack, Sentry, RXSwift, etc., and frameworks written by the user fall - * into this category. These frameworks can be both "in-app" or not. As we expect most frameworks of - * this category to be supporting frameworks, we mark them not as "in-app". If a user wants such a - * framework to be "in-app", they need to pass the name into @c inAppIncludes. For dynamic - * frameworks, the location is usually in the bundle under - * /Frameworks/FrameworkName.framework/FrameworkName. As for static frameworks, the location is the - * same as the main executable; this class marks all static frameworks as "in-app". To remove static - * frameworks from being "in-app", Sentry uses stack trace grouping rules on the server. - * - * Last, this class marks all public frameworks as not "in-app". Such frameworks are bound - * dynamically and are usually located at /Library/Frameworks or ~/Library/Frameworks. For - * simulators, the location can be something like - * /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/... - * - */ -@interface SentryInAppLogic : NSObject -SENTRY_NO_INIT - -@property (nonnull, readonly) NSArray *inAppIncludes; - -/** - * Initializes @c SentryInAppLogic with @c inAppIncludes and @c inAppExcludes. - * - * To work properly for Apple applications the @c inAppIncludes should contain the - * @c CFBundleExecutable, which is the name of the bundle’s executable file. - * - * @param inAppIncludes A list of string prefixes of framework names that belong to the app. This - * option takes precedence over @c inAppExcludes. - * @param inAppExcludes A list of string prefixes of framework names that do not belong to the app, - * but rather to third-party packages. Modules considered not part of the app will be hidden from - * stack traces by default. - */ -- (instancetype)initWithInAppIncludes:(NSArray *)inAppIncludes - inAppExcludes:(NSArray *)inAppExcludes; - -/** - * Determines if the framework belongs to the app by using @c inAppIncludes and @c inAppExcludes. - * Before checking this method lowercases the strings and uses only the @c lastPathComponent of the - * @c imagePath. - * - * @param imagePath the full path of the binary image. - * - * @return @c YES if the framework located at the @c imagePath starts with a prefix of - * @c inAppIncludes. @c NO if the framework located at the @c imagePath doesn't start with a prefix - * of - * @c inAppIncludes or start with a prefix of @c inAppExcludes. - */ -- (BOOL)isInApp:(nullable NSString *)imagePath; - -/** - * Determines if the class belongs to the app by getting its framework and checking with - * @c -[isInApp:] - * - * @param targetClass the class to check. - * - * @return @c YES if the @c targetClass belongs to a framework included in @c inAppIncludes. - * @c NO if targetClass does not belong to a framework in @c inAppIncludes or belongs to a framework - * in - * @c inAppExcludes. - */ -- (BOOL)isClassInApp:(Class)targetClass; - -+ (BOOL)isImageNameInApp:(NSString *)imageName inAppInclude:(NSString *)inAppInclude; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryInternalDefines.h b/Sources/Sentry/include/SentryInternalDefines.h index 51e2a62accb..27f3e6f053c 100644 --- a/Sources/Sentry/include/SentryInternalDefines.h +++ b/Sources/Sentry/include/SentryInternalDefines.h @@ -27,17 +27,6 @@ static NSString *const SentryPlatformName = @"cocoa"; SENTRY_LOG_WARN(__VA_ARGS__); \ NSAssert(NO, __VA_ARGS__); -/** - * Abort in test, log a warning otherwise. Meant to help us fail faster in our own development, but - * never crash customers because since it's not something they can control with their own - * configuration. - */ -#if SENTRY_TEST || SENTRY_TEST_CI -# define SENTRY_TEST_FATAL(...) SENTRY_CASSERT(NO, __VA_ARGS__) -#else -# define SENTRY_TEST_FATAL(...) SENTRY_LOG_WARN(__VA_ARGS__) -#endif // SENTRY_TEST || SENTRY_TEST_CI - /** * Abort if assertion fails in debug, and log a warning if it fails in production. */ @@ -89,3 +78,23 @@ static NSString *const SentryPlatformName = @"cocoa"; #define SPAN_DATA_BLOCKED_MAIN_THREAD @"blocked_main_thread" #define SPAN_DATA_THREAD_ID @"thread.id" #define SPAN_DATA_THREAD_NAME @"thread.name" + +/** + * `SENTRY_UNWRAP_NULLABLE` is used to unwrap a nullable pointer type to a non-nullable pointer type + * It should be used after the pointer has been checked for nullability. + * + * For example: + * ```objc + * id _Nullable nullablePointer = ...; + * if (nullablePointer != nil) { + * MyClass *_Nonnull nonNullPointer = SENTRY_UNWRAP_NULLABLE(MyClass, nullablePointer); + * } + * ``` + * + * We use this macro instead of directly casting to be able to find all usages of this + * pattern in the codebase. + */ +#define SENTRY_UNWRAP_NULLABLE(type, nullable_var) (type *_Nonnull)(nullable_var) +#define SENTRY_UNWRAP_NULLABLE_VALUE(type, nullable_var) (type _Nonnull)(nullable_var) +#define SENTRY_UNWRAP_NULLABLE_DICT(key, value, nullable_var) \ + (NSDictionary *_Nonnull)(nullable_var) diff --git a/Sources/Sentry/include/SentryLaunchProfiling.h b/Sources/Sentry/include/SentryLaunchProfiling.h index c477e76ad6d..99b73a173bf 100644 --- a/Sources/Sentry/include/SentryLaunchProfiling.h +++ b/Sources/Sentry/include/SentryLaunchProfiling.h @@ -10,6 +10,7 @@ @class SentryOptions; @class SentryTracerConfiguration; @class SentryTransactionContext; +@class SentryTracer; NS_ASSUME_NONNULL_BEGIN @@ -17,9 +18,12 @@ SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyTracesSampleRate; SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyTracesSampleRand; SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyProfilesSampleRate; SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyProfilesSampleRand; +# if !SDK_V9 SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyContinuousProfiling; +# endif // !SDK_V9 SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyContinuousProfilingV2; SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle; +SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyWaitForFullDisplay; /** * Whether or not the profiler started with the app launch. With trace profiling, this means there @@ -30,29 +34,25 @@ SENTRY_EXTERN NSString *const kSentryLaunchProfileConfigKeyContinuousProfilingV2 */ SENTRY_EXTERN BOOL sentry_isTracingAppLaunch; -/** Try to start a profiled trace for this app launch, if the configuration allows. */ -SENTRY_EXTERN void sentry_startLaunchProfile(void); +SENTRY_EXTERN SentryTracer *_Nullable sentry_launchTracer; -/** - * Stop any profiled trace that may be in flight from the start of the app launch, and transmit the - * dedicated transaction with the profiling data attached. - */ -SENTRY_EXTERN void sentry_stopAndTransmitLaunchProfile(SentryHub *hub); +SENTRY_EXTERN void sentry_startLaunchProfile(void); /** - * Stop the tracer that started the launch profiler. Use when the profiler will be attached to an - * app start transaction and doesn't need to be attached to a dedicated tracer. The tracer managing - * the profiler will be discarded in this case. + * Stop a launch tracer in order to stop the associated profiler. Must attach a hub, since there + * isn't yet one when we start the launch tracer. + * @noteIf the hub is nil, the tracer/profile will be discarded. This normally should always have a + * valid hub, but tests may not have one and call this with nil instead. */ -void sentry_stopAndDiscardLaunchProfileTracer(void); +SENTRY_EXTERN void sentry_stopAndDiscardLaunchProfileTracer(SentryHub *_Nullable hub); /** - * Write a file to disk containing sample rates for profiles and traces. The presence of this file - * will let the profiler know to start on the app launch, and the sample rates contained will help - * thread sampling decisions through to SentryHub later when it needs to start a transaction for the + * Write a file to disk containing profile configuration options. The presence of this file will let + * the profiler know to start on the app launch, and the sample rates contained will help thread + * sampling decisions through to SentryHub later when it needs to start a transaction for the * profile to be attached to. */ -SENTRY_EXTERN void sentry_configureLaunchProfiling(SentryOptions *options); +SENTRY_EXTERN void sentry_configureLaunchProfilingForNextLaunch(SentryOptions *options); NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryLevelMapper.h b/Sources/Sentry/include/SentryLevelMapper.h index fd67041b237..1398044158d 100644 --- a/Sources/Sentry/include/SentryLevelMapper.h +++ b/Sources/Sentry/include/SentryLevelMapper.h @@ -6,7 +6,7 @@ NS_ASSUME_NONNULL_BEGIN * Maps a string to a SentryLevel. If the passed string doesn't match any level this defaults to * the 'error' level. See https://develop.sentry.dev/sdk/event-payloads/#optional-attributes */ -SentryLevel sentryLevelForString(NSString *string); +SentryLevel sentryLevelForString(NSString *_Nullable string); NSString *nameForSentryLevel(SentryLevel level); diff --git a/Sources/Sentry/include/SentryMeasurementValue.h b/Sources/Sentry/include/SentryMeasurementValue.h deleted file mode 100644 index ec8a61bd275..00000000000 --- a/Sources/Sentry/include/SentryMeasurementValue.h +++ /dev/null @@ -1,19 +0,0 @@ -#import "SentryDefines.h" -#import "SentryMeasurementUnit.h" -#import "SentrySerializable.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryMeasurementValue : NSObject -SENTRY_NO_INIT - -- (instancetype)initWithValue:(NSNumber *)value; - -- (instancetype)initWithValue:(NSNumber *)value unit:(SentryMeasurementUnit *)unit; - -@property (nonatomic, copy, readonly) NSNumber *value; -@property (nullable, readonly, copy) SentryMeasurementUnit *unit; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryMetricProfiler.h b/Sources/Sentry/include/SentryMetricProfiler.h index 9b3409f6c4e..e17f04ca90a 100644 --- a/Sources/Sentry/include/SentryMetricProfiler.h +++ b/Sources/Sentry/include/SentryMetricProfiler.h @@ -9,6 +9,24 @@ NS_ASSUME_NONNULL_BEGIN +/** + * Return a serialized dictionary of the collected metrics. + * @discussion The dictionary will have the following structure: + * @code + * @"": @{ + * @"unit": @"", + * @"values": @[ + * @{ + * @"timestamp": @"", + * @"value": @"" + * }, + * // ... more dictionaries like that ... + * ] + * } + * @endcode + */ +SENTRY_EXTERN NSDictionary *serializeContinuousProfileMetrics(NSDictionary *state); + /** * A profiler that gathers various time-series and event-based metrics on the app process, such as * CPU and memory usage timeseries and thermal and memory pressure warning notifications. @@ -45,23 +63,10 @@ SENTRY_NO_INIT and:(uint64_t)endSystemTime; /** - * Return a serialized dictionary of the collected metrics. - * @discussion The dictionary will have the following structure: - * @code - * @"": @{ - * @"unit": @"", - * @"values": @[ - * @{ - * @"timestamp": @"", - * @"value": @"" - * }, - * // ... more dictionaries like that ... - * ] - * } - * @endcode + * Copy the data structures in a thread safe way so they can be used later to serialize into a + * payload for transmission. */ -- (NSMutableDictionary *) - serializeContinuousProfileMetrics; +- (NSDictionary *)copyMetricProfilerData; @end diff --git a/Sources/Sentry/include/SentryModels+Serializable.h b/Sources/Sentry/include/SentryModels+Serializable.h new file mode 100644 index 00000000000..4a5513d8ae6 --- /dev/null +++ b/Sources/Sentry/include/SentryModels+Serializable.h @@ -0,0 +1,93 @@ +#if SDK_V9 +# import "SentryBreadcrumb.h" +# import "SentryDebugMeta.h" +# import "SentryEnvelopeItemHeader.h" +# import "SentryEvent.h" +# import "SentryException.h" +# import "SentryFrame.h" +# import "SentryGeo.h" +# import "SentryInternalSerializable.h" +# import "SentryMechanism.h" +# import "SentryMechanismMeta.h" +# import "SentryMessage.h" +# import "SentryNSError.h" +# import "SentryRequest.h" +# import "SentryScope.h" +# import "SentryStacktrace.h" +# import "SentryThread.h" +# import "SentryTraceContext.h" +# import "SentryUser.h" + +@interface SentryScope () + +@end + +@interface SentryUser () + +@end + +@interface SentryEvent () + +@end + +@interface SentryStacktrace () + +@end + +@interface SentryGeo () + +@end + +@interface SentryFrame () + +@end + +@interface SentryNSError () + +@end + +@interface SentryMechanismMeta () + +@end + +@interface SentryMechanism () + +@end + +@interface SentryEnvelopeItemHeader () + +@end + +@interface SentryFrame () + +@end + +@interface SentryDebugMeta () + +@end + +@interface SentryException () + +@end + +@interface SentryTraceContext () + +@end + +@interface SentryMessage () + +@end + +@interface SentryThread () + +@end + +@interface SentryRequest () + +@end + +@interface SentryBreadcrumb () + +@end + +#endif // SDK_V9 diff --git a/Sources/Sentry/include/SentryNSApplication.h b/Sources/Sentry/include/SentryNSApplication.h deleted file mode 100644 index f9f7546b8b1..00000000000 --- a/Sources/Sentry/include/SentryNSApplication.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "SentryApplication.h" -#import "SentryDefines.h" - -#if TARGET_OS_OSX - -NS_ASSUME_NONNULL_BEGIN - -/** - * A helper tool to retrieve informations from the application instance. - */ -@interface SentryNSApplication : NSObject - -@end - -NS_ASSUME_NONNULL_END - -#endif // TARGET_OS_OSX diff --git a/Sources/Sentry/include/SentryNSNotificationCenterWrapper.h b/Sources/Sentry/include/SentryNSNotificationCenterWrapper.h deleted file mode 100644 index 68978115103..00000000000 --- a/Sources/Sentry/include/SentryNSNotificationCenterWrapper.h +++ /dev/null @@ -1,54 +0,0 @@ -#import "SentryDefines.h" - -#if SENTRY_HAS_UIKIT -# define SentryDidBecomeActiveNotification UIApplicationDidBecomeActiveNotification -# define SentryWillResignActiveNotification UIApplicationWillResignActiveNotification -# define SentryWillTerminateNotification UIApplicationWillTerminateNotification -#elif SENTRY_TARGET_MACOS_HAS_UI -# define SentryDidBecomeActiveNotification NSApplicationDidBecomeActiveNotification -# define SentryWillResignActiveNotification NSApplicationWillResignActiveNotification -# define SentryWillTerminateNotification NSApplicationWillTerminateNotification -#endif - -NS_ASSUME_NONNULL_BEGIN - -/** - * A wrapper around @c NSNotificationCenter functions for testability. - * @discussion Testing with @c NSNotificationCenter in CI leads to flaky tests for some classes. - * Therefore, we can use a wrapper around @c NSNotificationCenter to not depend on it. Instead, we - * call the methods - * @c NSNotificationCenter would call with Dynamic and ensure that sut properly subscribes to - * @c NSNotificationCenter. - */ -@interface SentryNSNotificationCenterWrapper : NSObject - -- (void)addObserver:(NSObject *)observer - selector:(SEL)aSelector - name:(NSNotificationName)aName - object:(nullable id)anObject; - -- (void)addObserver:(NSObject *)observer selector:(SEL)aSelector name:(NSNotificationName)aName; - -/** - * @note Per NSNotificationCenter's docs: The return value is retained by the system, and should be - * held onto by the caller in order to remove the observer with removeObserver: later, to stop - * observation. - */ -- (id)addObserverForName:(nullable NSNotificationName)name - object:(nullable id)obj - queue:(nullable NSOperationQueue *)queue - usingBlock:(void (^)(NSNotification *notification))block; - -- (void)removeObserver:(id)observer - name:(NSNotificationName)aName - object:(nullable id)anObject; - -- (void)removeObserver:(id)observer name:(NSNotificationName)aName; - -- (void)removeObserver:(id)observer; - -- (void)postNotification:(NSNotification *)notification; - -NS_ASSUME_NONNULL_END - -@end diff --git a/Sources/Sentry/include/SentryNSProcessInfoWrapper.h b/Sources/Sentry/include/SentryNSProcessInfoWrapper.h deleted file mode 100644 index f7aff957ae2..00000000000 --- a/Sources/Sentry/include/SentryNSProcessInfoWrapper.h +++ /dev/null @@ -1,19 +0,0 @@ -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryNSProcessInfoWrapper : NSObject - -@property (nonatomic, readonly) NSString *processDirectoryPath; -@property (nullable, nonatomic, readonly) NSString *processPath; -@property (readonly) NSUInteger processorCount; -@property (readonly) NSProcessInfoThermalState thermalState; -@property (readonly) NSDictionary *environment; - -#if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) -- (void)setProcessPath:(NSString *)path; -#endif // defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) || defined(DEBUG) - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryNSTimerFactory.h b/Sources/Sentry/include/SentryNSTimerFactory.h deleted file mode 100644 index b8200d4fa01..00000000000 --- a/Sources/Sentry/include/SentryNSTimerFactory.h +++ /dev/null @@ -1,19 +0,0 @@ -#import - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryNSTimerFactory : NSObject - -- (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval - repeats:(BOOL)repeats - block:(void (^)(NSTimer *timer))block; - -- (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti - target:(id)aTarget - selector:(SEL)aSelector - userInfo:(nullable id)userInfo - repeats:(BOOL)yesOrNo; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryNoOpSpan.h b/Sources/Sentry/include/SentryNoOpSpan.h index 61ae0d0795a..005f2bf2263 100644 --- a/Sources/Sentry/include/SentryNoOpSpan.h +++ b/Sources/Sentry/include/SentryNoOpSpan.h @@ -15,7 +15,9 @@ SENTRY_NO_INIT @property (nullable, readonly) NSDictionary *data; @property (readonly) NSDictionary *tags; +#if !SDK_V9 - (void)setExtraValue:(nullable id)value forKey:(NSString *)key DEPRECATED_ATTRIBUTE; +#endif // !SDK_V9 @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryNotificationNames.h b/Sources/Sentry/include/SentryNotificationNames.h new file mode 100644 index 00000000000..6dae332775b --- /dev/null +++ b/Sources/Sentry/include/SentryNotificationNames.h @@ -0,0 +1,11 @@ +#import "SentryDefines.h" + +#if SENTRY_HAS_UIKIT +# define SentryDidBecomeActiveNotification UIApplicationDidBecomeActiveNotification +# define SentryWillResignActiveNotification UIApplicationWillResignActiveNotification +# define SentryWillTerminateNotification UIApplicationWillTerminateNotification +#elif SENTRY_TARGET_MACOS_HAS_UI +# define SentryDidBecomeActiveNotification NSApplicationDidBecomeActiveNotification +# define SentryWillResignActiveNotification NSApplicationWillResignActiveNotification +# define SentryWillTerminateNotification NSApplicationWillTerminateNotification +#endif diff --git a/Sources/Sentry/include/SentryObjCRuntimeWrapper.h b/Sources/Sentry/include/SentryObjCRuntimeWrapper.h deleted file mode 100644 index fe1b07660a6..00000000000 --- a/Sources/Sentry/include/SentryObjCRuntimeWrapper.h +++ /dev/null @@ -1,9 +0,0 @@ -#import - -@protocol SentryObjCRuntimeWrapper - -- (const char **)copyClassNamesForImage:(const char *)image amount:(unsigned int *)outCount; - -- (const char *)class_getImageName:(Class)cls; - -@end diff --git a/Sources/Sentry/include/SentryOptions+Private.h b/Sources/Sentry/include/SentryOptions+Private.h index 58219cd4858..741ead64647 100644 --- a/Sources/Sentry/include/SentryOptions+Private.h +++ b/Sources/Sentry/include/SentryOptions+Private.h @@ -11,13 +11,42 @@ FOUNDATION_EXPORT NSString *const kSentryDefaultEnvironment; @interface SentryOptions () #if SENTRY_TARGET_PROFILING_SUPPORTED @property (nonatomic, assign) BOOL enableProfiling_DEPRECATED_TEST_ONLY; + +# if !SDK_V9 +/** + * If continuous profiling mode v1 ("beta") is enabled. + * @note Not for use with launch profiles. See functions in @c SentryLaunchProfiling . + */ - (BOOL)isContinuousProfilingEnabled; +# endif // !SDK_V9 + +/** + * If UI profiling mode ("continuous v2") is enabled. + * @note Not for use with launch profiles. See functions in @c SentryLaunchProfiling . + */ - (BOOL)isContinuousProfilingV2Enabled; + +/** + * Whether or not the SDK was configured with a profile mode that automatically starts and tracks + * profiles with traces. + * @note Not for use with launch profiles. See functions in @c SentryLaunchProfiling . + */ - (BOOL)isProfilingCorrelatedToTraces; + +/** + * UI Profiling options set on SDK start. + * @note Not for use with launch profiles. See functions in @c SentryLaunchProfiling . + */ @property (nonatomic, nullable, strong) SentryProfileOptions *profiling; #endif // SENTRY_TARGET_PROFILING_SUPPORTED -@property (nonatomic, readonly, class) NSArray *defaultIntegrationClasses; +#if SENTRY_TARGET_REPLAY_SUPPORTED + +- (BOOL)enableViewRendererV2; + +- (BOOL)enableFastViewRendering; + +#endif // # SENTRY_TARGET_REPLAY_SUPPORTED @property (nonatomic, strong, nullable) SentryUserFeedbackConfiguration *userFeedbackConfiguration API_AVAILABLE(ios(13.0)); diff --git a/Sources/Sentry/include/SentryPrivate.h b/Sources/Sentry/include/SentryPrivate.h index b26d24e1cdf..d77dfba0787 100644 --- a/Sources/Sentry/include/SentryPrivate.h +++ b/Sources/Sentry/include/SentryPrivate.h @@ -1,10 +1,19 @@ // Sentry internal headers that are needed for swift code; you cannot import headers that depend on // public interfaces here #import "NSLocale+Sentry.h" +#import "SentryBinaryImageCacheCallbacks.h" +#import "SentryCrashBinaryImageCache.h" +#import "SentryCrashDynamicLinker.h" #import "SentryCrashExceptionApplicationHelper.h" +#import "SentryCrashUUIDConversion.h" +#import "SentryDataCategoryMapper.h" +#import "SentryDiscardReasonMapper.h" +#import "SentryEnvelopeAttachmentHeader.h" +#import "SentryEnvelopeHeaderHelper.h" #import "SentryEventSwiftHelper.h" +#import "SentryHub+Private.h" #import "SentryNSDataUtils.h" -#import "SentryRandom.h" +#import "SentrySDK+Private.h" #import "SentryTime.h" #import "SentryUserAccess.h" #import "_SentryDispatchQueueWrapperInternal.h" @@ -12,21 +21,31 @@ // Headers that also import SentryDefines should be at the end of this list // otherwise it wont compile #import "SentryAsyncLog.h" +#import "SentryClient+Logs.h" +#import "SentryCrash.h" +#import "SentryCrashDebug.h" +#import "SentryCrashMonitor_AppState.h" +#import "SentryCrashMonitor_System.h" #import "SentryDateUtil.h" #import "SentryDateUtils.h" #import "SentryDependencyContainerSwiftHelper.h" #import "SentryDisplayLinkWrapper.h" +#import "SentryEvent+Serialize.h" #import "SentryFileIOTracker.h" #import "SentryFileManager.h" #import "SentryLevelHelper.h" #import "SentryMeta.h" +#import "SentryMsgPackSerializer.h" #import "SentryNSDictionarySanitize.h" +#import "SentryOptions+Private.h" #import "SentryProfiler+Private.h" -#import "SentryRandom.h" -#import "SentrySdkInfo.h" +#import "SentrySDKInternal.h" +#import "SentryScope+PrivateSwift.h" +#import "SentryScope.h" #import "SentrySerialization.h" -#import "SentrySession.h" +#import "SentrySessionInternal.h" #import "SentrySpanDataKey.h" #import "SentrySpanOperation.h" #import "SentryTraceHeader.h" #import "SentryTraceOrigin.h" +#import "SentryUser+Serialize.h" diff --git a/Sources/Sentry/include/SentryProfileConfiguration.h b/Sources/Sentry/include/SentryProfileConfiguration.h new file mode 100644 index 00000000000..e2eb75b60ed --- /dev/null +++ b/Sources/Sentry/include/SentryProfileConfiguration.h @@ -0,0 +1,57 @@ +#import "SentryProfilingConditionals.h" + +#if SENTRY_TARGET_PROFILING_SUPPORTED + +# import "SentryDefines.h" +# import + +NS_ASSUME_NONNULL_BEGIN + +@class SentrySamplerDecision; +@class SentryProfileOptions; + +/** + * A data structure to hold in memory the options that were persisted when configuring launch + * profiling on the previous launch's call to @c SentrySDK.startWith(options:) , and then is updated + * from SDK start. + * @note @c profilerSessionSampleDecision and @c profileOptions will be @c nil for continuous + * profiling v1 (continuous profiling beta). + */ +@interface SentryProfileConfiguration : NSObject + +SENTRY_NO_INIT + +@property (assign, nonatomic, readonly) BOOL isContinuousV1; +@property (assign, nonatomic, readonly) BOOL waitForFullDisplay; +@property (assign, nonatomic, readonly) BOOL isProfilingThisLaunch; + +/** + * Continuous profiling will respect its own sampling rate, which is computed once for each Sentry + * session. See calls to @c sentry_reevaluateSessionSampleRate() . + */ +@property (strong, nonatomic, nullable, readonly) + SentrySamplerDecision *profilerSessionSampleDecision; + +@property (strong, nonatomic, nullable, readonly) SentryProfileOptions *profileOptions; + +- (void)reevaluateSessionSampleRate; + +/** Initializer for SDK start if a configuration hasn't already been loaded for a launch profile. */ +- (instancetype)initWithProfileOptions:(SentryProfileOptions *)options; + +/** + * Initializer for both trace-based and continuous V1 (aka continuous beta) launch profiles. + */ +- (instancetype)initWaitingForFullDisplay:(BOOL)shouldWaitForFullDisplay + continuousV1:(BOOL)continuousV1; + +/** Initializer for launch UI profiles (aka continuous V2). */ +- (instancetype)initContinuousProfilingV2WaitingForFullDisplay:(BOOL)shouldWaitForFullDisplay + samplerDecision:(SentrySamplerDecision *)decision + profileOptions:(SentryProfileOptions *)options; + +@end + +NS_ASSUME_NONNULL_END + +#endif // SENTRY_TARGET_PROFILING_SUPPORTED diff --git a/Sources/Sentry/include/SentryProfileTimeseries.h b/Sources/Sentry/include/SentryProfileTimeseries.h index 0ae74f9366e..1a27fe44362 100644 --- a/Sources/Sentry/include/SentryProfileTimeseries.h +++ b/Sources/Sentry/include/SentryProfileTimeseries.h @@ -35,11 +35,11 @@ NSArray *_Nullable sentry_slicedProfileSamples( * recorded again unless the system changes it. In these cases, use the most recently recorded data * for it. */ -NSArray *sentry_sliceTraceProfileGPUData( +SENTRY_EXTERN NSArray *sentry_sliceTraceProfileGPUData( SentryFrameInfoTimeSeries *frameInfo, uint64_t startSystemTime, uint64_t endSystemTime, BOOL useMostRecentRecording); -NSArray *> *sentry_sliceContinuousProfileGPUData( +SENTRY_EXTERN NSArray *> *sentry_sliceContinuousProfileGPUData( SentryFrameInfoTimeSeries *frameInfo, NSTimeInterval start, NSTimeInterval end, BOOL useMostRecentFrameRate); diff --git a/Sources/Sentry/include/SentryProfiledTracerConcurrency.h b/Sources/Sentry/include/SentryProfiledTracerConcurrency.h index 15e8030e3d3..03eb0181d0d 100644 --- a/Sources/Sentry/include/SentryProfiledTracerConcurrency.h +++ b/Sources/Sentry/include/SentryProfiledTracerConcurrency.h @@ -25,9 +25,6 @@ NS_ASSUME_NONNULL_BEGIN SENTRY_EXTERN_C_BEGIN -void sentry_captureTransactionWithProfile(SentryHub *hub, SentryDispatchQueueWrapper *dispatchQueue, - SentryTransaction *transaction, NSDate *startTimestamp); - /** * @Returns An ID to use as a unique, unchanging ID for the tracer that started the profiler. It's * different from the profiler's internal ID. diff --git a/Sources/Sentry/include/SentryProfiler+Private.h b/Sources/Sentry/include/SentryProfiler+Private.h index 0f5edd11bac..84027f44a24 100644 --- a/Sources/Sentry/include/SentryProfiler+Private.h +++ b/Sources/Sentry/include/SentryProfiler+Private.h @@ -10,6 +10,8 @@ @class SentryId; @class SentryMetricProfiler; @class SentryOptions; +@class SentryProfileConfiguration; +@class SentryProfileOptions; @class SentryProfilerState; @class SentrySamplerDecision; @class SentryTransaction; @@ -21,6 +23,13 @@ NS_ASSUME_NONNULL_BEGIN +typedef struct { + BOOL shouldProfile; + /** Only needed for trace launch profiling or continuous profiling v2 with trace lifecycle; + * unused with continuous profiling. */ + SentrySamplerDecision *_Nullable tracesDecision; + SentrySamplerDecision *_Nullable profilesDecision; +} SentryLaunchProfileDecision; /** * Perform necessary profiler tasks that should take place when the SDK starts: configure the next * launch's profiling, stop tracer profiling if no automatic performance transaction is running, @@ -28,13 +37,11 @@ NS_ASSUME_NONNULL_BEGIN */ SENTRY_EXTERN void sentry_sdkInitProfilerTasks(SentryOptions *options, SentryHub *hub); -/** - * Continuous profiling will respect its own sampling rate, which is computed once for each Sentry - * session. - */ -SENTRY_EXTERN SentrySamplerDecision *_Nullable sentry_profilerSessionSampleDecision; +SENTRY_EXTERN SentryProfileConfiguration *_Nullable sentry_profileConfiguration; + +SENTRY_EXTERN BOOL sentry_isLaunchProfileCorrelatedToTraces(void); -SENTRY_EXTERN void sentry_reevaluateSessionSampleRate(float sessionSampleRate); +SENTRY_EXTERN void sentry_reevaluateSessionSampleRate(void); SENTRY_EXTERN void sentry_configureContinuousProfiling(SentryOptions *options); diff --git a/Sources/Sentry/include/SentryProfilingSwiftHelpers.h b/Sources/Sentry/include/SentryProfilingSwiftHelpers.h new file mode 100644 index 00000000000..ef4bd94d6dd --- /dev/null +++ b/Sources/Sentry/include/SentryProfilingSwiftHelpers.h @@ -0,0 +1,52 @@ +#import "SentryProfilingConditionals.h" +#import + +@class SentryId; +@class SentryProfileOptions; +@class SentrySpanId; +@class SentryClient; +@class SentryDispatchQueueWrapper; +@class SentryTransactionContext; + +NS_ASSUME_NONNULL_BEGIN + +// The functions in this file exist to bridge ObjectiveC++ to Swift. When building with Swift +// Package Manager you can’t import Swift into ObjectiveC++ so instead that code calls plain C +// functions in this file which then uses Swift in their implementation. + +#ifdef __cplusplus +extern "C" { +#endif + +#if !SDK_V9 +BOOL sentry_isContinuousProfilingEnabled(SentryClient *client); +#endif // !SDK_V9 +BOOL sentry_isContinuousProfilingV2Enabled(SentryClient *client); +BOOL sentry_isProfilingCorrelatedToTraces(SentryClient *client); +SentryProfileOptions *sentry_getProfiling(SentryClient *client); +NSString *sentry_stringFromSentryID(SentryId *sentryID); +NSDate *sentry_getDate(void); +uint64_t sentry_getSystemTime(void); +SentryId *sentry_getSentryId(void); +SentryProfileOptions *sentry_getSentryProfileOptions(void); +BOOL sentry_isTraceLifecycle(SentryProfileOptions *options); +float sentry_sessionSampleRate(SentryProfileOptions *options); +BOOL sentry_profileAppStarts(SentryProfileOptions *options); +SentrySpanId *sentry_getParentSpanID(SentryTransactionContext *context); +SentryId *sentry_getTraceID(SentryTransactionContext *context); +BOOL sentry_isNotSampled(SentryTransactionContext *context); +void sentry_dispatchAsync(SentryDispatchQueueWrapper *wrapper, dispatch_block_t block); +void sentry_dispatchAsyncOnMain(SentryDispatchQueueWrapper *wrapper, dispatch_block_t block); +void sentry_addObserver(id observer, SEL selector, NSNotificationName name, _Nullable id object); +void sentry_removeObserver(id observer); +void sentry_postNotification(NSNotification *notification); +id sentry_addObserverForName(NSNotificationName name, dispatch_block_t block); +NSTimer *sentry_scheduledTimer(NSTimeInterval interval, BOOL repeats, dispatch_block_t block); +NSTimer *sentry_scheduledTimerWithTarget( + NSTimeInterval interval, id target, SEL selector, _Nullable id userInfo, BOOL repeats); + +#ifdef __cplusplus +} +#endif + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryRandom.h b/Sources/Sentry/include/SentryRandom.h deleted file mode 100644 index bdcc09a011c..00000000000 --- a/Sources/Sentry/include/SentryRandom.h +++ /dev/null @@ -1,20 +0,0 @@ -#import - -NS_ASSUME_NONNULL_BEGIN - -@protocol SentryRandom - -/** - * Returns a random number uniformly distributed over the interval [0.0 , 1.0]. - */ -- (double)nextNumber; - -@end - -@interface SentryRandom : NSObject - -- (double)nextNumber; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentrySDK+Private.h b/Sources/Sentry/include/SentrySDK+Private.h index 011dfa67e67..b360f4e9888 100644 --- a/Sources/Sentry/include/SentrySDK+Private.h +++ b/Sources/Sentry/include/SentrySDK+Private.h @@ -4,10 +4,10 @@ # import "SentryProfilingConditionals.h" #endif -#if __has_include() -# import +#if __has_include() +# import #else -# import "SentrySDK.h" +# import "SentrySDKInternal.h" #endif @class SentryAppStartMeasurement; @@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN -@interface SentrySDK () +@interface SentrySDKInternal () + (void)captureFatalEvent:(SentryEvent *)event; diff --git a/Sources/Sentry/Public/SentrySDK.h b/Sources/Sentry/include/SentrySDKInternal.h similarity index 87% rename from Sources/Sentry/Public/SentrySDK.h rename to Sources/Sentry/include/SentrySDKInternal.h index 4259f87f872..aa2224bad3a 100644 --- a/Sources/Sentry/Public/SentrySDK.h +++ b/Sources/Sentry/include/SentrySDKInternal.h @@ -5,6 +5,7 @@ #else # import #endif +#import SENTRY_HEADER(SentryProfilingConditionals) @protocol SentrySpan; @@ -13,22 +14,31 @@ @class SentryFeedback; @class SentryFeedbackAPI; @class SentryId; -@class SentryMetricsAPI; @class SentryOptions; @class SentryReplayApi; @class SentryScope; @class SentryTransactionContext; @class SentryUser; @class SentryUserFeedback; +@class SentryAttachment; +@class SentryLogger; @class UIView; NS_ASSUME_NONNULL_BEGIN +@interface SentryIdWrapper : NSObject + +@property (nonatomic, strong) NSString *sentryIdString; + +- (instancetype)initWithId:(NSString *)sentryIdString; + +@end + /** - * The main entry point for the SentrySDK. - * We recommend using @c +[startWithConfigureOptions:] to initialize Sentry. + * The internal implementation of SentrySDK. + * This class is used internally by the Swift wrapper. */ -@interface SentrySDK : NSObject +@interface SentrySDKInternal : NSObject SENTRY_NO_INIT /** @@ -41,8 +51,6 @@ SENTRY_NO_INIT */ @property (class, nonatomic, readonly) BOOL isEnabled; -@property (class, nonatomic, readonly) SentryMetricsAPI *metrics; - #if SENTRY_TARGET_REPLAY_SUPPORTED /** * API to control session replay @@ -75,7 +83,7 @@ SENTRY_NO_INIT * @return The @c SentryId of the event or @c SentryId.empty if the event is not sent. * */ -+ (SentryId *)captureEvent:(SentryEvent *)event NS_SWIFT_NAME(capture(event:)); ++ (SentryIdWrapper *)captureEvent:(SentryEvent *)event NS_SWIFT_NAME(capture(event:)); /** * Captures a manually created event and sends it to Sentry. Only the data in this scope object will @@ -85,8 +93,8 @@ SENTRY_NO_INIT * @return The @c SentryId of the event or @c SentryId.empty if the event is not sent. * */ -+ (SentryId *)captureEvent:(SentryEvent *)event - withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(event:scope:)); ++ (SentryIdWrapper *)captureEvent:(SentryEvent *)event + withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(event:scope:)); /** * Captures a manually created event and sends it to Sentry. Maintains the global scope but mutates @@ -96,8 +104,9 @@ SENTRY_NO_INIT * @return The @c SentryId of the event or @c SentryId.empty if the event is not sent. * */ -+ (SentryId *)captureEvent:(SentryEvent *)event - withScopeBlock:(void (^)(SentryScope *scope))block NS_SWIFT_NAME(capture(event:block:)); ++ (SentryIdWrapper *)captureEvent:(SentryEvent *)event + withScopeBlock:(void (^)(SentryScope *scope))block + NS_SWIFT_NAME(capture(event:block:)); /** * Creates a transaction, binds it to the hub and returns the instance. @@ -167,7 +176,7 @@ SENTRY_NO_INIT * @return The @c SentryId of the event or @c SentryId.empty if the event is not sent. * */ -+ (SentryId *)captureError:(NSError *)error NS_SWIFT_NAME(capture(error:)); ++ (SentryIdWrapper *)captureError:(NSError *)error NS_SWIFT_NAME(capture(error:)); /** * Captures an error event and sends it to Sentry. Only the data in this scope object will be added @@ -177,8 +186,8 @@ SENTRY_NO_INIT * @return The @c SentryId of the event or @c SentryId.empty if the event is not sent. * */ -+ (SentryId *)captureError:(NSError *)error - withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(error:scope:)); ++ (SentryIdWrapper *)captureError:(NSError *)error + withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(error:scope:)); /** * Captures an error event and sends it to Sentry. Maintains the global scope but mutates scope data @@ -188,8 +197,9 @@ SENTRY_NO_INIT * @return The @c SentryId of the event or @c SentryId.empty if the event is not sent. * */ -+ (SentryId *)captureError:(NSError *)error - withScopeBlock:(void (^)(SentryScope *scope))block NS_SWIFT_NAME(capture(error:block:)); ++ (SentryIdWrapper *)captureError:(NSError *)error + withScopeBlock:(void (^)(SentryScope *scope))block + NS_SWIFT_NAME(capture(error:block:)); /** * Captures an exception event and sends it to Sentry. @@ -197,7 +207,7 @@ SENTRY_NO_INIT * @return The @c SentryId of the event or @c SentryId.empty if the event is not sent. * */ -+ (SentryId *)captureException:(NSException *)exception NS_SWIFT_NAME(capture(exception:)); ++ (SentryIdWrapper *)captureException:(NSException *)exception NS_SWIFT_NAME(capture(exception:)); /** * Captures an exception event and sends it to Sentry. Only the data in this scope object will be @@ -207,8 +217,8 @@ SENTRY_NO_INIT * @return The @c SentryId of the event or @c SentryId.empty if the event is not sent. * */ -+ (SentryId *)captureException:(NSException *)exception - withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(exception:scope:)); ++ (SentryIdWrapper *)captureException:(NSException *)exception + withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(exception:scope:)); /** * Captures an exception event and sends it to Sentry. Maintains the global scope but mutates scope @@ -218,8 +228,8 @@ SENTRY_NO_INIT * @return The @c SentryId of the event or @c SentryId.empty if the event is not sent. * */ -+ (SentryId *)captureException:(NSException *)exception - withScopeBlock:(void (^)(SentryScope *scope))block ++ (SentryIdWrapper *)captureException:(NSException *)exception + withScopeBlock:(void (^)(SentryScope *scope))block NS_SWIFT_NAME(capture(exception:block:)); /** @@ -228,7 +238,7 @@ SENTRY_NO_INIT * @return The @c SentryId of the event or @c SentryId.empty if the event is not sent. * */ -+ (SentryId *)captureMessage:(NSString *)message NS_SWIFT_NAME(capture(message:)); ++ (SentryIdWrapper *)captureMessage:(NSString *)message NS_SWIFT_NAME(capture(message:)); /** * Captures a message event and sends it to Sentry. Only the data in this scope object will be added @@ -238,8 +248,8 @@ SENTRY_NO_INIT * @return The @c SentryId of the event or @c SentryId.empty if the event is not sent. * */ -+ (SentryId *)captureMessage:(NSString *)message - withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(message:scope:)); ++ (SentryIdWrapper *)captureMessage:(NSString *)message + withScope:(SentryScope *)scope NS_SWIFT_NAME(capture(message:scope:)); /** * Captures a message event and sends it to Sentry. Maintains the global scope but mutates scope @@ -249,8 +259,8 @@ SENTRY_NO_INIT * @return The @c SentryId of the event or @c SentryId.empty if the event is not sent. * */ -+ (SentryId *)captureMessage:(NSString *)message - withScopeBlock:(void (^)(SentryScope *scope))block ++ (SentryIdWrapper *)captureMessage:(NSString *)message + withScopeBlock:(void (^)(SentryScope *scope))block NS_SWIFT_NAME(capture(message:block:)); #if !SDK_V9 @@ -266,19 +276,13 @@ SENTRY_NO_INIT "SentryOptions.configureUserFeedback."); #endif // !SDK_V9 -/** - * Captures user feedback that was manually gathered and sends it to Sentry. - * @warning This is an experimental feature and may still have bugs. - * @param feedback The feedback to send to Sentry. - * @note If you'd prefer not to have to build the UI required to gather the feedback from the user, - * see @c SentryOptions.configureUserFeedback to customize a fully managed integration. See - * https://docs.sentry.io/platforms/apple/user-feedback/ for more information. - */ -+ (void)captureFeedback:(SentryFeedback *)feedback NS_SWIFT_NAME(capture(feedback:)); ++ (void)captureSerializedFeedback:(NSDictionary *)serializedFeedback + withEventId:(NSString *)feedbackEventId + attachments:(NSArray *)feedbackAttachments; #if TARGET_OS_IOS && SENTRY_HAS_UIKIT -@property (nonatomic, class, readonly) SentryFeedbackAPI *feedback API_AVAILABLE(ios(13.0)); +@property (nonatomic, class, readonly) SentryFeedbackAPI *feedback; #endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT diff --git a/Sources/Sentry/include/SentrySampling.h b/Sources/Sentry/include/SentrySampling.h index 469d2a339b2..97742fe8e87 100644 --- a/Sources/Sentry/include/SentrySampling.h +++ b/Sources/Sentry/include/SentrySampling.h @@ -19,8 +19,10 @@ SENTRY_EXTERN SentrySamplerDecision *sentry_sampleTrace( * whether the trace corresponding to the profile was sampled, to decide whether to configure the * next launch to start a trace profile. */ +# if !SDK_V9 SENTRY_EXTERN SentrySamplerDecision *sentry_sampleTraceProfile(SentrySamplingContext *context, SentrySamplerDecision *tracesSamplerDecision, SentryOptions *options); +# endif // !SDK_V9 SENTRY_EXTERN SentrySamplerDecision *sentry_sampleProfileSession(float sessionSampleRate); #endif // SENTRY_TARGET_PROFILING_SUPPORTED diff --git a/Sources/Sentry/include/SentryScope+Private.h b/Sources/Sentry/include/SentryScope+Private.h index f5c2c36b2c1..1a0f6cabfb2 100644 --- a/Sources/Sentry/include/SentryScope+Private.h +++ b/Sources/Sentry/include/SentryScope+Private.h @@ -15,11 +15,6 @@ NS_ASSUME_NONNULL_BEGIN @property (atomic, strong, readonly) NSArray *attachments; -/** - * Set global user -> thus will be sent with every event - */ -@property (atomic, strong) SentryUser *_Nullable userObject; - /** * The propagation context has a setter, requiring it to be nonatomic */ @@ -49,6 +44,8 @@ NS_ASSUME_NONNULL_BEGIN - (NSArray *)breadcrumbs; +- (void)setSpan:(nullable id)span; + /** * used to add values in event context. */ diff --git a/Sources/Sentry/include/SentryScope+PrivateSwift.h b/Sources/Sentry/include/SentryScope+PrivateSwift.h new file mode 100644 index 00000000000..9c4f279ef8f --- /dev/null +++ b/Sources/Sentry/include/SentryScope+PrivateSwift.h @@ -0,0 +1,24 @@ +#import "SentryScope.h" + +NS_ASSUME_NONNULL_BEGIN + +static NSString *const SENTRY_CONTEXT_OS_KEY = @"os"; +static NSString *const SENTRY_CONTEXT_DEVICE_KEY = @"device"; + +// Added to only expose a limited sub-set of internal API needed in the Swift layer. +@interface SentryScope () + +// This is a workaround to make the traceId available in the Swift layer. +// Can't expose the SentryId directly for some reason. +@property (nonatomic, readonly) NSString *propagationContextTraceIdString; + +/** + * Set global user -> thus will be sent with every event + */ +@property (atomic, strong) SentryUser *_Nullable userObject; + +- (NSDictionary *_Nullable)getContextForKey:(NSString *)key; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryScopeObserver.h b/Sources/Sentry/include/SentryScopeObserver.h index 98894f86f61..bf26cd379a1 100644 --- a/Sources/Sentry/include/SentryScopeObserver.h +++ b/Sources/Sentry/include/SentryScopeObserver.h @@ -34,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)clear; @optional -- (void)setCurrentScreen:(NSString *)currentScreen; +- (void)setCurrentScreen:(NSString *_Nullable)currentScreen; @end diff --git a/Sources/Sentry/include/SentrySdkInfo.h b/Sources/Sentry/include/SentrySdkInfo.h deleted file mode 100644 index 6ad1d88013a..00000000000 --- a/Sources/Sentry/include/SentrySdkInfo.h +++ /dev/null @@ -1,77 +0,0 @@ -#if __has_include() -# import -#else -# import "SentryDefines.h" -#endif - -#if __has_include() -# import -#else -# import "SentryInternalSerializable.h" -#endif - -#import - -@class SentryOptions; - -NS_ASSUME_NONNULL_BEGIN - -/** - * Describes the Sentry SDK and its configuration used to capture and transmit an event. - * @note Both name and version are required. - * @see https://develop.sentry.dev/sdk/event-payloads/sdk/ - */ -@interface SentrySdkInfo : NSObject -SENTRY_NO_INIT - -+ (instancetype)global; - -/** - * The name of the SDK. Examples: sentry.cocoa, sentry.cocoa.vapor, ... - */ -@property (nonatomic, readonly, copy) NSString *name; - -/** - * The version of the SDK. It should have the Semantic Versioning format MAJOR.MINOR.PATCH, without - * any prefix (no v or anything else in front of the major version number). Examples: - * 0.1.0, 1.0.0, 2.0.0-beta0 - */ -@property (nonatomic, readonly, copy) NSString *version; - -/** - * A list of names identifying enabled integrations. The list should - * have all enabled integrations, including default integrations. Default - * integrations are included because different SDK releases may contain different - * default integrations. - */ -@property (nonatomic, readonly, copy) NSArray *integrations; - -/** - * A list of feature names identifying enabled SDK features. This list - * should contain all enabled SDK features. On some SDKs, enabling a feature in the - * options also adds an integration. We encourage tracking such features with either - * integrations or features but not both to reduce the payload size. - */ -@property (nonatomic, readonly, copy) NSArray *features; - -/** - * A list of packages that were installed as part of this SDK or the - * activated integrations. Each package consists of a name in the format - * source:identifier and version. - */ -@property (nonatomic, readonly, copy) NSArray *> *packages; - -- (instancetype)initWithOptions:(SentryOptions *_Nullable)options; - -- (instancetype)initWithName:(NSString *)name - version:(NSString *)version - integrations:(NSArray *)integrations - features:(NSArray *)features - packages:(NSArray *> *)packages - NS_DESIGNATED_INITIALIZER; - -- (instancetype)initWithDict:(NSDictionary *)dict; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentrySerialization.h b/Sources/Sentry/include/SentrySerialization.h index 63362f141e0..47e76ef07a5 100644 --- a/Sources/Sentry/include/SentrySerialization.h +++ b/Sources/Sentry/include/SentrySerialization.h @@ -17,8 +17,6 @@ NS_ASSUME_NONNULL_BEGIN + (NSData *_Nullable)dataWithEnvelope:(SentryEnvelope *)envelope; -+ (NSData *)dataWithReplayRecording:(SentryReplayRecording *)replayRecording; - + (SentryEnvelope *_Nullable)envelopeWithData:(NSData *)data; + (SentryAppState *_Nullable)appStateWithData:(NSData *)sessionData; diff --git a/Sources/Sentry/include/SentrySession+Private.h b/Sources/Sentry/include/SentrySession+Private.h deleted file mode 100644 index 988d378b92c..00000000000 --- a/Sources/Sentry/include/SentrySession+Private.h +++ /dev/null @@ -1,15 +0,0 @@ -#import "SentrySession.h" - -NS_ASSUME_NONNULL_BEGIN - -NSString *nameForSentrySessionStatus(SentrySessionStatus status); - -@interface SentrySession () - -@property (nonatomic) NSUInteger errors; - -- (void)setFlagInit; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentrySession.h b/Sources/Sentry/include/SentrySessionInternal.h similarity index 83% rename from Sources/Sentry/include/SentrySession.h rename to Sources/Sentry/include/SentrySessionInternal.h index 20996ed325c..0c4e2593b76 100644 --- a/Sources/Sentry/include/SentrySession.h +++ b/Sources/Sentry/include/SentrySessionInternal.h @@ -4,7 +4,9 @@ NS_ASSUME_NONNULL_BEGIN -typedef NS_ENUM(NSUInteger, SentrySessionStatus) { +NSString *nameForSentrySessionStatus(NSUInteger status); + +typedef NS_ENUM(NSUInteger, InternalSentrySessionStatus) { kSentrySessionStatusOk = 0, kSentrySessionStatusExited = 1, kSentrySessionStatusCrashed = 2, @@ -14,7 +16,7 @@ typedef NS_ENUM(NSUInteger, SentrySessionStatus) { /** * The SDK uses SentrySession to inform Sentry about release and project associated project health. */ -@interface SentrySession : NSObject +@interface SentrySessionInternal : NSObject SENTRY_NO_INIT - (instancetype)initWithReleaseName:(NSString *)releaseName distinctId:(NSString *)distinctId; @@ -32,10 +34,12 @@ SENTRY_NO_INIT - (void)incrementErrors; +- (void)setFlagInit; + @property (nonatomic, readonly, strong) NSUUID *sessionId; @property (nonatomic, readonly, strong) NSDate *started; -@property (nonatomic, readonly) enum SentrySessionStatus status; -@property (nonatomic, readonly) NSUInteger errors; +@property (nonatomic, readonly) InternalSentrySessionStatus status; +@property (nonatomic) NSUInteger errors; @property (nonatomic, readonly) NSUInteger sequence; @property (nonatomic, readonly, strong) NSString *distinctId; /** @@ -56,6 +60,8 @@ SENTRY_NO_INIT - (NSDictionary *)serialize; +- (SentrySessionInternal *)safeCopyWithZone:(nullable NSZone *)zone; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentrySessionTracker.h b/Sources/Sentry/include/SentrySessionTracker.h index 17161fa8603..53b97e39ada 100644 --- a/Sources/Sentry/include/SentrySessionTracker.h +++ b/Sources/Sentry/include/SentrySessionTracker.h @@ -1,9 +1,9 @@ #import "SentryDefines.h" @class SentryEvent; -@class SentryNSNotificationCenterWrapper; @class SentryOptions; +@protocol SentryNSNotificationCenterWrapper; @protocol SentryApplication; @protocol SentryCurrentDateProvider; @@ -20,7 +20,7 @@ SENTRY_NO_INIT - (instancetype)initWithOptions:(SentryOptions *)options application:(id)application dateProvider:(id)dateProvider - notificationCenter:(SentryNSNotificationCenterWrapper *)notificationCenter; + notificationCenter:(id)notificationCenter; - (void)start; - (void)stop; diff --git a/Sources/Sentry/include/SentrySpan.h b/Sources/Sentry/include/SentrySpan.h index 7fd111eed5b..13fb8953a6e 100644 --- a/Sources/Sentry/include/SentrySpan.h +++ b/Sources/Sentry/include/SentrySpan.h @@ -1,5 +1,6 @@ #import "SentryDefines.h" #import "SentryProfilingConditionals.h" +#import "SentrySerializable.h" #import "SentrySpanProtocol.h" NS_ASSUME_NONNULL_BEGIN @@ -110,7 +111,9 @@ SENTRY_NO_INIT #endif // SENTRY_HAS_UIKIT ; +#if !SDK_V9 - (void)setExtraValue:(nullable id)value forKey:(NSString *)key DEPRECATED_ATTRIBUTE; +#endif // !SDK_V9 @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentrySubClassFinder.h b/Sources/Sentry/include/SentrySubClassFinder.h index 8da9aa7efbf..99b85d35f5d 100644 --- a/Sources/Sentry/include/SentrySubClassFinder.h +++ b/Sources/Sentry/include/SentrySubClassFinder.h @@ -1,8 +1,9 @@ #import "SentryDefines.h" -#import "SentryObjCRuntimeWrapper.h" NS_ASSUME_NONNULL_BEGIN +@protocol SentryObjCRuntimeWrapper; + @class SentryDefaultObjCRuntimeWrapper; @class SentryDispatchQueueWrapper; diff --git a/Sources/Sentry/include/SentrySystemEventBreadcrumbs.h b/Sources/Sentry/include/SentrySystemEventBreadcrumbs.h index fc33880d785..447efe12d30 100644 --- a/Sources/Sentry/include/SentrySystemEventBreadcrumbs.h +++ b/Sources/Sentry/include/SentrySystemEventBreadcrumbs.h @@ -6,15 +6,15 @@ NS_ASSUME_NONNULL_BEGIN -@class SentryNSNotificationCenterWrapper; - +@protocol SentryNSNotificationCenterWrapper; @protocol SentryBreadcrumbDelegate; @interface SentrySystemEventBreadcrumbs : NSObject SENTRY_NO_INIT - (instancetype)initWithFileManager:(SentryFileManager *)fileManager - andNotificationCenterWrapper:(SentryNSNotificationCenterWrapper *)notificationCenterWrapper; + andNotificationCenterWrapper: + (id)notificationCenterWrapper; - (void)startWithDelegate:(id)delegate; diff --git a/Sources/Sentry/include/SentrySystemWrapper.h b/Sources/Sentry/include/SentrySystemWrapper.h index eccf490c156..90e2a96275e 100644 --- a/Sources/Sentry/include/SentrySystemWrapper.h +++ b/Sources/Sentry/include/SentrySystemWrapper.h @@ -1,8 +1,10 @@ -#import "SentryDefines.h" +#import "SentryProfilerDefines.h" -NS_ASSUME_NONNULL_BEGIN +#if SENTRY_TARGET_PROFILING_SUPPORTED + +# import "SentryDefines.h" -typedef void (^SentryMemoryPressureNotification)(uintptr_t); +NS_ASSUME_NONNULL_BEGIN /** * @c mach_vm_size_t Is a type defined in mach headers as an unsigned 64-bit type used to express @@ -16,6 +18,8 @@ typedef mach_vm_size_t SentryRAMBytes; */ @interface SentrySystemWrapper : NSObject +- (instancetype)initWithProcessorCount:(long)processorCount; + - (SentryRAMBytes)memoryFootprintBytes:(NSError **)error; /** @@ -25,12 +29,17 @@ typedef mach_vm_size_t SentryRAMBytes; */ - (nullable NSNumber *)cpuUsageWithError:(NSError **)error; +// Only some architectures support reading energy. +# if defined(__arm__) || defined(__arm64__) /** * @return The cumulative amount of nanojoules expended by the CPU for this task since process * start. */ - (nullable NSNumber *)cpuEnergyUsageWithError:(NSError **)error; +# endif @end NS_ASSUME_NONNULL_END + +#endif // SENTRY_TARGET_PROFILING_SUPPORTED diff --git a/Sources/Sentry/include/SentryTracer.h b/Sources/Sentry/include/SentryTracer.h index 74e2f375051..46cc99ef946 100644 --- a/Sources/Sentry/include/SentryTracer.h +++ b/Sources/Sentry/include/SentryTracer.h @@ -88,7 +88,7 @@ static const NSTimeInterval SENTRY_AUTO_TRANSACTION_MAX_DURATION = 500.0; /** * Get the tracer from a span. */ -+ (nullable SentryTracer *)getTracer:(id)span; ++ (nullable SentryTracer *)getTracer:(id _Nullable)span; - (void)startIdleTimeout; diff --git a/Sources/Sentry/include/SentryTracerConfiguration.h b/Sources/Sentry/include/SentryTracerConfiguration.h index 831b006b5b7..31bb1c62cb0 100644 --- a/Sources/Sentry/include/SentryTracerConfiguration.h +++ b/Sources/Sentry/include/SentryTracerConfiguration.h @@ -30,23 +30,19 @@ NS_ASSUME_NONNULL_BEGIN /** * This flag indicates whether the trace should be captured when the timeout triggers. - * If Yes, this tracer will be discarced in case the timeout triggers. + * If Yes, this tracer will be discarded in case the timeout triggers. * Default @c NO */ @property (nonatomic) BOOL finishMustBeCalled; #if SENTRY_TARGET_PROFILING_SUPPORTED /** - * Whether to sample a profile corresponding to this transaction + * Whether a profile is sampled for this trace. + * @note This can be set for either launch profiles (trace-based via @c + * SentryOptions.profilesSampleRate/SentryOptions.profilesSampler or trace lifecycle ui/v2 profiles + * via @c SentryProfilingOptions.sessionSampleRate) or non-launch trace-based profiles. */ @property (nonatomic, strong, nullable) SentrySamplerDecision *profilesSamplerDecision; - -/** - * For launch continuous v2 profiles that must start for trace lifecycle, we must explicitly be able - * to indicate that to the tracer here, since there's no hub or options attached to it for the - * profiler system to know whether it's a old-style trace profile or a trace continuous v2 profile. - */ -@property (nonatomic, strong, nullable) SentryProfileOptions *profileOptions; #endif // SENTRY_TARGET_PROFILING_SUPPORTED" /** diff --git a/Sources/Sentry/include/SentryUIApplication.h b/Sources/Sentry/include/SentryUIApplication.h deleted file mode 100644 index c467e86a1e0..00000000000 --- a/Sources/Sentry/include/SentryUIApplication.h +++ /dev/null @@ -1,32 +0,0 @@ -#import "SentryApplication.h" -#import "SentryDefines.h" - -#if SENTRY_HAS_UIKIT - -@class UIApplication; -@class UIScene; -@class UIWindow; -@class UIViewController; -@class SentryNSNotificationCenterWrapper; -@class SentryDispatchQueueWrapper; -@protocol UIApplicationDelegate; - -typedef NS_ENUM(NSInteger, UIApplicationState); - -NS_ASSUME_NONNULL_BEGIN - -/** - * A helper tool to retrieve informations from the application instance. - */ -@interface SentryUIApplication : NSObject -SENTRY_NO_INIT - -- (instancetype) - initWithNotificationCenterWrapper:(SentryNSNotificationCenterWrapper *)notificationCenterWrapper - dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper; - -@end - -NS_ASSUME_NONNULL_END - -#endif // SENTRY_HAS_UIKIT diff --git a/Sources/Sentry/include/SentryUIDeviceWrapper.h b/Sources/Sentry/include/SentryUIDeviceWrapper.h deleted file mode 100644 index 5dca34d5587..00000000000 --- a/Sources/Sentry/include/SentryUIDeviceWrapper.h +++ /dev/null @@ -1,27 +0,0 @@ -#import "SentryDefines.h" - -#if SENTRY_HAS_UIKIT - -# import - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryUIDeviceWrapper : NSObject - -- (void)start; -- (void)stop; - -# if TARGET_OS_IOS -- (UIDeviceOrientation)orientation; -- (BOOL)isBatteryMonitoringEnabled; -- (UIDeviceBatteryState)batteryState; -- (float)batteryLevel; -# endif // TARGET_OS_IOS - -- (NSString *)getSystemVersion; - -@end - -NS_ASSUME_NONNULL_END - -#endif // SENTRY_HAS_UIKIT diff --git a/Sources/Sentry/include/SentryUIViewControllerSwizzling.h b/Sources/Sentry/include/SentryUIViewControllerSwizzling.h index 0c43472352b..b1f4100cc80 100644 --- a/Sources/Sentry/include/SentryUIViewControllerSwizzling.h +++ b/Sources/Sentry/include/SentryUIViewControllerSwizzling.h @@ -2,14 +2,15 @@ #if SENTRY_HAS_UIKIT -# import "SentryObjCRuntimeWrapper.h" # import NS_ASSUME_NONNULL_BEGIN +@protocol SentryObjCRuntimeWrapper; +@protocol SentryProcessInfoSource; + @class SentryBinaryImageCache; @class SentryDispatchQueueWrapper; -@class SentryNSProcessInfoWrapper; @class SentryOptions; @class SentrySubClassFinder; @@ -34,7 +35,7 @@ SENTRY_NO_INIT dispatchQueue:(SentryDispatchQueueWrapper *)dispatchQueue objcRuntimeWrapper:(id)objcRuntimeWrapper subClassFinder:(SentrySubClassFinder *)subClassFinder - processInfoWrapper:(SentryNSProcessInfoWrapper *)processInfoWrapper + processInfoWrapper:(id)processInfoWrapper binaryImageCache:(SentryBinaryImageCache *)binaryImageCache; - (void)start; diff --git a/Sources/Sentry/include/SentryUser+Serialize.h b/Sources/Sentry/include/SentryUser+Serialize.h new file mode 100644 index 00000000000..0d5aa94a921 --- /dev/null +++ b/Sources/Sentry/include/SentryUser+Serialize.h @@ -0,0 +1,8 @@ +#if SDK_V9 +# import "SentrySerializable.h" +# import "SentryUser.h" + +@interface SentryUser () + +@end +#endif // SDK_V9 diff --git a/Sources/Sentry/include/SentryUserFeedbackIntegration.h b/Sources/Sentry/include/SentryUserFeedbackIntegration.h index 2425cdbd6f5..9685d35d244 100644 --- a/Sources/Sentry/include/SentryUserFeedbackIntegration.h +++ b/Sources/Sentry/include/SentryUserFeedbackIntegration.h @@ -7,6 +7,7 @@ NS_ASSUME_NONNULL_BEGIN API_AVAILABLE(ios(13.0)) +NS_EXTENSION_UNAVAILABLE("Sentry User Feedback UI cannot be used from app extensions.") @interface SentryUserFeedbackIntegration : SentryBaseIntegration - (void)showWidget; - (void)hideWidget; diff --git a/Sources/Sentry/include/_SentryDispatchQueueWrapperInternal.h b/Sources/Sentry/include/_SentryDispatchQueueWrapperInternal.h index 8c4d8652639..8f06e2d3b05 100644 --- a/Sources/Sentry/include/_SentryDispatchQueueWrapperInternal.h +++ b/Sources/Sentry/include/_SentryDispatchQueueWrapperInternal.h @@ -4,7 +4,7 @@ NS_ASSUME_NONNULL_BEGIN /** * A wrapper around DispatchQueue functions for testability. - * This should not be used directly, instead the Swift version in + * This should not be used directly, instead the Swift version in * SentryDispatchQueueWrapper should be used to ensure compatibility * with Swift code. */ diff --git a/Sources/SentryCppHelper/SentryCppHelper.swift b/Sources/SentryCppHelper/SentryCppHelper.swift new file mode 100644 index 00000000000..725a69faee5 --- /dev/null +++ b/Sources/SentryCppHelper/SentryCppHelper.swift @@ -0,0 +1 @@ +// No content needed, we just need this empty file diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_System.m b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_System.m index 2114ee16b19..3a176c0fce0 100644 --- a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_System.m +++ b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_System.m @@ -37,6 +37,7 @@ #import "SentryLogC.h" #import "SentryDefines.h" +#import "SentrySwift.h" #import #include @@ -460,15 +461,6 @@ return isAppStoreReceipt && receiptExists; } -/** - * Check if the app has an embdded.mobileprovision file in the bundle. - */ -static bool -hasEmbeddedMobileProvision(void) -{ - return [[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"] != nil; -} - static const char * getBuildType(void) { @@ -478,8 +470,9 @@ if (isDebugBuild()) { return "debug"; } - if (hasEmbeddedMobileProvision()) { - return "enterprise"; + SentryMobileProvisionParser *parser = [[SentryMobileProvisionParser alloc] init]; + if ([parser hasEmbeddedMobileProvisionProfile]) { + return [parser mobileProvisionProfileProvisionsAllDevices] ? "enterprise" : "adhoc"; } if (isTestBuild()) { return "test"; diff --git a/Sources/SentryCrash/Recording/SentryBinaryImageCacheCallbacks.m b/Sources/SentryCrash/Recording/SentryBinaryImageCacheCallbacks.m new file mode 100644 index 00000000000..c0a9c4f699b --- /dev/null +++ b/Sources/SentryCrash/Recording/SentryBinaryImageCacheCallbacks.m @@ -0,0 +1,30 @@ +#import "SentryBinaryImageCacheCallbacks.h" +#import "SentryDependencyContainer.h" +#import "SentryInternalDefines.h" +#import "SentrySwift.h" + +// Used to call SentryDependencyContainer, since it isn't available to swift yet +void +binaryImageWasAdded(const SentryCrashBinaryImage *_Nullable image) +{ + if (image == NULL) { + SENTRY_LOG_WARN(@"The image is NULL. Can't add NULL to cache."); + return; + } + [SentryDependencyContainer.sharedInstance.binaryImageCache binaryImageAdded:image->name + vmAddress:image->vmAddress + address:image->address + size:image->size + uuid:image->uuid]; +} + +// Used to call SentryDependencyContainer, since it isn't available to swift yet +void +binaryImageWasRemoved(const SentryCrashBinaryImage *_Nullable image) +{ + if (image == NULL) { + SENTRY_LOG_WARN(@"The image is NULL. Can't remove it from the cache."); + return; + } + [SentryDependencyContainer.sharedInstance.binaryImageCache binaryImageRemoved:image->address]; +} diff --git a/Sources/SentryCrash/Recording/SentryCrash.m b/Sources/SentryCrash/Recording/SentryCrash.m index bb119ab299f..07a7aedd476 100644 --- a/Sources/SentryCrash/Recording/SentryCrash.m +++ b/Sources/SentryCrash/Recording/SentryCrash.m @@ -39,7 +39,7 @@ #import "SentryDefines.h" #import "SentryDependencyContainer.h" #import "SentryInternalCDefines.h" -#import "SentryNSNotificationCenterWrapper.h" +#import "SentrySwift.h" #import #import "SentryLogC.h" @@ -238,39 +238,48 @@ - (BOOL)install } #if SENTRY_HAS_UIKIT - SentryNSNotificationCenterWrapper *notificationCenter + id notificationCenter = SentryDependencyContainer.sharedInstance.notificationCenterWrapper; [notificationCenter addObserver:self selector:@selector(applicationDidBecomeActive) - name:UIApplicationDidBecomeActiveNotification]; + name:UIApplicationDidBecomeActiveNotification + object:nil]; [notificationCenter addObserver:self selector:@selector(applicationWillResignActive) - name:UIApplicationWillResignActiveNotification]; + name:UIApplicationWillResignActiveNotification + object:nil]; [notificationCenter addObserver:self selector:@selector(applicationDidEnterBackground) - name:UIApplicationDidEnterBackgroundNotification]; + name:UIApplicationDidEnterBackgroundNotification + object:nil]; [notificationCenter addObserver:self selector:@selector(applicationWillEnterForeground) - name:UIApplicationWillEnterForegroundNotification]; + name:UIApplicationWillEnterForegroundNotification + object:nil]; [notificationCenter addObserver:self selector:@selector(applicationWillTerminate) - name:UIApplicationWillTerminateNotification]; + name:UIApplicationWillTerminateNotification + object:nil]; #endif // SENTRY_HAS_UIKIT #if SENTRY_HAS_NSEXTENSION - SentryNSNotificationCenterWrapper *notificationCenter + id notificationCenter = SentryDependencyContainer.sharedInstance.notificationCenterWrapper; [notificationCenter addObserver:self selector:@selector(applicationDidBecomeActive) - name:NSExtensionHostDidBecomeActiveNotification]; + name:NSExtensionHostDidBecomeActiveNotification + object:nil]; [notificationCenter addObserver:self selector:@selector(applicationWillResignActive) - name:NSExtensionHostWillResignActiveNotification]; + name:NSExtensionHostWillResignActiveNotification + object:nil]; [notificationCenter addObserver:self selector:@selector(applicationDidEnterBackground) - name:NSExtensionHostDidEnterBackgroundNotification]; + name:NSExtensionHostDidEnterBackgroundNotification + object:nil]; [notificationCenter addObserver:self selector:@selector(applicationWillEnterForeground) - name:NSExtensionHostWillEnterForegroundNotification]; + name:NSExtensionHostWillEnterForegroundNotification + object:nil]; #endif // SENTRY_HAS_NSEXTENSION return true; @@ -285,21 +294,37 @@ - (void)uninstall sentrycrash_uninstall(); #if SENTRY_HAS_UIKIT - SentryNSNotificationCenterWrapper *notificationCenter + id notificationCenter = SentryDependencyContainer.sharedInstance.notificationCenterWrapper; - [notificationCenter removeObserver:self name:UIApplicationDidBecomeActiveNotification]; - [notificationCenter removeObserver:self name:UIApplicationWillResignActiveNotification]; - [notificationCenter removeObserver:self name:UIApplicationDidEnterBackgroundNotification]; - [notificationCenter removeObserver:self name:UIApplicationWillEnterForegroundNotification]; - [notificationCenter removeObserver:self name:UIApplicationWillTerminateNotification]; + [notificationCenter removeObserver:self + name:UIApplicationDidBecomeActiveNotification + object:nil]; + [notificationCenter removeObserver:self + name:UIApplicationWillResignActiveNotification + object:nil]; + [notificationCenter removeObserver:self + name:UIApplicationDidEnterBackgroundNotification + object:nil]; + [notificationCenter removeObserver:self + name:UIApplicationWillEnterForegroundNotification + object:nil]; + [notificationCenter removeObserver:self name:UIApplicationWillTerminateNotification object:nil]; #endif // SENTRY_HAS_UIKIT #if SENTRY_HAS_NSEXTENSION - SentryNSNotificationCenterWrapper *notificationCenter + id notificationCenter = SentryDependencyContainer.sharedInstance.notificationCenterWrapper; - [notificationCenter removeObserver:self name:NSExtensionHostDidBecomeActiveNotification]; - [notificationCenter removeObserver:self name:NSExtensionHostWillResignActiveNotification]; - [notificationCenter removeObserver:self name:NSExtensionHostDidEnterBackgroundNotification]; - [notificationCenter removeObserver:self name:NSExtensionHostWillEnterForegroundNotification]; + [notificationCenter removeObserver:self + name:NSExtensionHostDidBecomeActiveNotification + object:nil]; + [notificationCenter removeObserver:self + name:NSExtensionHostWillResignActiveNotification + object:nil]; + [notificationCenter removeObserver:self + name:NSExtensionHostDidEnterBackgroundNotification + object:nil]; + [notificationCenter removeObserver:self + name:NSExtensionHostWillEnterForegroundNotification + object:nil]; #endif } diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashDynamicLinker.c b/Sources/SentryCrash/Recording/Tools/SentryCrashDynamicLinker.c index 23a08330367..9b26b801822 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashDynamicLinker.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashDynamicLinker.c @@ -480,6 +480,7 @@ getCrashInfo(const struct mach_header *header, SentryCrashBinaryImage *buffer) } } +#if !SDK_V9 int sentrycrashdl_imageCount(void) { @@ -497,6 +498,7 @@ sentrycrashdl_getBinaryImage(int index, SentryCrashBinaryImage *buffer, bool isC const char *imageName = _dyld_get_image_name((unsigned)index); return sentrycrashdl_getBinaryImageForHeader((const void *)header, imageName, buffer, isCrash); } +#endif // !SDK_V9 void sentrycrashdl_getCrashInfo(uint64_t address, SentryCrashBinaryImage *buffer) diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor.c b/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor.c index 1e34e690ef6..3f42e83a584 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor.c @@ -56,7 +56,7 @@ void sentrycrashsc_initCursor(SentryCrashStackCursor *cursor, void (*resetCursor)(SentryCrashStackCursor *), bool (*advanceCursor)(SentryCrashStackCursor *)) { - cursor->symbolicate = sentrycrashsymbolicator_symbolicate; + cursor->symbolicate = sentrycrashsymbolicator_symbolicate_async_unsafe_sentryDlAddr; cursor->advanceCursor = advanceCursor != NULL ? advanceCursor : g_advanceCursor; cursor->resetCursor = resetCursor != NULL ? resetCursor : sentrycrashsc_resetCursor; cursor->resetCursor(cursor); diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashSymbolicator.c b/Sources/SentryCrash/Recording/Tools/SentryCrashSymbolicator.c index b3132694d95..ed6b9e026e0 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashSymbolicator.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashSymbolicator.c @@ -51,7 +51,7 @@ #define CALL_INSTRUCTION_FROM_RETURN_ADDRESS(A) (DETAG_INSTRUCTION_ADDRESS((A)) - 1) static bool -symbolicate_internal(SentryCrashStackCursor *cursor, bool asyncUnsafe) +symbolicate_internal(SentryCrashStackCursor *cursor, bool useDlAddr) { if (cursor->stackEntry.address == SentryCrashSC_ASYNC_MARKER) { cursor->stackEntry.imageAddress = 0; @@ -65,7 +65,7 @@ symbolicate_internal(SentryCrashStackCursor *cursor, bool asyncUnsafe) bool symbols_succeed = false; - if (asyncUnsafe) { + if (useDlAddr) { symbols_succeed = dladdr((void *)cursor->stackEntry.address, &symbolsBuffer) != 0; } else { // sentrycrashdl_dladdr isn't async safe, but we've been using it for @@ -91,13 +91,15 @@ symbolicate_internal(SentryCrashStackCursor *cursor, bool asyncUnsafe) } bool -sentrycrashsymbolicator_symbolicate(SentryCrashStackCursor *cursor) +sentrycrashsymbolicator_symbolicate_async_unsafe_sentryDlAddr(SentryCrashStackCursor *cursor) { + // Symbolicate using `sentrycrashdl_dladdr` note this is not async-signal-safe return symbolicate_internal(cursor, false); } bool sentrycrashsymbolicator_symbolicate_async_unsafe(SentryCrashStackCursor *cursor) { + // Symbolicate using `dladdr` note this is not async-signal-safe return symbolicate_internal(cursor, true); } diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashSymbolicator.h b/Sources/SentryCrash/Recording/Tools/SentryCrashSymbolicator.h index 7994cdefe9b..07d93bece74 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashSymbolicator.h +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashSymbolicator.h @@ -39,9 +39,9 @@ extern "C" { * * @return True if successful. */ -bool sentrycrashsymbolicator_symbolicate(SentryCrashStackCursor *cursor); +bool sentrycrashsymbolicator_symbolicate_async_unsafe_sentryDlAddr(SentryCrashStackCursor *cursor); -/** Same as ``sentrycrashsymbolicator_symbolicate`` but faster and async unsafe. +/** Same as ``sentrycrashsymbolicator_symbolicate_async_unsafe_sentryDlAddr`` but faster. */ bool sentrycrashsymbolicator_symbolicate_async_unsafe(SentryCrashStackCursor *cursor); diff --git a/Sources/SentrySwiftUI/Preview/SentryReplayMaskPreview.swift b/Sources/SentrySwiftUI/Preview/SentryReplayMaskPreview.swift index 6b5775b1135..240e9109bd7 100644 --- a/Sources/SentrySwiftUI/Preview/SentryReplayMaskPreview.swift +++ b/Sources/SentrySwiftUI/Preview/SentryReplayMaskPreview.swift @@ -19,7 +19,7 @@ struct SentryReplayMaskPreview: ViewModifier { @available(iOS 13, macOS 10.15, tvOS 13, *) public extension View { func sentryReplayPreviewMask(redactOptions: SentryRedactOptions? = nil, opacity: Float = 1) -> some View { - let options = redactOptions ?? SentrySDK.options?.sessionReplay ?? PreviewRedactOptions() + let options = redactOptions ?? SentrySDKInternal.options?.sessionReplay ?? PreviewRedactOptions() return modifier(SentryReplayMaskPreview(redactOptions: options, opacity: opacity)) } } diff --git a/Sources/SentrySwiftUI/SentryInternal/SentryInternal.h b/Sources/SentrySwiftUI/SentryInternal/SentryInternal.h index b914e3ae87b..fc06436d6a9 100644 --- a/Sources/SentrySwiftUI/SentryInternal/SentryInternal.h +++ b/Sources/SentrySwiftUI/SentryInternal/SentryInternal.h @@ -13,6 +13,10 @@ # import "Sentry.h" #endif +#if __has_include("SentrySDKInternal.h") +# include "SentrySDKInternal.h" +#endif + #if SENTRY_TEST # import "SentrySpan.h" # import "SentryTracer.h" @@ -109,8 +113,16 @@ typedef NS_ENUM(NSUInteger, SentrySpanStatus); @end -@interface SentrySDK () +#if __has_include("SentrySDKInternal.h") +@interface SentrySDKInternal () +#else +@interface SentrySDKInternal : NSObject +#endif + @property (nonatomic, nullable, readonly, class) SentryOptions *options; ++ (void)setCurrentHub:(nullable SentryHub *)hub; ++ (void)setStartOptions:(nullable SentryOptions *)options NS_SWIFT_NAME(setStart(with:)); + @end NS_ASSUME_NONNULL_END diff --git a/Sources/SentrySwiftUI/SentryTracedView.swift b/Sources/SentrySwiftUI/SentryTracedView.swift index fa74e81fa76..9aefb7ad346 100644 --- a/Sources/SentrySwiftUI/SentryTracedView.swift +++ b/Sources/SentrySwiftUI/SentryTracedView.swift @@ -21,7 +21,7 @@ class SentryTraceViewModel { init(name: String, nameSource: SentryTransactionNameSource, waitForFullDisplay: Bool?) { self.name = name self.nameSource = nameSource - self.waitForFullDisplay = waitForFullDisplay ?? SentrySDK.options?.enableTimeToFullDisplayTracing ?? false + self.waitForFullDisplay = waitForFullDisplay ?? SentrySDKInternal.options?.enableTimeToFullDisplayTracing ?? false } func startSpan() -> SpanId? { diff --git a/Sources/SentrySwiftUI/module.modulemap b/Sources/SentrySwiftUI/module.modulemap index fc8127e7198..22e0f41c1b1 100644 --- a/Sources/SentrySwiftUI/module.modulemap +++ b/Sources/SentrySwiftUI/module.modulemap @@ -1,4 +1,3 @@ module SentryInternal { header "SentrySwiftUI.h" } - diff --git a/Sources/Swift/Core/Helper/Log/SentryLevel.swift b/Sources/Swift/Core/Helper/Log/SentryLevel.swift index 2a0f3fe01c4..0e1970b9d05 100644 --- a/Sources/Swift/Core/Helper/Log/SentryLevel.swift +++ b/Sources/Swift/Core/Helper/Log/SentryLevel.swift @@ -29,8 +29,8 @@ extension SentryLevel: CustomStringConvertible { return SentryLevel.levelNames[Int(self.rawValue)] } - static func fromName(_ name: String) -> SentryLevel { - guard let index = SentryLevel.levelNames.firstIndex(of: name) else { return .error } + static func fromName(_ name: String?) -> SentryLevel { + guard let name = name, let index = SentryLevel.levelNames.firstIndex(of: name) else { return .error } return SentryLevel(rawValue: UInt(index)) ?? .error } } @@ -41,7 +41,7 @@ extension SentryLevel: CustomStringConvertible { return level.description } - public static func levelForName(_ name: String) -> SentryLevel { + public static func levelForName(_ name: String?) -> SentryLevel { .fromName(name) } } diff --git a/Sources/Swift/Core/Helper/SentryBaggageSerialization.swift b/Sources/Swift/Core/Helper/SentryBaggageSerialization.swift index 63361f1cafe..7c3714f4524 100644 --- a/Sources/Swift/Core/Helper/SentryBaggageSerialization.swift +++ b/Sources/Swift/Core/Helper/SentryBaggageSerialization.swift @@ -4,13 +4,16 @@ import Foundation @_spi(Private) public class SentryBaggageSerialization: NSObject { private static let SENTRY_BAGGAGE_MAX_SIZE = 8_192 + private static let allowedSet = { + var allowedSet = CharacterSet.alphanumerics + allowedSet.insert(charactersIn: "-_.") + return allowedSet + }() public static func encodeDictionary(_ dictionary: [String: String]) -> String { var items: [String] = [] items.reserveCapacity(dictionary.count) - var allowedSet = CharacterSet.alphanumerics - allowedSet.insert(charactersIn: "-_.") var currentSize = 0 for (key, value) in dictionary { diff --git a/Sources/Swift/Core/Helper/SentryBinaryImageCache.swift b/Sources/Swift/Core/Helper/SentryBinaryImageCache.swift new file mode 100644 index 00000000000..9c60d461b80 --- /dev/null +++ b/Sources/Swift/Core/Helper/SentryBinaryImageCache.swift @@ -0,0 +1,175 @@ +@_implementationOnly import _SentryPrivate +import Foundation + +@objc(SentryBinaryImageInfo) +@_spi(Private) public final class SentryBinaryImageInfo: NSObject { + @objc public var name: String + @objc public var uuid: String? + @objc public var vmAddress: UInt64 + @objc public var address: UInt64 + @objc public var size: UInt64 + + @objc public init(name: String, uuid: String?, vmAddress: UInt64, address: UInt64, size: UInt64) { + self.name = name + self.uuid = uuid + self.vmAddress = vmAddress + self.address = address + self.size = size + super.init() + } +} + +/** + * This class listens to `SentryCrashBinaryImageCache` to keep a copy of the loaded binaries + * information in a sorted collection that will be used to symbolicate frames with better + * performance. + */ +@objc(SentryBinaryImageCache) +@_spi(Private) public final class SentryBinaryImageCache: NSObject { + @objc public internal(set) var cache: [SentryBinaryImageInfo]? + private var isDebug: Bool = false + // Use a recursive lock to allow the same thread to enter again + private let lock = NSRecursiveLock() + + @objc public func start(_ isDebug: Bool) { + lock.synchronized { + self.isDebug = isDebug + self.cache = [] + sentrycrashbic_registerAddedCallback(binaryImageWasAdded) + sentrycrashbic_registerRemovedCallback(binaryImageWasRemoved) + } + } + + @objc public func stop() { + lock.synchronized { + sentrycrashbic_registerAddedCallback(nil) + sentrycrashbic_registerRemovedCallback(nil) + self.cache = nil + } + } + + // We have to expand `SentryCrashBinaryImage` since the model is defined in SentryPrivate + @objc(binaryImageAdded:vmAddress:address:size:uuid:) + public func binaryImageAdded(imageName: UnsafePointer?, + vmAddress: UInt64, + address: UInt64, + size: UInt64, + uuid: UnsafePointer?) { + guard let imageName else { + SentrySDKLog.warning("The image name was NULL. Can't add image to cache.") + return + } + guard let nameString = String(cString: imageName, encoding: .utf8) else { + SentrySDKLog.warning("Couldn't convert the cString image name to an NSString. This could be due to a different encoding than NSUTF8StringEncoding of the cString..") + return + } + + let newImage = SentryBinaryImageInfo( + name: nameString, + uuid: Self.convertUUID(uuid), + vmAddress: vmAddress, + address: address, + size: size + ) + + lock.synchronized { + guard let cache = self.cache else { return } + + // Binary search insertion to maintain sorted order by address + var left = 0 + var right = cache.count + + while left < right { + let mid = (left + right) / 2 + let compareImage = cache[mid] + if newImage.address < compareImage.address { + right = mid + } else { + left = mid + 1 + } + } + + self.cache?.insert(newImage, at: left) + } + + if isDebug { + // This validation adds some overhead with each class present in the image, so we only + // run this when debug is enabled. A non main queue is used to avoid affecting the UI. + LoadValidator.checkForDuplicatedSDK(imageName: nameString, + imageAddress: NSNumber(value: newImage.address), + imageSize: NSNumber(value: newImage.size), + objcRuntimeWrapper: Dependencies.objcRuntimeWrapper, + dispatchQueueWrapper: Dependencies.dispatchQueueWrapper) + } + } + + @objc + public static func convertUUID(_ value: UnsafePointer?) -> String? { + guard let value = value else { return nil } + + var uuidBuffer = [CChar](repeating: 0, count: 37) + sentrycrashdl_convertBinaryImageUUID(value, &uuidBuffer) + return String(cString: uuidBuffer, encoding: .ascii) + } + + @objc + public func binaryImageRemoved(_ imageAddress: UInt64) { + lock.synchronized { + guard let index = indexOfImage(address: imageAddress) else { return } + self.cache?.remove(at: index) + } + } + + @objc + public func imageByAddress(_ address: UInt64) -> SentryBinaryImageInfo? { + lock.synchronized { + guard let index = indexOfImage(address: address) else { return nil } + return cache?[index] + } + } + + private func indexOfImage(address: UInt64) -> Int? { + guard let cache = self.cache else { return nil } + + var left = 0 + var right = cache.count - 1 + + while left <= right { + let mid = (left + right) / 2 + let image = cache[mid] + + if address >= image.address && address < (image.address + image.size) { + return mid + } else if address < image.address { + right = mid - 1 + } else { + left = mid + 1 + } + } + + return nil + } + + @objc(imagePathsForInAppInclude:) + public func imagePathsFor(inAppInclude: String) -> Set { + lock.synchronized { + var imagePaths = Set() + + guard let cache = self.cache else { return imagePaths } + + for info in cache { + if SentryInAppLogic.isImageNameInApp(info.name, inAppInclude: inAppInclude) { + imagePaths.insert(info.name) + } + } + return imagePaths + } + } + + @objc + public func getAllBinaryImages() -> [SentryBinaryImageInfo] { + lock.synchronized { + return cache ?? [] + } + } +} diff --git a/Sources/Swift/Core/Helper/SentryExtraPackages.swift b/Sources/Swift/Core/Helper/SentryExtraPackages.swift index 791e6be7c13..739f101a903 100644 --- a/Sources/Swift/Core/Helper/SentryExtraPackages.swift +++ b/Sources/Swift/Core/Helper/SentryExtraPackages.swift @@ -17,10 +17,9 @@ import Foundation } } - @objc - public static func getPackages() -> NSMutableSet { + static func getPackages() -> Set<[String: String]> { lock.synchronized { - NSMutableSet(set: extraPackages as NSSet) + Set(extraPackages) } } diff --git a/Sources/Swift/Core/Helper/SentryInAppLogic.swift b/Sources/Swift/Core/Helper/SentryInAppLogic.swift new file mode 100644 index 00000000000..462356275a2 --- /dev/null +++ b/Sources/Swift/Core/Helper/SentryInAppLogic.swift @@ -0,0 +1,113 @@ +import Foundation +import ObjectiveC + +/** + * This class detects whether a framework belongs to the app or not. We differentiate between three + * different types of frameworks. + * + * First, the main executable of the app, which's name can be retrieved by @c CFBundleExecutable. To + * mark this framework as "in-app" the caller needs to pass in the @c CFBundleExecutable to + * @c inAppIncludes. + * + * Next, there are private frameworks embedded in the application bundle. Both app supporting + * frameworks as CocoaLumberJack, Sentry, RXSwift, etc., and frameworks written by the user fall + * into this category. These frameworks can be both "in-app" or not. As we expect most frameworks of + * this category to be supporting frameworks, we mark them not as "in-app". If a user wants such a + * framework to be "in-app", they need to pass the name into @c inAppIncludes. For dynamic + * frameworks, the location is usually in the bundle under + * /Frameworks/FrameworkName.framework/FrameworkName. As for static frameworks, the location is the + * same as the main executable; this class marks all static frameworks as "in-app". To remove static + * frameworks from being "in-app", Sentry uses stack trace grouping rules on the server. + * + * Last, this class marks all public frameworks as not "in-app". Such frameworks are bound + * dynamically and are usually located at /Library/Frameworks or ~/Library/Frameworks. For + * simulators, the location can be something like + * /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/... + * + */ +@objc @_spi(Private) public class SentryInAppLogic: NSObject { + + @objc public let inAppIncludes: [String] + private let inAppExcludes: [String] + + /** + * Initializes @c SentryInAppLogic with @c inAppIncludes and @c inAppExcludes. + * + * To work properly for Apple applications the @c inAppIncludes should contain the + * @c CFBundleExecutable, which is the name of the bundle's executable file. + * + * @param inAppIncludes A list of string prefixes of framework names that belong to the app. This + * option takes precedence over @c inAppExcludes. + * @param inAppExcludes A list of string prefixes of framework names that do not belong to the app, + * but rather to third-party packages. Modules considered not part of the app will be hidden from + * stack traces by default. + */ + @objc(initWithInAppIncludes:inAppExcludes:) public init(inAppIncludes: [String], inAppExcludes: [String]) { + self.inAppIncludes = inAppIncludes.map { $0.lowercased() } + self.inAppExcludes = inAppExcludes.map { $0.lowercased() } + super.init() + } + + /** + * Determines if the framework belongs to the app by using @c inAppIncludes and @c inAppExcludes. + * Before checking this method lowercases the strings and uses only the @c lastPathComponent of the + * @c imagePath. + * + * @param imagePath the full path of the binary image. + * + * @return @c YES if the framework located at the @c imagePath starts with a prefix of + * @c inAppIncludes. @c NO if the framework located at the @c imagePath doesn't start with a prefix of + * @c inAppIncludes or start with a prefix of @c inAppExcludes. + */ + @objc public func `is`(inApp imagePath: String?) -> Bool { + guard let imagePath else { + return false + } + + let imageNameLastPathComponent = (imagePath as NSString).lastPathComponent.lowercased() + + for inAppInclude in inAppIncludes { + if Self.isImageNameLastPathComponentInApp(imageNameLastPathComponent, inAppInclude: inAppInclude) { + return true + } + } + + for inAppExclude in inAppExcludes { + if imageNameLastPathComponent.hasPrefix(inAppExclude) { + return false + } + } + + return false + } + + /** + * Determines if the class belongs to the app by getting its framework and checking with + * @c -[isInApp:] + * + * @param targetClass the class to check. + * + * @return @c YES if the @c targetClass belongs to a framework included in @c inAppIncludes. + * @c NO if targetClass does not belong to a framework in @c inAppIncludes or belongs to a framework in + * @c inAppExcludes. + */ + @objc public func isClassInApp(_ targetClass: AnyClass) -> Bool { + guard let imageName = class_getImageName(targetClass) else { + return false + } + + let classImageName = String(cString: imageName, encoding: .utf8) + return `is`(inApp: classImageName) + } + + @objc public static func isImageNameInApp(_ imageName: String, inAppInclude: String) -> Bool { + return isImageNameLastPathComponentInApp( + (imageName as NSString).lastPathComponent.lowercased(), + inAppInclude: inAppInclude.lowercased() + ) + } + + private static func isImageNameLastPathComponentInApp(_ imageNameLastPathComponent: String, inAppInclude: String) -> Bool { + return imageNameLastPathComponent.hasPrefix(inAppInclude) + } +} diff --git a/Sources/Swift/Core/Helper/SentryUIDeviceWrapper.swift b/Sources/Swift/Core/Helper/SentryUIDeviceWrapper.swift new file mode 100644 index 00000000000..690d2192236 --- /dev/null +++ b/Sources/Swift/Core/Helper/SentryUIDeviceWrapper.swift @@ -0,0 +1,99 @@ +#if !os(watchOS) && !os(macOS) && !SENTRY_NO_UIKIT +import UIKit + +@_spi(Private) @objc public protocol SentryUIDeviceWrapper { + func start() + func stop() + func getSystemVersion() -> String + +#if os(iOS) + var orientation: UIDeviceOrientation { get } + var isBatteryMonitoringEnabled: Bool { get } + var batteryState: UIDevice.BatteryState { get } + var batteryLevel: Float { get } +#endif +} + +@_spi(Private) @objc public final class SentryDefaultUIDeviceWrapper: NSObject, SentryUIDeviceWrapper { + + private let queueWrapper: SentryDispatchQueueWrapper + private var systemVersion = "" + private var cleanupBatteryMonitoring = false + private var cleanupDeviceOrientationNotifications = false + + // This one shouldn't be used because it acceccess `Dependencies` directly rather than being + // initialized with dependencies, but since we need to sublcass NSObject it has to be here. + @available(*, unavailable) + override convenience init() { + self.init(queueWrapper: Dependencies.dispatchQueueWrapper) + } + + @objc public init(queueWrapper: SentryDispatchQueueWrapper) { + self.queueWrapper = queueWrapper + } + + @objc public func start() { + queueWrapper.dispatchAsyncOnMainQueue { [weak self] in + guard let self else { return } +#if os(iOS) + if !UIDevice.current.isGeneratingDeviceOrientationNotifications { + self.cleanupDeviceOrientationNotifications = true + UIDevice.current.beginGeneratingDeviceOrientationNotifications() + } + + // Needed so we can read the battery level + if !UIDevice.current.isBatteryMonitoringEnabled { + self.cleanupBatteryMonitoring = true + UIDevice.current.isBatteryMonitoringEnabled = true + } +#endif + + self.systemVersion = UIDevice.current.systemVersion + } + } + + @objc public func stop() { + #if os(iOS) + let needsCleanup = self.cleanupDeviceOrientationNotifications + let needsDisablingBattery = self.cleanupBatteryMonitoring + let device = UIDevice.current + queueWrapper.dispatchAsyncOnMainQueue { + if needsCleanup { + device.endGeneratingDeviceOrientationNotifications() + } + if needsDisablingBattery { + device.isBatteryMonitoringEnabled = false + } + } + #endif + } + + deinit { + stop() + } + + #if os(iOS) + @objc public var orientation: UIDeviceOrientation { + UIDevice.current.orientation + } + + @objc public var isBatteryMonitoringEnabled: Bool { + UIDevice.current.isBatteryMonitoringEnabled + } + + @objc public var batteryState: UIDevice.BatteryState { + UIDevice.current.batteryState + } + + @objc public var batteryLevel: Float { + UIDevice.current.batteryLevel + } + + #endif // os(iOS) + + @objc public func getSystemVersion() -> String { + systemVersion + } + +} +#endif diff --git a/Sources/Swift/Core/MetricKit/SentryMXManager.swift b/Sources/Swift/Core/MetricKit/SentryMXManager.swift index f77710d3412..6c80d895089 100644 --- a/Sources/Swift/Core/MetricKit/SentryMXManager.swift +++ b/Sources/Swift/Core/MetricKit/SentryMXManager.swift @@ -2,12 +2,7 @@ import Foundation #if os(iOS) || os(macOS) -/** - * We need to check if MetricKit is available for compatibility on iOS 12 and below. As there are no compiler directives for iOS versions we use canImport. - */ -#if canImport(MetricKit) import MetricKit -#endif @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, *) @available(tvOS, unavailable) diff --git a/Sources/Swift/Tools/SentryScreenshot.swift b/Sources/Swift/Core/Tools/ViewCapture/SentryScreenshotSource.swift similarity index 84% rename from Sources/Swift/Tools/SentryScreenshot.swift rename to Sources/Swift/Core/Tools/ViewCapture/SentryScreenshotSource.swift index 4e7919e3006..590928ad503 100644 --- a/Sources/Swift/Tools/SentryScreenshot.swift +++ b/Sources/Swift/Core/Tools/ViewCapture/SentryScreenshotSource.swift @@ -5,42 +5,51 @@ import UIKit @objcMembers -@_spi(Private) public class SentryScreenshot: NSObject { +@_spi(Private) public class SentryScreenshotSource: NSObject { private let photographer: SentryViewPhotographer - - public override init() { - photographer = SentryViewPhotographer( + + public override convenience init() { + // We need to provide a init method without parameters for Obj-C compatibility. + // However, we want to force users to provide a photographer. + // `assertionFailure` will not crash the app in release builds, but at least + // it notifies the developer during testing and development. + assertionFailure("Use init(photographer:) instead") + self.init(photographer: SentryViewPhotographer( renderer: SentryDefaultViewRenderer(), redactOptions: SentryRedactDefaultOptions(), enableMaskRendererV2: false - ) + )) + } + + public init(photographer: SentryViewPhotographer) { + self.photographer = photographer super.init() } - + /// Get a screenshot of every open window in the app. /// - Returns: An array of UIImage instances. public func appScreenshotsFromMainThread() -> [UIImage] { var result: [UIImage] = [] - + let takeScreenShot = { result = self.appScreenshots() } - + SentryDependencyContainerSwiftHelper.dispatchSync(onMainQueue: takeScreenShot) - + return result } - + /// Get a screenshot of every open window in the app. /// - Returns: An array of Data instances containing PNG images. public func appScreenshotDatasFromMainThread() -> [Data] { var result: [Data] = [] - + let takeScreenShot = { result = self.appScreenshotsData() } - + SentryDependencyContainerSwiftHelper.dispatchSync(onMainQueue: takeScreenShot) - + return result } - + /// Save the current app screen shots in the given directory. /// If an app has more than one screen, one image for each screen will be saved. /// - Parameter imagesDirectoryPath: The path where the images should be saved. @@ -51,19 +60,19 @@ import UIKit // during signal handling, and if we dispatch it to the main thread, // that is probably blocked by the crash event, we freeze the application. let screenshotData = appScreenshotsData() - + for (index, data) in screenshotData.enumerated() { let name = index == 0 ? "screenshot.png" : "screenshot-\(index + 1).png" let fileName = (imagesDirectoryPath as NSString).appendingPathComponent(name) try? data.write(to: URL(fileURLWithPath: fileName), options: .atomic) } } - + public func appScreenshots() -> [UIImage] { let windows = SentryDependencyContainerSwiftHelper.windows() ?? [] var result: [UIImage] = [] result.reserveCapacity(windows.count) - + for window in windows { let size = window.frame.size if size.width == 0 || size.height == 0 { @@ -72,9 +81,9 @@ import UIKit // scale=1.000000 continue } - + let img = photographer.image(view: window) - + // this shouldn't happen now that we discard windows with either 0 height or 0 width, // but still, we shouldn't send any images with either one. if img.size.width > 0 && img.size.height > 0 { @@ -83,12 +92,12 @@ import UIKit } return result } - + public func appScreenshotsData() -> [Data] { let screenshots = appScreenshots() var result: [Data] = [] result.reserveCapacity(screenshots.count) - + for screenshot in screenshots { // this shouldn't happen now that we discard windows with either 0 height or 0 width, // but still, we shouldn't send any images with either one. @@ -103,4 +112,4 @@ import UIKit } #endif // os(iOS) || os(tvOS) -#endif // canImport(UIKit) && !SENTRY_NO_UIKIT +#endif // canImport(UIKit) && !SENTRY_NO_UIKIT diff --git a/Sources/Swift/Core/Tools/ViewCapture/SentryUIRedactBuilder.swift b/Sources/Swift/Core/Tools/ViewCapture/SentryUIRedactBuilder.swift index fdbc59c9b3a..a702ef8f06d 100644 --- a/Sources/Swift/Core/Tools/ViewCapture/SentryUIRedactBuilder.swift +++ b/Sources/Swift/Core/Tools/ViewCapture/SentryUIRedactBuilder.swift @@ -4,20 +4,35 @@ import Foundation import ObjectiveC.NSObjCRuntime import UIKit #if os(iOS) +import PDFKit import WebKit #endif final class SentryUIRedactBuilder { + // MARK: - Constants + + /// Class identifier for ``CameraUI.ChromeSwiftUIView``, if it exists. + /// + /// This object identifier is used to identify views of this class type during the redaction process. + /// This workaround is specifically for Xcode 16 building for iOS 26 where accessing CameraUI.ModeLoupeLayer + /// causes a crash due to unimplemented init(layer:) initializer. + private static let cameraSwiftUIViewClassId = "CameraUI.ChromeSwiftUIView" + ///This is a wrapper which marks it's direct children to be ignored private var ignoreContainerClassIdentifier: ObjectIdentifier? + ///This is a wrapper which marks it's direct children to be redacted private var redactContainerClassIdentifier: ObjectIdentifier? ///This is a list of UIView subclasses that will be ignored during redact process private var ignoreClassesIdentifiers: Set - ///This is a list of UIView subclasses that need to be redacted from screenshot - private var redactClassesIdentifiers: Set - + + /// This is a list of UIView subclasses that need to be redacted from screenshot + /// + /// This set is configured as `private(set)` to allow modification only from within this class, + /// while still allowing read access from tests. + private(set) var redactClassesIdentifiers: Set + /** Initializes a new instance of the redaction process with the specified options. @@ -57,7 +72,7 @@ final class SentryUIRedactBuilder { } #if os(iOS) - redactClasses += [ WKWebView.self ] + redactClasses += [ PDFView.self, WKWebView.self ] redactClasses += [ // If we try to use 'UIWebView.self' it will not compile for macCatalyst, but the class does exists. @@ -65,7 +80,10 @@ final class SentryUIRedactBuilder { // Used by: // - https://developer.apple.com/documentation/SafariServices/SFSafariViewController // - https://developer.apple.com/documentation/AuthenticationServices/ASWebAuthenticationSession - "SFSafariView" + "SFSafariView", + // Used by: + // - https://developer.apple.com/documentation/avkit/avplayerviewcontroller + "AVPlayerView" ].compactMap(NSClassFromString(_:)) ignoreClassesIdentifiers = [ ObjectIdentifier(UISlider.self), ObjectIdentifier(UISwitch.self) ] @@ -85,7 +103,7 @@ final class SentryUIRedactBuilder { } func containsIgnoreClass(_ ignoreClass: AnyClass) -> Bool { - return ignoreClassesIdentifiers.contains(ObjectIdentifier(ignoreClass)) + return ignoreClassesIdentifiers.contains(ObjectIdentifier(ignoreClass)) } func containsRedactClass(_ redactClass: AnyClass) -> Bool { @@ -178,7 +196,7 @@ final class SentryUIRedactBuilder { } private func shouldIgnore(view: UIView) -> Bool { - return SentryRedactViewHelper.shouldUnmask(view) || containsIgnoreClass(type(of: view)) || shouldIgnoreParentContainer(view) + return SentryRedactViewHelper.shouldUnmask(view) || containsIgnoreClass(type(of: view)) || shouldIgnoreParentContainer(view) } private func shouldIgnoreParentContainer(_ view: UIView) -> Bool { @@ -220,6 +238,19 @@ final class SentryUIRedactBuilder { } let newTransform = concatenateTranform(transform, from: layer, withParent: parentLayer) + // Check if the subtree should be ignored to avoid crashes with some special views. + // If a subtree is ignored, it will be fully redacted and we return early to prevent duplicates. + if isViewSubtreeIgnored(view) { + redacting.append(SentryRedactRegion( + size: layer.bounds.size, + transform: newTransform, + type: .redact, + color: self.color(for: view), + name: view.debugDescription + )) + return + } + let ignore = !forceRedact && shouldIgnore(view: view) let swiftUI = SentryRedactViewHelper.shouldRedactSwiftUI(view) let redact = forceRedact || shouldRedact(view: view) || swiftUI @@ -231,7 +262,7 @@ final class SentryUIRedactBuilder { transform: newTransform, type: swiftUI ? .redactSwiftUI : .redact, color: self.color(for: view), - name: layer.name ?? layer.debugDescription + name: view.debugDescription )) guard !view.clipsToBounds else { @@ -248,11 +279,12 @@ final class SentryUIRedactBuilder { size: layer.bounds.size, transform: newTransform, type: .clipOut, - name: layer.name ?? layer.debugDescription + name: view.debugDescription )) } } - + + // Traverse the sublayers to redact them if necessary guard let subLayers = layer.sublayers, subLayers.count > 0 else { return } @@ -264,7 +296,7 @@ final class SentryUIRedactBuilder { size: layer.bounds.size, transform: newTransform, type: .clipEnd, - name: layer.name ?? layer.debugDescription + name: view.debugDescription )) } for subLayer in subLayers.sorted(by: { $0.zPosition < $1.zPosition }) { @@ -275,11 +307,40 @@ final class SentryUIRedactBuilder { size: layer.bounds.size, transform: newTransform, type: .clipBegin, - name: layer.name ?? layer.debugDescription + name: view.debugDescription )) } } + private func isViewSubtreeIgnored(_ view: UIView) -> Bool { + // We intentionally avoid using `NSClassFromString` or directly referencing class objects here, + // because both approaches can trigger the Objective-C `+initialize` method on the class. + // This has side effects and can cause crashes, especially when performed off the main thread + // or with UIKit classes that expect to be initialized on the main thread. + // + // Instead, we use the string description of the type (i.e., `type(of: view).description()`) + // for comparison. This is a safer, more "Swifty" approach that avoids the pitfalls of + // class initialization side effects. + // + // We have previously encountered related issues: + // - In EmergeTools' snapshotting code where using `NSClassFromString` led to crashes [1] + // - In Sentry's own SubClassFinder where storing or accessing class objects on a background thread caused crashes due to `+initialize` being called on UIKit classes [2] + // + // [1] https://github.com/EmergeTools/SnapshotPreviews/blob/main/Sources/SnapshotPreviewsCore/View%2BSnapshot.swift#L248 + // [2] https://github.com/getsentry/sentry-cocoa/blob/00d97404946a37e983eabb21cc64bd3d5d2cb474/Sources/Sentry/SentrySubClassFinder.m#L58-L84 + let viewTypeId = type(of: view).description() + + if #available(iOS 26.0, *), viewTypeId == Self.cameraSwiftUIViewClassId { + // CameraUI.ChromeSwiftUIView is a special case because it contains layers which can not be iterated due to this error: + // + // Fatal error: Use of unimplemented initializer 'init(layer:)' for class 'CameraUI.ModeLoupeLayer' + // + // This crash only occurs when building with Xcode 16 for iOS 26, so we add a runtime check + return true + } + return false + } + /** Gets a transform that represents the layer global position. */ diff --git a/Sources/Swift/Exports.swift b/Sources/Swift/Exports.swift index eaf31f92e03..81d2b3363ea 100644 --- a/Sources/Swift/Exports.swift +++ b/Sources/Swift/Exports.swift @@ -3,6 +3,6 @@ // to add an import. This allows the same source to // compile in SPM and xcodebuild (which doesn't separate // ObjC into the SentryHeaders target) -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 @_exported import SentryHeaders #endif diff --git a/Sources/Swift/Helper/Dependencies.swift b/Sources/Swift/Helper/Dependencies.swift new file mode 100644 index 00000000000..f205c0dae7a --- /dev/null +++ b/Sources/Swift/Helper/Dependencies.swift @@ -0,0 +1,8 @@ +@objc(SentryDependencies) @_spi(Private) public final class Dependencies: NSObject { + @objc public static let dispatchQueueWrapper = SentryDispatchQueueWrapper() + @objc public static let dateProvider = SentryDefaultCurrentDateProvider() + public static let objcRuntimeWrapper = SentryDefaultObjCRuntimeWrapper() +#if !os(watchOS) && !os(macOS) && !SENTRY_NO_UIKIT + @objc public static let uiDeviceWrapper = SentryDefaultUIDeviceWrapper(queueWrapper: Dependencies.dispatchQueueWrapper) +#endif // !os(watchOS) && !os(macOS) && !SENTRY_NO_UIKIT +} diff --git a/Sources/Swift/Helper/SentryApplication.swift b/Sources/Swift/Helper/SentryApplication.swift new file mode 100644 index 00000000000..09a0c4ccaeb --- /dev/null +++ b/Sources/Swift/Helper/SentryApplication.swift @@ -0,0 +1,37 @@ +#if canImport(AppKit) +import AppKit +#endif +#if canImport(UIKit) && !SENTRY_NO_UIKIT +import UIKit +#endif + +@objc @_spi(Private) public protocol SentryApplication { + + // This can only be accessed on the main thread + var mainThread_isActive: Bool { get } + + #if !os(macOS) && !os(watchOS) && !SENTRY_NO_UIKIT + + /** + * Returns the application state available at @c UIApplication.sharedApplication.applicationState + * Must be called on the main thread. + */ + var unsafeApplicationState: UIApplication.State { get } + +/** + * All windows connected to scenes. + */ + func getWindows() -> [UIWindow]? + + @available(iOS 13.0, tvOS 13.0, *) + var connectedScenes: Set { get } + + var delegate: UIApplicationDelegate? { get } + +/** + * Use @c [SentryUIApplication relevantViewControllers] and convert the + * result to a string array with the class name of each view controller. + */ + func relevantViewControllersNames() -> [String]? + #endif // canImport(UIKit) && !SENTRY_NO_UIKIT +} diff --git a/Sources/Swift/Helper/SentryApplicationExtensions.swift b/Sources/Swift/Helper/SentryApplicationExtensions.swift new file mode 100644 index 00000000000..307063bc985 --- /dev/null +++ b/Sources/Swift/Helper/SentryApplicationExtensions.swift @@ -0,0 +1,166 @@ +// This is needed because a file that only contains an @objc extension will get automatically stripped out +// in static builds. We need to either use the -all_load linker flag (which has downsides of app size increases) +// or make sure that every file containing objc categories/extensions also have a concrete type that +// is referenced. Once `SentryAppliction` is not using `@objc` this can be removed. +@_spi(Private) @objc public final class PlaceholderSentryApplication: NSObject { } + +#if !os(macOS) && !os(watchOS) && !SENTRY_NO_UIKIT +import UIKit + +@objc @_spi(Private) extension UIApplication: SentryApplication { + + @objc public func getWindows() -> [UIWindow]? { + internal_getWindows() + } + + @objc public func relevantViewControllersNames() -> [String]? { + internal_relevantViewControllersNames() + } + + @objc public var unsafeApplicationState: State { + applicationState + } + + @objc public var mainThread_isActive: Bool { + unsafeApplicationState == .active + } +} + +extension SentryApplication { + // This cannot be declared with @objc so until we delete more ObjC code it needs a separate + // function than the objc visible one. + public func internal_getWindows() -> [UIWindow]? { + var windows = Set() + Dependencies.dispatchQueueWrapper.dispatchSyncOnMainQueue({ [weak self] in + guard let self else { return } + if #available(iOS 13.0, tvOS 13.0, *) { + let scenes = self.connectedScenes + for scene in scenes { + if scene.activationState == .foregroundActive { + if + let delegate = scene.delegate as? UIWindowSceneDelegate, + let window = delegate.window { + if let window { + windows.insert(window) + } + } + } + } + } + + if let window = self.delegate?.window { + if let window { + windows.insert(window) + } + } + }, timeout: 0.01) + return Array(windows) + } + + // This cannot be declared with @objc so until we delete more ObjC code it needs a separate + // function than the objc visible one. + public func internal_relevantViewControllersNames() -> [String]? { + var result: [String]? + Dependencies.dispatchQueueWrapper.dispatchSyncOnMainQueue({ [weak self] in + guard let self else { return } + let viewControllers = self.relevantviewControllers() ?? [] + result = viewControllers.map { SwiftDescriptor.getViewControllerClassName($0) } + }, timeout: 0.01) + return result + } + + private func relevantviewControllers() -> [UIViewController]? { + let windows = getWindows() + guard !(windows?.isEmpty ?? true) else { return nil } + + return windows?.compactMap { relevantViewControllerFromWindow($0) }.flatMap { $0 } + } + + private func relevantViewControllerFromWindow(_ window: UIWindow) -> [UIViewController]? { + let viewController = window.rootViewController + guard let viewController else { return nil } + + var result = [UIViewController]() + result.append(viewController) + var index = 0 + while index < result.count { + let topVC = result[index] + // If the view controller is presenting another one, usually in a modal form. + if let presented = topVC.presentedViewController { + if presented is UIAlertController { + break + } + result[index] = presented + continue + } + + // The top view controller is meant for navigation and not content + if isContainerViewController(topVC) { + if let contentViewController = relevantViewControllerFromContainer(topVC), contentViewController.count > 0 { + result.remove(at: index) + result.append(contentsOf: contentViewController) + } else { + break + } + continue + } + + var relevantChild: UIViewController? + for childVC in topVC.children { + // Sometimes a view controller is used as container for a navigation controller + // If the navigation is occupying the whole view controller we will consider this the + // case. + if isContainerViewController(childVC), childVC.isViewLoaded, childVC.view.frame == topVC.view.bounds { + relevantChild = childVC + break + } + } + if let relevantChild { + result[index] = relevantChild + } + + index += 1 + } + return result + } + + func relevantViewControllerFromContainer(_ vc: UIViewController) -> [UIViewController]? { + if let navigationController = vc as? UINavigationController { + return navigationController.topViewController.map { [$0] } + } + if let tabBarController = vc as? UITabBarController { + let selectedIndex = tabBarController.selectedIndex + if let vcs = tabBarController.viewControllers, vcs.count > selectedIndex { + return [vcs[selectedIndex]] + } else { + return nil + } + } + if let splitViewController = vc as? UISplitViewController { + if splitViewController.viewControllers.count > 0 { + return splitViewController.viewControllers + } + } + + if let pageViewController = vc as? UIPageViewController { + if let vcs = pageViewController.viewControllers, vcs.count > 0 { + return [vcs[0]] + } + } + + return nil + } + + func isContainerViewController(_ vc: UIViewController) -> Bool { + return vc is UINavigationController || vc is UITabBarController || vc is UISplitViewController || vc is UIPageViewController + } +} +#endif + +#if canImport(AppKit) && !targetEnvironment(macCatalyst) +@objc @_spi(Private) extension NSApplication: SentryApplication { + public var mainThread_isActive: Bool { + isActive + } +} +#endif diff --git a/Sources/Swift/Helper/SentryDefaultObjCRuntimeWrapper.swift b/Sources/Swift/Helper/SentryDefaultObjCRuntimeWrapper.swift new file mode 100644 index 00000000000..f9ea3332b90 --- /dev/null +++ b/Sources/Swift/Helper/SentryDefaultObjCRuntimeWrapper.swift @@ -0,0 +1,15 @@ +import Foundation +import ObjectiveC.runtime + +@objc @_spi(Private) +public final class SentryDefaultObjCRuntimeWrapper: NSObject, SentryObjCRuntimeWrapper { + @_spi(Private) + public func copyClassNamesForImage(_ image: UnsafePointer, _ outCount: UnsafeMutablePointer?) -> UnsafeMutablePointer>? { + return objc_copyClassNamesForImage(image, outCount) + } + + @_spi(Private) + public func classGetImageName(_ cls: AnyClass) -> UnsafePointer? { + return class_getImageName(cls) + } +} diff --git a/Sources/Swift/Helper/SentryDispatchQueueWrapper.swift b/Sources/Swift/Helper/SentryDispatchQueueWrapper.swift index 2691df0da8a..e9703bc91f1 100644 --- a/Sources/Swift/Helper/SentryDispatchQueueWrapper.swift +++ b/Sources/Swift/Helper/SentryDispatchQueueWrapper.swift @@ -1,6 +1,6 @@ @_implementationOnly import _SentryPrivate -// This is the Swift verion of `_SentryDispatchQueueWrapperInternal` +// This is the Swift version of `_SentryDispatchQueueWrapperInternal` // It exists to allow the implementation of `_SentryDispatchQueueWrapperInternal` // to be accessible to Swift without making that header file public @objcMembers @_spi(Private) public class SentryDispatchQueueWrapper: NSObject { @@ -45,11 +45,16 @@ public func dispatch(after interval: TimeInterval, block: @escaping () -> Void) { internalWrapper.dispatch(after: interval, block: block) } - + public func dispatchOnce(_ predicate: UnsafeMutablePointer, block: @escaping () -> Void) { internalWrapper.dispatchOnce(predicate, block: block) } + @_spi(Private) public func dispatch(after interval: TimeInterval, workItem: DispatchWorkItem) { + // Swift only API, so we need to call the internal queue directly. + internalWrapper.queue.asyncAfter(deadline: .now() + interval, execute: workItem) + } + // The ObjC version of this code wrapped `dispatch_cancel` and `dispatch_block_create` // However dispatch_block is not accessible in Swift. Unit tests rely on stubbing out // the creation and cancelation of dispatch blocks, so these two variables allow diff --git a/Sources/Swift/Helper/SentryEnabledFeaturesBuilder.swift b/Sources/Swift/Helper/SentryEnabledFeaturesBuilder.swift index 330af27b69a..51d8a323e66 100644 --- a/Sources/Swift/Helper/SentryEnabledFeaturesBuilder.swift +++ b/Sources/Swift/Helper/SentryEnabledFeaturesBuilder.swift @@ -1,8 +1,10 @@ +@_implementationOnly import _SentryPrivate import Foundation @objcMembers @_spi(Private) public class SentryEnabledFeaturesBuilder: NSObject { // swiftlint:disable cyclomatic_complexity function_body_length + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") public static func getEnabledFeatures(options: Options?) -> [String] { guard let options = options else { return [] @@ -22,9 +24,11 @@ import Foundation } #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) + #if !SDK_V9 if options.enableAppLaunchProfiling { features.append("appLaunchProfiling") } + #endif // !SDK_V9 #endif // os(iOS) || os(macOS) || targetEnvironment(macCatalyst) #if os(iOS) || os(tvOS) @@ -40,9 +44,11 @@ import Foundation } #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) + #if !SDK_V9 if options.enableAppHangTrackingV2 { features.append("appHangTrackingV2") } + #endif // !SDK_V9 #endif //os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) if options.enablePersistingTracesWhenCrashing { @@ -50,11 +56,11 @@ import Foundation } #if (os(iOS) || os(tvOS)) && !SENTRY_NO_UIKIT - if options.sessionReplay.enableViewRendererV2 { + if options.enableViewRendererV2() { // We keep the old name for backwards compatibility of the telemetry data. features.append("experimentalViewRenderer") } - if options.sessionReplay.enableFastViewRendering { + if options.enableFastViewRendering() { features.append("fastViewRendering") } #endif // (os(iOS) || os(tvOS)) && !SENTRY_NO_UIKIT diff --git a/Sources/Swift/Helper/SentryEnvelopeItemType.swift b/Sources/Swift/Helper/SentryEnvelopeItemType.swift new file mode 100644 index 00000000000..486a74864d5 --- /dev/null +++ b/Sources/Swift/Helper/SentryEnvelopeItemType.swift @@ -0,0 +1,20 @@ +/// Each item type must have a data category name mapped to it; see SentryDataCategoryMapper +/// +/// While these envelope item types might look similar to the data categories, +/// they are not identical, and have slight differences. +@_spi(Private) @objcMembers public final class SentryEnvelopeItemTypes: NSObject { + public static let event = "event" + public static let session = "session" + #if !SDK_V9 + public static let userFeedback = "user_report" + #endif + public static let feedback = "feedback" + public static let transaction = "transaction" + public static let attachment = "attachment" + public static let clientReport = "client_report" + public static let profile = "profile" + public static let replayVideo = "replay_video" + public static let statsd = "statsd" + public static let profileChunk = "profile_chunk" + public static let log = "log" +} diff --git a/Sources/Swift/Helper/SentryMobileProvisionParser.swift b/Sources/Swift/Helper/SentryMobileProvisionParser.swift new file mode 100644 index 00000000000..dc3e4e25b5f --- /dev/null +++ b/Sources/Swift/Helper/SentryMobileProvisionParser.swift @@ -0,0 +1,63 @@ +@objc @_spi(Private) +public class SentryMobileProvisionParser: NSObject { + private var provisionsAllDevices: Bool = false + private var embeddedProfilePath: String? + + // If the profile provisions all devices, it indicates Enterprise distribution + @objc + public var mobileProvisionProfileProvisionsAllDevices: Bool { + return provisionsAllDevices + } + + // This convenience initializer exists so we can use it from ObjC. + // Functions with Optional parameters (used for testing) are not available to ObjC + @objc + convenience override public init() { + self.init(nil) + } + + public init(_ path: String?) { + super.init() + embeddedProfilePath = path ?? Bundle.main.path(forResource: "embedded", ofType: "mobileprovision") + guard let embeddedProfilePath else { + SentrySDKLog.debug("Couldn't find a embedded mobileprovision profile") + return + } + parseProfileFromPath(embeddedProfilePath) + } + + @objc + public func hasEmbeddedMobileProvisionProfile() -> Bool { + embeddedProfilePath != nil + } + + private func parseProfileFromPath(_ path: String) { + guard let fileData = try? Data(contentsOf: URL(fileURLWithPath: path)) else { + SentrySDKLog.debug("Failed to read embedded mobileprovision profile at path \(path)") + return + } + + // The file is a CMS (PKCS#7) container with a plist embedded inside as text. + // Convert to Latin-1 to preserve the bytes -> string even if not UTF-8. + guard let payload = String(data: fileData, encoding: .isoLatin1), + let startRange = payload.range(of: "") else { + SentrySDKLog.debug("Failed to parse embedded mobileprovision profile") + return + } + + let plistRange = startRange.lowerBound ..< payload.index(endRange.upperBound, offsetBy: 0) + let plistString = String(payload[plistRange]) + guard let plistData = plistString.data(using: .utf8) else { return } + + var format = PropertyListSerialization.PropertyListFormat.xml + + guard let obj = try? PropertyListSerialization.propertyList(from: plistData, + options: [], + format: &format), + let dict = obj as? [String: Any] else { + return + } + provisionsAllDevices = dict["ProvisionsAllDevices"] as? Bool ?? false + } +} diff --git a/Sources/Swift/Helper/SentryNSNotificationCenterWrapper.swift b/Sources/Swift/Helper/SentryNSNotificationCenterWrapper.swift new file mode 100644 index 00000000000..1b92ba1e9a6 --- /dev/null +++ b/Sources/Swift/Helper/SentryNSNotificationCenterWrapper.swift @@ -0,0 +1,12 @@ +import Foundation + +@objc @_spi(Private) public protocol SentryNSNotificationCenterWrapper { + func addObserver(_ observer: Any, selector aSelector: Selector, name aName: NSNotification.Name?, object anObject: Any?) + @objc(addObserverForName:object:queue:usingBlock:) + func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @Sendable @escaping (Notification) -> Void) -> NSObjectProtocol + func removeObserver(_ observer: Any, name aName: NSNotification.Name?, object anObject: Any?) + @objc(postNotification:) + func post(_ notification: Notification) +} + +@objc @_spi(Private) extension NotificationCenter: SentryNSNotificationCenterWrapper { } diff --git a/Sources/Swift/Helper/SentryNSTimerFactory.swift b/Sources/Swift/Helper/SentryNSTimerFactory.swift new file mode 100644 index 00000000000..87122a0f590 --- /dev/null +++ b/Sources/Swift/Helper/SentryNSTimerFactory.swift @@ -0,0 +1,25 @@ +import Foundation + +@objc +@_spi(Private) public class SentryNSTimerFactory: NSObject { + + @objc @discardableResult + @_spi(Private) public func scheduledTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Void) -> Timer { + if !Thread.isMainThread { + let warningText = "Timers must be scheduled from the main thread, or they may never fire. See the attribute on the declaration in NSTimer.h. See https://stackoverflow.com/questions/8304702/how-do-i-create-a-nstimer-on-a-background-thread for more info." + SentrySDKLog.warning(warningText) + assertionFailure(warningText) + } + return Timer.scheduledTimer(withTimeInterval: interval, repeats: repeats, block: block) + } + + @objc @discardableResult + @_spi(Private) public func scheduledTimer(withTimeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer { + if !Thread.isMainThread { + let warningText = "Timers must be scheduled from the main thread, or they may never fire. See the attribute on the declaration in NSTimer.h. See https://stackoverflow.com/questions/8304702/how-do-i-create-a-nstimer-on-a-background-thread for more info." + SentrySDKLog.warning(warningText) + assertionFailure(warningText) + } + return Timer.scheduledTimer(timeInterval: ti, target: aTarget, selector: aSelector, userInfo: userInfo, repeats: yesOrNo) + } +} diff --git a/Sources/Swift/Helper/SentryObjCRuntimeWrapper.swift b/Sources/Swift/Helper/SentryObjCRuntimeWrapper.swift new file mode 100644 index 00000000000..a77a4c25fb3 --- /dev/null +++ b/Sources/Swift/Helper/SentryObjCRuntimeWrapper.swift @@ -0,0 +1,9 @@ +import Foundation + +@objc @_spi(Private) +public protocol SentryObjCRuntimeWrapper { + @objc(copyClassNamesForImage:amount:) + func copyClassNamesForImage(_ image: UnsafePointer, _ outCount: UnsafeMutablePointer?) -> UnsafeMutablePointer>? + @objc(class_getImageName:) + func classGetImageName(_ cls: AnyClass) -> UnsafePointer? +} diff --git a/Sources/Swift/Helper/SentryProcessInfo.swift b/Sources/Swift/Helper/SentryProcessInfo.swift new file mode 100644 index 00000000000..153880f6467 --- /dev/null +++ b/Sources/Swift/Helper/SentryProcessInfo.swift @@ -0,0 +1,29 @@ +@_spi(Private) @objc public protocol SentryProcessInfoSource { + var processDirectoryPath: String { get } + var processPath: String? { get } + var processorCount: Int { get } + var thermalState: ProcessInfo.ThermalState { get } + var environment: [String: String] { get } + + @available(iOS 14.0, macOS 11.0, watchOS 7.0, tvOS 14.0, *) + var isiOSAppOnMac: Bool { get } + + @available(iOS 13.0, macOS 10.15, watchOS 6.0, tvOS 13.0, *) + var isMacCatalystApp: Bool { get } +} + +// This is needed because a file that only contains an @objc extension will get automatically stripped out +// in static builds. We need to either use the -all_load linker flag (which has downsides of app size increases) +// or make sure that every file containing objc categories/extensions also have a concrete type that +// is referenced. Once `SentryProcessInfoSource` is not using `@objc` this can be removed. +@_spi(Private) @objc public final class PlaceholderProcessInfoClass: NSObject { } + +@_spi(Private) extension ProcessInfo: SentryProcessInfoSource { + public var processDirectoryPath: String { + Bundle.main.bundlePath + } + + public var processPath: String? { + Bundle.main.executablePath + } +} diff --git a/Sources/Swift/Helper/SentryRandom.swift b/Sources/Swift/Helper/SentryRandom.swift new file mode 100644 index 00000000000..329c953f64c --- /dev/null +++ b/Sources/Swift/Helper/SentryRandom.swift @@ -0,0 +1,16 @@ +import Foundation + +/// Protocol for generating random numbers. +@objc +@_spi(Private) public protocol SentryRandomProtocol { + /// Returns a random number uniformly distributed over the interval [0.0 , 1.0]. + @objc func nextNumber() -> Double +} + +@objc +@_spi(Private) public class SentryRandom: NSObject, SentryRandomProtocol { + /// Returns a random number uniformly distributed over the interval [0.0 , 1.0]. + @objc public func nextNumber() -> Double { + Double.random(in: 0...1) + } +} diff --git a/Sources/Swift/Helper/SentrySDK.swift b/Sources/Swift/Helper/SentrySDK.swift new file mode 100644 index 00000000000..a0ef1b74c10 --- /dev/null +++ b/Sources/Swift/Helper/SentrySDK.swift @@ -0,0 +1,461 @@ +// swiftlint:disable file_length +@_implementationOnly import _SentryPrivate +import Foundation + +/// The main entry point for the Sentry SDK. +/// We recommend using `start(configureOptions:)` to initialize Sentry. +@objc open class SentrySDK: NSObject { + + // MARK: - Public + + /// The current active transaction or span bound to the scope. + @objc public static var span: Span? { + return SentrySDKInternal.span + } + + /// Indicates whether the Sentry SDK is enabled. + @objc public static var isEnabled: Bool { + return SentrySDKInternal.isEnabled + } + + #if canImport(UIKit) && !SENTRY_NO_UIKIT && (os(iOS) || os(tvOS)) + /// API to control session replay + @objc public static var replay: SentryReplayApi { + return SentrySDKInternal.replay + } + #endif + + /// API to access Sentry logs + @objc public static var logger: SentryLogger { + return _loggerLock.synchronized { + let sdkEnabled = SentrySDKInternal.isEnabled + if !sdkEnabled { + SentrySDKLog.fatal("Logs called before SentrySDK.start() will be dropped.") + } + if let _logger, _loggerConfigured { + return _logger + } + let hub = SentryDependencyContainerSwiftHelper.currentHub() + var batcher: SentryLogBatcher? + if let client = hub.getClient(), client.options.experimental.enableLogs { + batcher = SentryLogBatcher(client: client, dispatchQueue: Dependencies.dispatchQueueWrapper) + } + let logger = SentryLogger( + hub: hub, + dateProvider: Dependencies.dateProvider, + batcher: batcher + ) + _logger = logger + _loggerConfigured = sdkEnabled + return logger + } + } + + /// Inits and configures Sentry (`SentryHub`, `SentryClient`) and sets up all integrations. Make sure to + /// set a valid DSN. + /// - note: Call this method on the main thread. When calling it from a background thread, the + /// SDK starts on the main thread async. + @objc public static func start(options: Options) { + SentrySDKInternal.start(options: options) + } + + /// Inits and configures Sentry (`SentryHub`, `SentryClient`) and sets up all integrations. Make sure to + /// set a valid DSN. + /// - note: Call this method on the main thread. When calling it from a background thread, the + /// SDK starts on the main thread async. + @objc public static func start(configureOptions: @escaping (Options) -> Void) { + SentrySDKInternal.start(configureOptions: configureOptions) + } + + // MARK: - Event Capture + + /// Captures a manually created event and sends it to Sentry. + /// - parameter event: The event to send to Sentry. + /// - returns: The `SentryId` of the event or `SentryId.empty` if the event is not sent. + @objc(captureEvent:) + @discardableResult public static func capture(event: Event) -> SentryId { + return SentrySDKInternal.capture(event: event).sentryId + } + + /// Captures a manually created event and sends it to Sentry. Only the data in this scope object will + /// be added to the event. The global scope will be ignored. + /// - parameter event: The event to send to Sentry. + /// - parameter scope: The scope containing event metadata. + /// - returns: The `SentryId` of the event or `SentryId.empty` if the event is not sent. + @objc(captureEvent:withScope:) + @discardableResult public static func capture(event: Event, scope: Scope) -> SentryId { + return SentrySDKInternal.capture(event: event, scope: scope).sentryId + } + + /// Captures a manually created event and sends it to Sentry. Maintains the global scope but mutates + /// scope data for only this call. + /// - parameter event: The event to send to Sentry. + /// - parameter block: The block mutating the scope only for this call. + /// - returns: The `SentryId` of the event or `SentryId.empty` if the event is not sent. + @objc(captureEvent:withScopeBlock:) + @discardableResult public static func capture(event: Event, block: @escaping (Scope) -> Void) -> SentryId { + return SentrySDKInternal.capture(event: event, block: block).sentryId + } + + // MARK: - Transaction Management + + /// Creates a transaction, binds it to the hub and returns the instance. + /// - parameter name: The transaction name. + /// - parameter operation: Short code identifying the type of operation the span is measuring. + /// - returns: The created transaction. + @objc @discardableResult public static func startTransaction(name: String, operation: String) -> Span { + return SentrySDKInternal.startTransaction(name: name, operation: operation) + } + + /// Creates a transaction, binds it to the hub and returns the instance. + /// - parameter name: The transaction name. + /// - parameter operation: Short code identifying the type of operation the span is measuring. + /// - parameter bindToScope: Indicates whether the SDK should bind the new transaction to the scope. + /// - returns: The created transaction. + @objc @discardableResult public static func startTransaction(name: String, operation: String, bindToScope: Bool) -> Span { + return SentrySDKInternal.startTransaction(name: name, operation: operation, bindToScope: bindToScope) + } + + /// Creates a transaction, binds it to the hub and returns the instance. + /// - parameter transactionContext: The transaction context. + /// - returns: The created transaction. + @objc(startTransactionWithContext:) + @discardableResult public static func startTransaction(transactionContext: TransactionContext) -> Span { + return SentrySDKInternal.startTransaction(transactionContext: transactionContext) + } + + /// Creates a transaction, binds it to the hub and returns the instance. + /// - parameter transactionContext: The transaction context. + /// - parameter bindToScope: Indicates whether the SDK should bind the new transaction to the scope. + /// - returns: The created transaction. + @objc(startTransactionWithContext:bindToScope:) + @discardableResult public static func startTransaction(transactionContext: TransactionContext, bindToScope: Bool) -> Span { + return SentrySDKInternal.startTransaction(transactionContext: transactionContext, bindToScope: bindToScope) + } + + /// Creates a transaction, binds it to the hub and returns the instance. + /// - parameter transactionContext: The transaction context. + /// - parameter bindToScope: Indicates whether the SDK should bind the new transaction to the scope. + /// - parameter customSamplingContext: Additional information about the sampling context. + /// - returns: The created transaction. + @objc(startTransactionWithContext:bindToScope:customSamplingContext:) + @discardableResult public static func startTransaction(transactionContext: TransactionContext, bindToScope: Bool, customSamplingContext: [String: Any]) -> Span { + return SentrySDKInternal.startTransaction(transactionContext: transactionContext, bindToScope: bindToScope, customSamplingContext: customSamplingContext) + } + + /// Creates a transaction, binds it to the hub and returns the instance. + /// - parameter transactionContext: The transaction context. + /// - parameter customSamplingContext: Additional information about the sampling context. + /// - returns: The created transaction. + @objc(startTransactionWithContext:customSamplingContext:) + @discardableResult public static func startTransaction(transactionContext: TransactionContext, customSamplingContext: [String: Any]) -> Span { + return SentrySDKInternal.startTransaction(transactionContext: transactionContext, customSamplingContext: customSamplingContext) + } + + // MARK: - Error Capture + + /// Captures an error event and sends it to Sentry. + /// - parameter error: The error to send to Sentry. + /// - returns: The `SentryId` of the event or `SentryId.empty` if the event is not sent. + @objc(captureError:) + @discardableResult public static func capture(error: Error) -> SentryId { + return SentrySDKInternal.capture(error: error).sentryId + } + + /// Captures an error event and sends it to Sentry. Only the data in this scope object will be added + /// to the event. The global scope will be ignored. + /// - parameter error: The error to send to Sentry. + /// - parameter scope: The scope containing event metadata. + /// - returns: The `SentryId` of the event or `SentryId.empty` if the event is not sent. + @objc(captureError:withScope:) + @discardableResult public static func capture(error: Error, scope: Scope) -> SentryId { + return SentrySDKInternal.capture(error: error, scope: scope).sentryId + } + + /// Captures an error event and sends it to Sentry. Maintains the global scope but mutates scope data + /// for only this call. + /// - parameter error: The error to send to Sentry. + /// - parameter block: The block mutating the scope only for this call. + /// - returns: The `SentryId` of the event or `SentryId.empty` if the event is not sent. + @objc(captureError:withScopeBlock:) + @discardableResult public static func capture(error: Error, block: @escaping (Scope) -> Void) -> SentryId { + return SentrySDKInternal.capture(error: error, block: block).sentryId + } + + // MARK: - Exception Capture + + /// Captures an exception event and sends it to Sentry. + /// - parameter exception: The exception to send to Sentry. + /// - returns: The `SentryId` of the event or `SentryId.empty` if the event is not sent. + @objc(captureException:) + @discardableResult public static func capture(exception: NSException) -> SentryId { + return SentrySDKInternal.capture(exception: exception).sentryId + } + + /// Captures an exception event and sends it to Sentry. Only the data in this scope object will be + /// added to the event. The global scope will be ignored. + /// - parameter exception: The exception to send to Sentry. + /// - parameter scope: The scope containing event metadata. + /// - returns: The `SentryId` of the event or `SentryId.empty` if the event is not sent. + @objc(captureException:withScope:) + @discardableResult public static func capture(exception: NSException, scope: Scope) -> SentryId { + return SentrySDKInternal.capture(exception: exception, scope: scope).sentryId + } + + /// Captures an exception event and sends it to Sentry. Maintains the global scope but mutates scope + /// data for only this call. + /// - parameter exception: The exception to send to Sentry. + /// - parameter block: The block mutating the scope only for this call. + /// - returns: The `SentryId` of the event or `SentryId.empty` if the event is not sent. + @objc(captureException:withScopeBlock:) + @discardableResult public static func capture(exception: NSException, block: @escaping (Scope) -> Void) -> SentryId { + return SentrySDKInternal.capture(exception: exception, block: block).sentryId + } + + // MARK: - Message Capture + + /// Captures a message event and sends it to Sentry. + /// - parameter message: The message to send to Sentry. + /// - returns: The `SentryId` of the event or `SentryId.empty` if the event is not sent. + @objc(captureMessage:) + @discardableResult public static func capture(message: String) -> SentryId { + return SentrySDKInternal.capture(message: message).sentryId + } + + /// Captures a message event and sends it to Sentry. Only the data in this scope object will be added + /// to the event. The global scope will be ignored. + /// - parameter message: The message to send to Sentry. + /// - parameter scope: The scope containing event metadata. + /// - returns: The `SentryId` of the event or `SentryId.empty` if the event is not sent. + @objc(captureMessage:withScope:) + @discardableResult public static func capture(message: String, scope: Scope) -> SentryId { + return SentrySDKInternal.capture(message: message, scope: scope).sentryId + } + + /// Captures a message event and sends it to Sentry. Maintains the global scope but mutates scope + /// data for only this call. + /// - parameter message: The message to send to Sentry. + /// - parameter block: The block mutating the scope only for this call. + /// - returns: The `SentryId` of the event or `SentryId.empty` if the event is not sent. + @objc(captureMessage:withScopeBlock:) + @discardableResult public static func capture(message: String, block: @escaping (Scope) -> Void) -> SentryId { + return SentrySDKInternal.capture(message: message, block: block).sentryId + } + + #if !SDK_V9 + /// Captures user feedback that was manually gathered and sends it to Sentry. + /// - parameter userFeedback: The user feedback to send to Sentry. + @available(*, deprecated, message: "Use SentrySDK.back or use or configure our new managed UX with SentryOptions.configureUserFeedback.") + @objc(captureUserFeedback:) + public static func capture(userFeedback: UserFeedback) { + SentrySDKInternal.capture(userFeedback: userFeedback) + } + #endif + + /// Captures user feedback that was manually gathered and sends it to Sentry. + /// - warning: This is an experimental feature and may still have bugs. + /// - parameter feedback: The feedback to send to Sentry. + /// - note: If you'd prefer not to have to build the UI required to gather the feedback from the user, + /// see `SentryOptions.configureUserFeedback` to customize a fully managed integration. See + /// https://docs.sentry.io/platforms/apple/user-feedback/ for more information. + @objc(captureFeedback:) + public static func capture(feedback: SentryFeedback) { + SentrySDKInternal.captureSerializedFeedback( + feedback.serialize(), + withEventId: feedback.eventId.sentryIdString, + attachments: feedback.attachmentsForEnvelope()) + } + + #if os(iOS) && !SENTRY_NO_UIKIT + @available(iOS 13.0, *) + @objc public static let feedback = { + return SentryFeedbackAPI() + }() + #endif + + /// Adds a `Breadcrumb` to the current `Scope` of the current `Hub`. If the total number of breadcrumbs + /// exceeds the `SentryOptions.maxBreadcrumbs` the SDK removes the oldest breadcrumb. + /// - parameter crumb: The `Breadcrumb` to add to the current `Scope` of the current `Hub`. + @objc(addBreadcrumb:) + public static func addBreadcrumb(_ crumb: Breadcrumb) { + SentrySDKInternal.addBreadcrumb(crumb) + } + + /// Use this method to modify the current `Scope` of the current `Hub`. The SDK uses the `Scope` to attach + /// contextual data to events. + /// - parameter callback: The callback for configuring the current `Scope` of the current `Hub`. + @objc(configureScope:) + public static func configureScope(_ callback: @escaping (Scope) -> Void) { + SentrySDKInternal.configureScope(callback) + } + + // MARK: - Crash Detection + + /// Checks if the last program execution terminated with a crash. + @objc public static var crashedLastRun: Bool { + return SentrySDKInternal.crashedLastRun + } + + /// Checks if the SDK detected a start-up crash during SDK initialization. + /// - note: The SDK init waits synchronously for up to 5 seconds to flush out events if the app crashes + /// within 2 seconds after the SDK init. + /// - returns: true if the SDK detected a start-up crash and false if not. + @objc public static var detectedStartUpCrash: Bool { + return SentrySDKInternal.detectedStartUpCrash + } + + // MARK: - User Management + + /// Set `user` to the current `Scope` of the current `Hub`. + /// - parameter user: The user to set to the current `Scope`. + /// - note: You must start the SDK before calling this method, otherwise it doesn't set the user. + @objc public static func setUser(_ user: User?) { + SentrySDKInternal.setUser(user) + } + + // MARK: - Session Management + + /// Starts a new `SentrySession`. If there's a running `SentrySession`, it ends it before starting the + /// new one. You can use this method in combination with `endSession` to manually track + /// sessions. The SDK uses `SentrySession` to inform Sentry about release and project + /// associated project health. + @objc public static func startSession() { + SentrySDKInternal.startSession() + } + + /// Ends the current `SentrySession`. You can use this method in combination with `startSession` to + /// manually track `SentrySessions`. The SDK uses `SentrySession` to inform Sentry about release and + /// project associated project health. + @objc public static func endSession() { + SentrySDKInternal.endSession() + } + + /// This forces a crash, useful to test the `SentryCrash` integration. + /// + /// - note: The SDK can't report a crash when a debugger is attached. Your application needs to run + /// without a debugger attached to capture the crash and send it to Sentry the next time you launch + /// your application. + @objc public static func crash() { + SentrySDKInternal.crash() + } + + /// Reports to the ongoing `UIViewController` transaction + /// that the screen contents are fully loaded and displayed, + /// which will create a new span. + /// + /// - seealso: + /// https://docs.sentry.io/platforms/cocoa/performance/instrumentation/automatic-instrumentation/#time-to-full-display + @objc public static func reportFullyDisplayed() { + SentrySDKInternal.reportFullyDisplayed() + } + + // MARK: - App Hang Tracking + + /// Pauses sending detected app hangs to Sentry. + /// + /// This method doesn't close the detection of app hangs. Instead, the app hang detection + /// will ignore detected app hangs until you call `resumeAppHangTracking`. + @objc public static func pauseAppHangTracking() { + SentrySDKInternal.pauseAppHangTracking() + } + + /// Resumes sending detected app hangs to Sentry. + @objc public static func resumeAppHangTracking() { + SentrySDKInternal.resumeAppHangTracking() + } + + /// Waits synchronously for the SDK to flush out all queued and cached items for up to the specified + /// timeout in seconds. If there is no internet connection, the function returns immediately. The SDK + /// doesn't dispose the client or the hub. + /// - parameter timeout: The time to wait for the SDK to complete the flush. + /// - note: This might take slightly longer than the specified timeout if there are many batched logs to capture. + @objc(flush:) + public static func flush(timeout: TimeInterval) { + let captureLogsDuration = captureLogs() + // Capturing batched logs should never take long, but we need to fall back to a sane value. + // This is a workaround for experimental logs, until we'll write batched logs to disk, + // to avoid data loss due to crashes. This is a trade-off until then. + SentrySDKInternal.flush(timeout: max(timeout / 2, timeout - captureLogsDuration)) + } + + /// Closes the SDK, uninstalls all the integrations, and calls `flush` with + /// `SentryOptions.shutdownTimeInterval`. + @objc public static func close() { + // Capturing batched logs should never take long, ignore the duration here. + _ = captureLogs() + SentrySDKInternal.close() + } + +#if !(os(watchOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) + /// Start a new continuous profiling session if one is not already running. + /// - warning: Continuous profiling mode is experimental and may still contain bugs. + /// - note: Unlike transaction-based profiling, continuous profiling does not take into account + /// `SentryOptions.profilesSampleRate` or `SentryOptions.profilesSampler`. If either of those + /// options are set, this method does nothing. + /// - note: Taking into account the above note, if `SentryOptions.configureProfiling` is not set, + /// calls to this method will always start a profile if one is not already running. This includes app + /// launch profiles configured with `SentryOptions.enableAppLaunchProfiling`. + /// - note: If neither `SentryOptions.profilesSampleRate` nor `SentryOptions.profilesSampler` are + /// set, and `SentryOptions.configureProfiling` is set, this method does nothing if the profiling + /// session is not sampled with respect to `SentryOptions.profileSessionSampleRate`, or if it is + /// sampled but the profiler is already running. + /// - note: If neither `SentryOptions.profilesSampleRate` nor `SentryOptions.profilesSampler` are + /// set, and `SentryOptions.configureProfiling` is set, this method does nothing if + /// `SentryOptions.profileLifecycle` is set to `trace`. In this scenario, the profiler is + /// automatically started and stopped depending on whether there is an active sampled span, so it is + /// not permitted to manually start profiling. + /// - note: Profiling is automatically disabled if a thread sanitizer is attached. + /// - seealso: https://docs.sentry.io/platforms/apple/guides/ios/profiling/#continuous-profiling + @objc public static func startProfiler() { + SentrySDKInternal.startProfiler() + } + + /// Stop a continuous profiling session if there is one ongoing. + /// - warning: Continuous profiling mode is experimental and may still contain bugs. + /// - note: Does nothing if `SentryOptions.profileLifecycle` is set to `trace`. + /// - note: Does not immediately stop the profiler. Profiling data is uploaded at regular timed + /// intervals; when the current interval completes, then the profiler stops and the data gathered + /// during that last interval is uploaded. + /// - note: If a new call to `startProfiler` that would start the profiler is made before the last + /// interval completes, the profiler will continue running until another call to stop is made. + /// - note: Profiling is automatically disabled if a thread sanitizer is attached. + /// - seealso: https://docs.sentry.io/platforms/apple/guides/ios/profiling/#continuous-profiling + @objc public static func stopProfiler() { + SentrySDKInternal.stopProfiler() + } + #endif + + // MARK: Internal + + /// - note: Conceptually internal but needs to be marked public with SPI for ObjC visibility + @objc @_spi(Private) public static func clearLogger() { + _loggerLock.synchronized { + _logger = nil + _loggerConfigured = false + } + } + + // MARK: Private + + private static var _loggerLock = NSLock() + private static var _logger: SentryLogger? + // Flag to re-create instance if accessed before SDK init. + private static var _loggerConfigured = false + + @discardableResult + private static func captureLogs() -> TimeInterval { + var duration: TimeInterval = 0.0 + _loggerLock.synchronized { + duration = _logger?.captureLogs() ?? 0.0 + } + return duration + } +} + +extension SentryIdWrapper { + var sentryId: SentryId { + SentryId(uuidString: sentryIdString) + } +} + +// swiftlint:enable file_length diff --git a/Sources/Swift/Helper/SentrySdkInfo.swift b/Sources/Swift/Helper/SentrySdkInfo.swift new file mode 100644 index 00000000000..a728e3a42b3 --- /dev/null +++ b/Sources/Swift/Helper/SentrySdkInfo.swift @@ -0,0 +1,157 @@ +@_implementationOnly import _SentryPrivate +import Foundation + +/** + * Describes the Sentry SDK and its configuration used to capture and transmit an event. + * @note Both name and version are required. + * @see https://develop.sentry.dev/sdk/event-payloads/sdk/ + */ +@_spi(Private) @objc public final class SentrySdkInfo: NSObject, SentrySerializable { + + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + @objc public static func global() -> Self { + Self(withOptions: SentrySDKInternal.currentHub().getClient()?.options) + } + + /** + * The name of the SDK. Examples: sentry.cocoa, sentry.cocoa.vapor, ... + */ + @objc public let name: String + + /** + * The version of the SDK. It should have the Semantic Versioning format MAJOR.MINOR.PATCH, without + * any prefix (no v or anything else in front of the major version number). Examples: + * 0.1.0, 1.0.0, 2.0.0-beta0 + */ + @objc public let version: String + + /** + * A list of names identifying enabled integrations. The list should + * have all enabled integrations, including default integrations. Default + * integrations are included because different SDK releases may contain different + * default integrations. + */ + @objc public let integrations: [String] + + /** + * A list of feature names identifying enabled SDK features. This list + * should contain all enabled SDK features. On some SDKs, enabling a feature in the + * options also adds an integration. We encourage tracking such features with either + * integrations or features but not both to reduce the payload size. + */ + @objc public let features: [String] + + /** + * A list of packages that were installed as part of this SDK or the + * activated integrations. Each package consists of a name in the format + * source:identifier and version. + */ + @objc public let packages: [[String: String]] + + /** + * A set of settings as part of this SDK. + */ + @objc public let settings: SentrySDKSettings + + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + @objc public convenience init(withOptions options: Options?) { + let features = SentryEnabledFeaturesBuilder.getEnabledFeatures(options: options) + var integrations = SentrySDKInternal.currentHub().trimmedInstalledIntegrationNames() + #if (os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT + if options?.enablePreWarmedAppStartTracing ?? false { + integrations.append("PreWarmedAppStartTracing") + } + #endif + var packages = SentryExtraPackages.getPackages() + let sdkPackage = SentrySdkPackage.global() + if let sdkPackage { + packages.insert(sdkPackage) + } + self.init( + name: SentryMeta.sdkName, + version: SentryMeta.versionString, + integrations: integrations, + features: features, + packages: Array(packages), + settings: SentrySDKSettings(options: options)) + } + + @objc public init(name: String?, version: String?, integrations: [String]?, features: [String]?, packages: [[String: String]]?, settings: SentrySDKSettings) { + self.name = name ?? "" + self.version = version ?? "" + self.integrations = integrations ?? [] + self.features = features ?? [] + self.packages = packages ?? [] + self.settings = settings + } + + // swiftlint:disable cyclomatic_complexity + @objc + public convenience init(dict: [AnyHashable: Any]) { + var name = "" + var version = "" + var integrations = Set() + var features = Set() + var packages = Set<[String: String]>() + var settings = SentrySDKSettings(dict: [:]) + + if let nameValue = dict["name"] as? String { + name = nameValue + } + + if let versionValue = dict["version"] as? String { + version = versionValue + } + + if let integrationArray = dict["integrations"] as? [Any] { + for item in integrationArray { + if let integration = item as? String { + integrations.insert(integration) + } + } + } + + if let featureArray = dict["features"] as? [Any] { + for item in featureArray { + if let feature = item as? String { + features.insert(feature) + } + } + } + + if let packageArray = dict["packages"] as? [Any] { + for item in packageArray { + if let package = item as? [String: Any], + let name = package["name"] as? String, + let version = package["version"] as? String { + packages.insert(["name": name, "version": version]) + } + } + } + + if let settingsDict = dict["settings"] as? NSDictionary { + settings = SentrySDKSettings(dict: settingsDict) + } + + self.init( + name: name, + version: version, + integrations: Array(integrations), + features: Array(features), + packages: Array(packages), + settings: settings + ) + } + // swiftlint:enable cyclomatic_complexity + + @objc public func serialize() -> [String: Any] { + [ + "name": self.name, + "version": self.version, + "integrations": self.integrations, + "features": self.features, + "packages": self.packages, + "settings": self.settings.serialize() + ] + } +} diff --git a/Sources/Swift/Helper/SentrySerialization+ReplayRecording.swift b/Sources/Swift/Helper/SentrySerialization+ReplayRecording.swift new file mode 100644 index 00000000000..5531445a981 --- /dev/null +++ b/Sources/Swift/Helper/SentrySerialization+ReplayRecording.swift @@ -0,0 +1,20 @@ +@_implementationOnly import _SentryPrivate + +extension SentryReplayRecording { + @objc public func data() -> Data? { + var recording = Data() + guard let headerData = SentrySerialization.data(withJSONObject: headerForReplayRecording()) else { + SentrySDKLog.error("Failed to serialize replay recording header.") + return nil + } + recording.append(headerData) + let newLineData = Data(bytes: "\n", count: 1) + recording.append(newLineData) + guard let replayData = SentrySerialization.data(withJSONObject: serialize()) else { + SentrySDKLog.error("Failed to serialize replay recording data.") + return nil + } + recording.append(replayData) + return recording + } +} diff --git a/Sources/Swift/Helper/ThreadSafeApplication.swift b/Sources/Swift/Helper/ThreadSafeApplication.swift new file mode 100644 index 00000000000..1e8bee59b4b --- /dev/null +++ b/Sources/Swift/Helper/ThreadSafeApplication.swift @@ -0,0 +1,49 @@ +#if !os(macOS) && !os(watchOS) && !SENTRY_NO_UIKIT +import UIKit + +@objc @_spi(Private) public final class SentryThreadsafeApplication: NSObject { + private let notificationCenter: SentryNSNotificationCenterWrapper + + @objc public init(initialState: UIApplication.State, notificationCenter: SentryNSNotificationCenterWrapper) { + self.notificationCenter = notificationCenter + _internalState = initialState + super.init() + + notificationCenter.addObserver(self, selector: #selector(didEnterBackground), name: UIApplication.didEnterBackgroundNotification, object: nil) + notificationCenter.addObserver(self, selector: #selector(didBecomeActive), name: UIApplication.didBecomeActiveNotification, object: nil) + } + + deinit { + notificationCenter.removeObserver(self, name: nil, object: nil) + } + + private let lock = NSRecursiveLock() + private var _internalState: UIApplication.State + @objc public var applicationState: UIApplication.State { + var state: UIApplication.State + lock.lock() + state = _internalState + lock.unlock() + return state + } + + @objc + public var isActive: Bool { + return applicationState == .active + } + + @objc + private func didEnterBackground() { + lock.lock() + _internalState = .background + lock.unlock() + } + + @objc + private func didBecomeActive() { + lock.lock() + _internalState = .active + lock.unlock() + } +} +#endif diff --git a/Sources/Swift/Integrations/Screenshot/SentryScreenshotOptions.swift b/Sources/Swift/Integrations/Screenshot/SentryScreenshotOptions.swift new file mode 100644 index 00000000000..47129d71b5e --- /dev/null +++ b/Sources/Swift/Integrations/Screenshot/SentryScreenshotOptions.swift @@ -0,0 +1,180 @@ +import Foundation + +@objcMembers +public class SentryViewScreenshotOptions: NSObject, SentryRedactOptions { + /** + * Default values for the screenshot options. + * + * - Note: These values are used to ensure the different initializers use the same default values. + */ + public class DefaultValues { + public static let enableViewRendererV2: Bool = true + public static let enableFastViewRendering: Bool = false + + public static let maskAllText: Bool = true + public static let maskAllImages: Bool = true + public static let maskedViewClasses: [AnyClass] = [] + public static let unmaskedViewClasses: [AnyClass] = [] + } + + // MARK: - Rendering + + /** + * Enables the up to 5x faster new view renderer. + * + * Enabling this flag will reduce the amount of time it takes to render the screenshot on the main thread, therefore reducing + * interruptions and visual lag. [Our benchmarks](https://github.com/getsentry/sentry-cocoa/pull/4940) have shown a significant improvement of + * **up to 4-5x faster rendering** (reducing `~160ms` to `~36ms`) on older devices. + * + * - Experiment: In case you are noticing issues with the new view renderer, please report the issue on [GitHub](https://github.com/getsentry/sentry-cocoa). + * Eventually, we will remove this feature flag and use the new view renderer by default. + * + * - Note: See ``SentryViewScreenshotOptions.init`` for the default value. + */ + public var enableViewRendererV2: Bool + + /** + * Enables up to 5x faster but incomplete view rendering. + * + * Enabling this flag will reduce the amount of time it takes to render the screenshot, therefore reducing + * interruptions and visual lag. [Our benchmarks](https://github.com/getsentry/sentry-cocoa/pull/4940) have shown a significant improvement of + * up to **5x faster render times** (reducing `~160ms` to `~30ms`) on older devices. + * + * This flag controls the way the view hierarchy is drawn into a graphics context. By default, the view hierarchy is drawn using + * the `UIView.drawHierarchy(in:afterScreenUpdates:)` method, which is the most complete way to render the view hierarchy. However, + * this method can be slow, especially when rendering complex views, therefore enabling this flag will switch to render the underlying `CALayer` instead. + * + * - Note: This flag can only be used together with `enableViewRendererV2` with up to 20% faster render times. + * - Warning: Rendering the view hiearchy using the `CALayer.render(in:)` method can lead to rendering issues, especially when using custom views. + * For complete rendering, it is recommended to set this option to `false`. In case you prefer performance over completeness, you can + * set this option to `true`. + * - Experiment: This is an experimental feature and is therefore disabled by default. In case you are noticing issues with the experimental + * view renderer, please report the issue on [GitHub](https://github.com/getsentry/sentry-cocoa). Eventually, we will + * mark this feature as stable and remove the experimental flag, but will keep it disabled by default. + * + * - Note: See ``SentryViewScreenshotOptions.init`` for the default value. + */ + public var enableFastViewRendering: Bool + + // MARK: - Masking + + /** + * Indicates whether the screenshot should redact all non-bundled image + * in the app by drawing a black rectangle over it. + * + * - Note: See ``SentryViewScreenshotOptions.init`` for the default value. + */ + public var maskAllImages: Bool + + /** + * Indicates whether the screenshot should redact all text in the app + * by drawing a black rectangle over it. + * + * - Note: See ``SentryViewScreenshotOptions.init`` for the default value. + */ + public var maskAllText: Bool + + /** + * A list of custom UIView subclasses that need + * to be masked during the screenshot. + * By default Sentry already mask text and image elements from UIKit + * Every child of a view that is redacted will also be redacted. + * + * - Note: See ``SentryViewScreenshotOptions.init`` for the default value. + */ + public var maskedViewClasses: [AnyClass] + + /** + * A list of custom UIView subclasses to be ignored + * during masking step of the screenshot. + * The views of given classes will not be redacted but their children may be. + * This property has precedence over `redactViewTypes`. + * + * - Note: See ``SentryViewScreenshotOptions.init`` for the default value. + */ + public var unmaskedViewClasses: [AnyClass] + + /** + * Initialize screenshot options disabled + * + * - Note: This initializer is added for Objective-C compatibility, as constructors with default values + * are not supported in Objective-C. + * - Note: See ``SentryViewScreenshotOptions.DefaultValues`` for the default values of each parameter. + */ + public convenience override init() { + // Setting all properties to nil will fallback to the default values in the init method. + self.init( + enableViewRendererV2: DefaultValues.enableViewRendererV2, + enableFastViewRendering: DefaultValues.enableFastViewRendering, + maskAllText: DefaultValues.maskAllText, + maskAllImages: DefaultValues.maskAllImages, + maskedViewClasses: DefaultValues.maskedViewClasses, + unmaskedViewClasses: DefaultValues.unmaskedViewClasses + ) + } + + /** + * Initializes a new instance of ``SentryViewScreenshotOptions`` using a dictionary. + * + * - Parameter dictionary: A dictionary containing the configuration options for the screenshot. + * + * - Warning: This initializer is primarily used by Hybrid SDKs and is not intended for public use. + */ + convenience init(dictionary: [String: Any]) { + // This initalizer is calling the one with optional parameters, so that defaults can be applied + // for absent values. + self.init( + enableViewRendererV2: (dictionary["enableViewRendererV2"] as? NSNumber)?.boolValue ?? DefaultValues.enableViewRendererV2, + enableFastViewRendering: (dictionary["enableFastViewRendering"] as? NSNumber)?.boolValue ?? DefaultValues.enableFastViewRendering, + maskAllText: (dictionary["maskAllText"] as? NSNumber)?.boolValue ?? DefaultValues.maskAllText, + maskAllImages: (dictionary["maskAllImages"] as? NSNumber)?.boolValue ?? DefaultValues.maskAllImages, + maskedViewClasses: (dictionary["maskedViewClasses"] as? NSArray)?.compactMap({ element in + NSClassFromString((element as? String) ?? "") + }) ?? DefaultValues.maskedViewClasses, + unmaskedViewClasses: (dictionary["unmaskedViewClasses"] as? NSArray)?.compactMap({ element in + NSClassFromString((element as? String) ?? "") + }) ?? DefaultValues.unmaskedViewClasses + ) + } + + /** + * Initializes a new instance of ``SentryViewScreenshotOptions`` with the specified parameters. + * + * - Parameters: + * - enableViewRendererV2: Enables the up to 5x faster view renderer. + * - enableFastViewRendering: Enables faster but incomplete view rendering. See ``SentryViewScreenshotOptions.enableFastViewRendering`` for more information. + * - maskAllText: Flag to redact all text in the app by drawing a rectangle over it. + * - maskAllImages: Flag to redact all images in the app by drawing a rectangle over it. + * - maskedViewClasses: A list of custom UIView subclasses that need to be masked during the screenshot. + * - unmaskedViewClasses: A list of custom UIView subclasses to be ignored during masking step of the screenshot. + * + * - Note: See ``SentryViewScreenshotOptions.DefaultValues`` for the default values of each parameter. + */ + public init( + enableViewRendererV2: Bool = DefaultValues.enableViewRendererV2, + enableFastViewRendering: Bool = DefaultValues.enableFastViewRendering, + maskAllText: Bool = DefaultValues.maskAllText, + maskAllImages: Bool = DefaultValues.maskAllImages, + maskedViewClasses: [AnyClass] = DefaultValues.maskedViewClasses, + unmaskedViewClasses: [AnyClass] = DefaultValues.unmaskedViewClasses + ) { + // - This initializer is publicly available for Swift, but not for Objective-C, because automatically bridged Swift initializers + // with default values result in a single initializer requiring all parameters. + // - Each parameter has a default value, so the parameter can be omitted, which is not possible for Objective-C. + // - Parameter values are not optional, because SDK users should not be able to set them to nil. + // - The publicly available property `quality` is omitted in this initializer, because adding it would break backwards compatibility + // with the automatically bridged Objective-C initializer. + self.enableViewRendererV2 = enableViewRendererV2 + self.enableFastViewRendering = enableFastViewRendering + self.maskAllText = maskAllText + self.maskAllImages = maskAllImages + self.maskedViewClasses = maskedViewClasses + self.unmaskedViewClasses = unmaskedViewClasses + + super.init() + } + + public override var description: String { + return "SentryViewScreenshotOptions(enableViewRendererV2: \(enableViewRendererV2), enableFastViewRendering: \(enableFastViewRendering), maskAllText: \(maskAllText), maskAllImages: \(maskAllImages), maskedViewClasses: \(maskedViewClasses), unmaskedViewClasses: \(unmaskedViewClasses))" + } +} diff --git a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebEvent.swift b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebEvent.swift index 1010af7eaed..392c6876893 100644 --- a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebEvent.swift +++ b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebEvent.swift @@ -17,7 +17,8 @@ enum SentryRRWebEventType: Int { @_spi(Private) public class SentryRRWebEvent: NSObject, SentryRRWebEventProtocol { let type: SentryRRWebEventType let timestamp: Date - let data: [String: Any]? + // Visible only for the RN SDK + @_spi(Private) public let data: [String: Any]? init(type: SentryRRWebEventType, timestamp: Date, data: [String: Any]?) { self.type = type diff --git a/Sources/Swift/Integrations/SessionReplay/SentryOnDemandReplay.swift b/Sources/Swift/Integrations/SessionReplay/SentryOnDemandReplay.swift index 011ba23dc37..54adfa08b79 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentryOnDemandReplay.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentryOnDemandReplay.swift @@ -224,19 +224,14 @@ import UIKit // swiftlint:disable function_body_length cyclomatic_complexity private func renderVideo(with videoFrames: [SentryReplayFrame], from: Int, at outputFileURL: URL, completion: @escaping (Result) -> Void) { SentrySDKLog.debug("[Session Replay] Rendering video with \(videoFrames.count) frames, from index: \(from), to output url: \(outputFileURL)") + guard from < videoFrames.count else { SentrySDKLog.error("[Session Replay] Failed to render video, reason: index out of bounds") - return completion(.success(SentryRenderVideoResult( - info: nil, - finalFrameIndex: from - ))) + return completion(.failure(SentryOnDemandReplayError.indexOutOfBounds)) } guard let image = UIImage(contentsOfFile: videoFrames[from].imagePath) else { SentrySDKLog.error("[Session Replay] Failed to render video, reason: can't read image at path: \(videoFrames[from].imagePath)") - return completion(.success(SentryRenderVideoResult( - info: nil, - finalFrameIndex: from - ))) + return completion(.failure(SentryOnDemandReplayError.cantReadImage)) } let videoWidth = image.size.width * CGFloat(videoScale) @@ -262,23 +257,17 @@ import UIKit videoWriter.startWriting() videoWriter.startSession(atSourceTime: .zero) - var lastImageSize: CGSize = image.size - var usedFrames = [SentryReplayFrame]() - var frameIndex = from - - // Convenience wrapper to handle the completion callback to return the video info and the final frame index - // It is not possible to use an inout frame index here, because the closure is escaping and the frameIndex variable is captured. - let deferredCompletionCallback: (Result) -> Void = { result in - switch result { - case .success(let videoResult): - completion(.success(SentryRenderVideoResult( - info: videoResult, - finalFrameIndex: frameIndex - ))) - case .failure(let error): - completion(.failure(error)) - } - } + let frameProcessor = SentryVideoFrameProcessor( + videoFrames: videoFrames, + videoWriter: videoWriter, + currentPixelBuffer: currentPixelBuffer, + outputFileURL: outputFileURL, + videoHeight: videoHeight, + videoWidth: videoWidth, + frameRate: frameRate, + initialFrameIndex: from, + initialImageSize: image.size + ) // Append frames to the video writer input in a pull-style manner when the input is ready to receive more media data. // @@ -290,145 +279,11 @@ import UIKit // // By setting the queue to the asset worker queue, we ensure that the callback is invoked on the asset worker queue. // This is important to avoid a deadlock, as this method is called on the processing queue. - videoWriterInput.requestMediaDataWhenReady(on: assetWorkerQueue.queue) { [weak self] in - SentrySDKLog.debug("[Session Replay] Video writer input is ready, status: \(videoWriter.status)") - guard let strongSelf = self else { - SentrySDKLog.warning("[Session Replay] On-demand replay is deallocated, completing writing session without output video info") - return deferredCompletionCallback(.success(nil)) - } - guard videoWriter.status == .writing else { - SentrySDKLog.error("[Session Replay] Video writer is not writing anymore, cancelling the writing session, reason: \(videoWriter.error?.localizedDescription ?? "Unknown error")") - videoWriter.cancelWriting() - return deferredCompletionCallback(.failure(videoWriter.error ?? SentryOnDemandReplayError.errorRenderingVideo)) - } - guard frameIndex < videoFrames.count else { - SentrySDKLog.debug("[Session Replay] No more frames available to process, finishing the video") - return strongSelf.finishVideo( - outputFileURL: outputFileURL, - usedFrames: usedFrames, - videoHeight: Int(videoHeight), - videoWidth: Int(videoWidth), - videoWriter: videoWriter, - onCompletion: deferredCompletionCallback - ) - } - - let frame = videoFrames[frameIndex] - if let image = UIImage(contentsOfFile: frame.imagePath) { - SentrySDKLog.debug("[Session Replay] Image at index \(frameIndex) is ready, size: \(image.size)") - guard lastImageSize == image.size else { - SentrySDKLog.debug("[Session Replay] Image size has changed, finishing video") - return strongSelf.finishVideo( - outputFileURL: outputFileURL, - usedFrames: usedFrames, - videoHeight: Int(videoHeight), - videoWidth: Int(videoWidth), - videoWriter: videoWriter, - onCompletion: deferredCompletionCallback - ) - } - lastImageSize = image.size - - let presentTime = SentryOnDemandReplay.calculatePresentationTime( - forFrameAtIndex: frameIndex, - frameRate: strongSelf.frameRate - ).timeValue - guard currentPixelBuffer.append(image: image, presentationTime: presentTime) else { - SentrySDKLog.error("[Session Replay] Failed to append image to pixel buffer, cancelling the writing session, reason: \(String(describing: videoWriter.error))") - videoWriter.cancelWriting() - return deferredCompletionCallback(.failure(videoWriter.error ?? SentryOnDemandReplayError.errorRenderingVideo)) - } - usedFrames.append(frame) - } - - // Increment the frame index even if the image could not be appended to the pixel buffer. - // This is important to avoid an infinite loop. - frameIndex += 1 + videoWriterInput.requestMediaDataWhenReady(on: assetWorkerQueue.queue) { + frameProcessor.processFrames(videoWriterInput: videoWriterInput, onCompletion: completion) } } - // swiftlint:enable function_body_length cyclomatic_complexity - private func finishVideo( - outputFileURL: URL, - usedFrames: [SentryReplayFrame], - videoHeight: Int, - videoWidth: Int, - videoWriter: AVAssetWriter, - onCompletion completion: @escaping (Result) -> Void - ) { - // Note: This method is expected to be called from the asset worker queue and *not* the processing queue. - SentrySDKLog.info("[Session Replay] Finishing video with output file URL: \(outputFileURL), used frames count: \(usedFrames.count), video height: \(videoHeight), video width: \(videoWidth)") - videoWriter.inputs.forEach { $0.markAsFinished() } - videoWriter.finishWriting { [weak self] in - SentrySDKLog.debug("[Session Replay] Finished video writing, status: \(videoWriter.status)") - guard let strongSelf = self else { - SentrySDKLog.warning("[Session Replay] On-demand replay is deallocated, completing writing session without output video info") - return completion(.success(nil)) - } - - switch videoWriter.status { - case .writing: - SentrySDKLog.error("[Session Replay] Finish writing video was called with status writing, this is unexpected! Completing with no video info") - completion(.success(nil)) - case .cancelled: - SentrySDKLog.warning("[Session Replay] Finish writing video was cancelled, completing with no video info.") - completion(.success(nil)) - case .completed: - SentrySDKLog.debug("[Session Replay] Finish writing video was completed, creating video info from file attributes.") - do { - let result = try strongSelf.getVideoInfo( - from: outputFileURL, - usedFrames: usedFrames, - videoWidth: Int(videoWidth), - videoHeight: Int(videoHeight) - ) - completion(.success(result)) - } catch { - SentrySDKLog.warning("[Session Replay] Failed to create video info from file attributes, reason: \(error)") - completion(.failure(error)) - } - case .failed: - SentrySDKLog.warning("[Session Replay] Finish writing video failed, reason: \(String(describing: videoWriter.error))") - completion(.failure(videoWriter.error ?? SentryOnDemandReplayError.errorRenderingVideo)) - case .unknown: - SentrySDKLog.warning("[Session Replay] Finish writing video with unknown status, reason: \(String(describing: videoWriter.error))") - completion(.failure(videoWriter.error ?? SentryOnDemandReplayError.errorRenderingVideo)) - @unknown default: - SentrySDKLog.warning("[Session Replay] Finish writing video in unknown state, reason: \(String(describing: videoWriter.error))") - completion(.failure(SentryOnDemandReplayError.errorRenderingVideo)) - } - } - } - - fileprivate func getVideoInfo(from outputFileURL: URL, usedFrames: [SentryReplayFrame], videoWidth: Int, videoHeight: Int) throws -> SentryVideoInfo { - SentrySDKLog.debug("[Session Replay] Getting video info from file: \(outputFileURL.path), width: \(videoWidth), height: \(videoHeight), used frames count: \(usedFrames.count)") - let fileAttributes = try FileManager.default.attributesOfItem(atPath: outputFileURL.path) - guard let fileSize = fileAttributes[FileAttributeKey.size] as? Int else { - SentrySDKLog.warning("[Session Replay] Failed to read video size from video file, reason: size attribute not found") - throw SentryOnDemandReplayError.cantReadVideoSize - } - let minFrame = usedFrames.min(by: { $0.time < $1.time }) - guard let start = minFrame?.time else { - // Note: This code path is currently not reached, because the `getVideoInfo` method is only called after the video is successfully created, therefore at least one frame was used. - // The compiler still requires us to unwrap the optional value, and we do not permit force-unwrapping. - SentrySDKLog.warning("[Session Replay] Failed to read video start time from used frames, reason: no frames found") - throw SentryOnDemandReplayError.cantReadVideoStartTime - } - let duration = TimeInterval(usedFrames.count / self.frameRate) - return SentryVideoInfo( - path: outputFileURL, - height: videoHeight, - width: videoWidth, - duration: duration, - frameCount: usedFrames.count, - frameRate: self.frameRate, - start: start, - end: start.addingTimeInterval(duration), - fileSize: fileSize, - screens: usedFrames.compactMap({ $0.screenName }) - ) - } - internal func createVideoSettings(width: CGFloat, height: CGFloat) -> [String: Any] { return [ // The codec type for the video. H.264 (AVC) is the most widely supported codec across platforms, diff --git a/Sources/Swift/Integrations/SessionReplay/SentryOnDemandReplayError.swift b/Sources/Swift/Integrations/SessionReplay/SentryOnDemandReplayError.swift index 7b060ad97d1..81ead3d9685 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentryOnDemandReplayError.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentryOnDemandReplayError.swift @@ -1,6 +1,8 @@ enum SentryOnDemandReplayError: Error { case cantReadVideoSize case cantCreatePixelBuffer + case cantReadImage case errorRenderingVideo case cantReadVideoStartTime + case indexOutOfBounds } diff --git a/Sources/Swift/Integrations/SessionReplay/SentryPixelBuffer.swift b/Sources/Swift/Integrations/SessionReplay/SentryPixelBuffer.swift index be923e98687..88d1becbe39 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentryPixelBuffer.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentryPixelBuffer.swift @@ -6,7 +6,11 @@ import CoreGraphics import Foundation import UIKit -final class SentryPixelBuffer { +protocol SentryAppendablePixelBuffer { + func append(image: UIImage, presentationTime: CMTime) -> Bool +} + +final class SentryPixelBuffer: SentryAppendablePixelBuffer { private var pixelBuffer: CVPixelBuffer? private let rgbColorSpace = CGColorSpaceCreateDeviceRGB() private let size: CGSize diff --git a/Sources/Swift/Integrations/SessionReplay/SentryReplayEvent.swift b/Sources/Swift/Integrations/SessionReplay/SentryReplayEvent.swift index 8d5a1e0d115..eb4893860bd 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentryReplayEvent.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentryReplayEvent.swift @@ -36,7 +36,7 @@ import Foundation fatalError("init() has not been implemented") } - public override func serialize() -> [String: Any] { + @_implementationOnly public override func serialize() -> [String: Any] { var result = super.serialize() result["urls"] = urls result["replay_start_timestamp"] = replayStartTimestamp.timeIntervalSince1970 diff --git a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift index f404fe02874..6520f49b1c2 100644 --- a/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift +++ b/Sources/Swift/Integrations/SessionReplay/SentryReplayOptions.swift @@ -193,7 +193,7 @@ public class SentryReplayOptions: NSObject, SentryRedactOptions { public var enableViewRendererV2: Bool /** - * Enables up to 5x faster but incommpelte view rendering used by the Session Replay integration. + * Enables up to 5x faster but incomplete view rendering used by the Session Replay integration. * * Enabling this flag will reduce the amount of time it takes to render each frame of the session replay on the main thread, therefore reducing * interruptions and visual lag. [Our benchmarks](https://github.com/getsentry/sentry-cocoa/pull/4940) have shown a significant improvement of diff --git a/Sources/Swift/Integrations/SessionReplay/SentryVideoFrameProcessor.swift b/Sources/Swift/Integrations/SessionReplay/SentryVideoFrameProcessor.swift new file mode 100644 index 00000000000..889db33f8e9 --- /dev/null +++ b/Sources/Swift/Integrations/SessionReplay/SentryVideoFrameProcessor.swift @@ -0,0 +1,178 @@ +#if canImport(UIKit) && !SENTRY_NO_UIKIT +#if os(iOS) || os(tvOS) + +import AVFoundation +import CoreGraphics +import Foundation +import UIKit + +class SentryVideoFrameProcessor { + let videoFrames: [SentryReplayFrame] + let videoWriter: AVAssetWriter + let currentPixelBuffer: SentryAppendablePixelBuffer + let outputFileURL: URL + let videoHeight: CGFloat + let videoWidth: CGFloat + let frameRate: Int + + var frameIndex: Int + var lastImageSize: CGSize + var usedFrames: [SentryReplayFrame] + var isFinished: Bool + + init( + videoFrames: [SentryReplayFrame], + videoWriter: AVAssetWriter, + currentPixelBuffer: SentryAppendablePixelBuffer, + outputFileURL: URL, + videoHeight: CGFloat, + videoWidth: CGFloat, + frameRate: Int, + initialFrameIndex: Int, + initialImageSize: CGSize + ) { + self.videoFrames = videoFrames + self.videoWriter = videoWriter + self.currentPixelBuffer = currentPixelBuffer + self.outputFileURL = outputFileURL + self.videoHeight = videoHeight + self.videoWidth = videoWidth + self.frameRate = frameRate + + self.frameIndex = initialFrameIndex + self.lastImageSize = initialImageSize + self.usedFrames = [] + self.isFinished = false + } + + func processFrames(videoWriterInput: AVAssetWriterInput, onCompletion: @escaping (Result) -> Void) { + // Use the recommended loop pattern for AVAssetWriterInput + // See https://developer.apple.com/documentation/avfoundation/avassetwriterinput/requestmediadatawhenready(on:using:)#Discussion + // This could lead to an infinite loop if we don't make sure to mark the input as finished when the video is finished either by the end of the frames or by an error. + while videoWriterInput.isReadyForMoreMediaData { + SentrySDKLog.debug("[Session Replay] Video writer input is ready, status: \(videoWriter.status)") + guard videoWriter.status == .writing else { + SentrySDKLog.error("[Session Replay] Video writer is not writing anymore, cancelling the writing session, reason: \(videoWriter.error?.localizedDescription ?? "Unknown error")") + videoWriter.inputs.forEach { $0.markAsFinished() } + videoWriter.cancelWriting() + return onCompletion(.failure(videoWriter.error ?? SentryOnDemandReplayError.errorRenderingVideo)) + } + guard frameIndex < videoFrames.count else { + SentrySDKLog.debug("[Session Replay] No more frames available to process, finishing the video") + return finishVideo(frameIndex: self.frameIndex, onCompletion: onCompletion) + } + + let frame = videoFrames[frameIndex] + defer { + // Increment the frame index even if the image could not be appended to the pixel buffer. + // This is important to avoid an infinite loop. + frameIndex += 1 + } + guard let image = UIImage(contentsOfFile: frame.imagePath) else { + // Continue with the next frame + continue + } + + SentrySDKLog.debug("[Session Replay] Image at index \(frameIndex) is ready, size: \(image.size)") + guard lastImageSize == image.size else { + SentrySDKLog.debug("[Session Replay] Image size has changed, finishing video") + return finishVideo(frameIndex: self.frameIndex, onCompletion: onCompletion) + } + lastImageSize = image.size + + let presentTime = SentryOnDemandReplay.calculatePresentationTime( + forFrameAtIndex: frameIndex, + frameRate: frameRate + ).timeValue + guard currentPixelBuffer.append(image: image, presentationTime: presentTime) else { + SentrySDKLog.error("[Session Replay] Failed to append image to pixel buffer, cancelling the writing session, reason: \(String(describing: videoWriter.error))") + videoWriter.inputs.forEach { $0.markAsFinished() } + videoWriter.cancelWriting() + return onCompletion(.failure(videoWriter.error ?? SentryOnDemandReplayError.errorRenderingVideo)) + } + usedFrames.append(frame) + } + } + + // swiftlint:enable function_body_length cyclomatic_complexity + func finishVideo(frameIndex: Int, onCompletion completion: @escaping (Result) -> Void) { + // Note: This method is expected to be called from the asset worker queue and *not* the processing queue. + SentrySDKLog.info("[Session Replay] Finishing video with output file URL: \(outputFileURL), used frames count: \(usedFrames.count), video height: \(videoHeight), video width: \(videoWidth)") + videoWriter.inputs.forEach { $0.markAsFinished() } + videoWriter.finishWriting { [weak self] in + guard let self = self else { + SentrySDKLog.warning("[Session Replay] On-demand replay is deallocated, completing writing session without output video info") + let videoResult = SentryRenderVideoResult(info: nil, finalFrameIndex: frameIndex) + return completion(.success(videoResult)) + } + SentrySDKLog.debug("[Session Replay] Finished video writing, status: \(self.videoWriter.status)") + + switch self.videoWriter.status { + case .writing: + SentrySDKLog.error("[Session Replay] Finish writing video was called with status writing, this is unexpected! Completing with no video info") + let videoResult = SentryRenderVideoResult(info: nil, finalFrameIndex: frameIndex) + return completion(.success(videoResult)) + case .cancelled: + SentrySDKLog.warning("[Session Replay] Finish writing video was cancelled, completing with no video info.") + let videoResult = SentryRenderVideoResult(info: nil, finalFrameIndex: frameIndex) + return completion(.success(videoResult)) + case .completed: + SentrySDKLog.debug("[Session Replay] Finish writing video was completed, creating video info from file attributes.") + do { + let videoInfo = try self.getVideoInfo( + from: self.outputFileURL, + usedFrames: self.usedFrames, + videoWidth: Int(self.videoWidth), + videoHeight: Int(self.videoHeight) + ) + let videoResult = SentryRenderVideoResult(info: videoInfo, finalFrameIndex: frameIndex) + completion(.success(videoResult)) + } catch { + SentrySDKLog.warning("[Session Replay] Failed to create video info from file attributes, reason: \(error)") + completion(.failure(error)) + } + case .failed: + SentrySDKLog.warning("[Session Replay] Finish writing video failed, reason: \(String(describing: self.videoWriter.error))") + completion(.failure(self.videoWriter.error ?? SentryOnDemandReplayError.errorRenderingVideo)) + case .unknown: + SentrySDKLog.warning("[Session Replay] Finish writing video with unknown status, reason: \(String(describing: self.videoWriter.error))") + completion(.failure(self.videoWriter.error ?? SentryOnDemandReplayError.errorRenderingVideo)) + @unknown default: + SentrySDKLog.warning("[Session Replay] Finish writing video in unknown state, reason: \(String(describing: self.videoWriter.error))") + completion(.failure(SentryOnDemandReplayError.errorRenderingVideo)) + } + } + } + + func getVideoInfo(from outputFileURL: URL, usedFrames: [SentryReplayFrame], videoWidth: Int, videoHeight: Int) throws -> SentryVideoInfo { + SentrySDKLog.debug("[Session Replay] Getting video info from file: \(outputFileURL.path), width: \(videoWidth), height: \(videoHeight), used frames count: \(usedFrames.count)") + let fileAttributes = try FileManager.default.attributesOfItem(atPath: outputFileURL.path) + guard let fileSize = fileAttributes[FileAttributeKey.size] as? Int else { + SentrySDKLog.warning("[Session Replay] Failed to read video size from video file, reason: size attribute not found") + throw SentryOnDemandReplayError.cantReadVideoSize + } + let minFrame = usedFrames.min(by: { $0.time < $1.time }) + guard let start = minFrame?.time else { + // Note: This code path is currently not reached, because the `getVideoInfo` method is only called after the video is successfully created, therefore at least one frame was used. + // The compiler still requires us to unwrap the optional value, and we do not permit force-unwrapping. + SentrySDKLog.warning("[Session Replay] Failed to read video start time from used frames, reason: no frames found") + throw SentryOnDemandReplayError.cantReadVideoStartTime + } + let duration = TimeInterval(usedFrames.count / self.frameRate) + return SentryVideoInfo( + path: outputFileURL, + height: videoHeight, + width: videoWidth, + duration: duration, + frameCount: usedFrames.count, + frameRate: self.frameRate, + start: start, + end: start.addingTimeInterval(duration), + fileSize: fileSize, + screens: usedFrames.compactMap({ $0.screenName }) + ) + } +} + +#endif // os(iOS) || os(tvOS) +#endif // canImport(UIKit) && !SENTRY_NO_UIKIT diff --git a/Sources/Swift/Integrations/UserFeedback/SentryFeedback.swift b/Sources/Swift/Integrations/UserFeedback/SentryFeedback.swift index 7ae287492c1..c22eb600c02 100644 --- a/Sources/Swift/Integrations/UserFeedback/SentryFeedback.swift +++ b/Sources/Swift/Integrations/UserFeedback/SentryFeedback.swift @@ -1,3 +1,4 @@ +@_implementationOnly import _SentryPrivate import Foundation @objcMembers @@ -41,8 +42,22 @@ public class SentryFeedback: NSObject { } } -extension SentryFeedback: SentrySerializable { +#if !SDK_V9 +extension SentryFeedback: SentrySerializable { } +#endif + +extension SentryFeedback { + #if SDK_V9 + @_spi(Private) public func serialize() -> [String: Any] { + return internalSerialize() + } + #else public func serialize() -> [String: Any] { + return internalSerialize() + } + #endif + + private func internalSerialize() -> [String: Any] { let numberOfOptionalItems = (name == nil ? 0 : 1) + (email == nil ? 0 : 1) + (associatedEventId == nil ? 0 : 1) var dict = [String: Any](minimumCapacity: 2 + numberOfOptionalItems) dict["message"] = message diff --git a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift index 2bbffe308ff..da1d316025f 100644 --- a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift +++ b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackIntegrationDriver.swift @@ -13,18 +13,19 @@ import UIKit * - note: The default method to show the feedback form is via a floating widget placed in the bottom trailing corner of the screen. See the configuration classes for alternative options. */ @available(iOS 13.0, *) +@available(iOSApplicationExtension, unavailable) @objcMembers @_spi(Private) public class SentryUserFeedbackIntegrationDriver: NSObject { let configuration: SentryUserFeedbackConfiguration private var widget: SentryUserFeedbackWidget? weak var delegate: (any SentryUserFeedbackIntegrationDriverDelegate)? - let screenshotProvider: SentryScreenshot + let screenshotSource: SentryScreenshotSource weak var customButton: UIButton? - @_spi(Private) public init(configuration: SentryUserFeedbackConfiguration, delegate: any SentryUserFeedbackIntegrationDriverDelegate, screenshotProvider: SentryScreenshot) { + @_spi(Private) public init(configuration: SentryUserFeedbackConfiguration, delegate: any SentryUserFeedbackIntegrationDriverDelegate, screenshotSource: SentryScreenshotSource) { self.configuration = configuration self.delegate = delegate - self.screenshotProvider = screenshotProvider + self.screenshotSource = screenshotSource super.init() if let uiFormConfigBuilder = configuration.configureForm { @@ -85,6 +86,7 @@ import UIKit // MARK: SentryUserFeedbackFormDelegate @available(iOS 13.0, *) +@available(iOSApplicationExtension, unavailable) extension SentryUserFeedbackIntegrationDriver: SentryUserFeedbackFormDelegate { func finished(with feedback: SentryFeedback?) { if let feedback = feedback { @@ -100,6 +102,7 @@ extension SentryUserFeedbackIntegrationDriver: SentryUserFeedbackFormDelegate { // MARK: SentryUserFeedbackWidgetDelegate @available(iOS 13.0, *) +@available(iOSApplicationExtension, unavailable) extension SentryUserFeedbackIntegrationDriver: SentryUserFeedbackWidgetDelegate { func showForm() { showForm(screenshot: nil) @@ -108,6 +111,7 @@ extension SentryUserFeedbackIntegrationDriver: SentryUserFeedbackWidgetDelegate // MARK: UIAdaptivePresentationControllerDelegate @available(iOS 13.0, *) +@available(iOSApplicationExtension, unavailable) extension SentryUserFeedbackIntegrationDriver: UIAdaptivePresentationControllerDelegate { public func presentationControllerDidDismiss(_ presentationController: UIPresentationController) { widget?.rootVC.setWidget(visible: true, animated: configuration.animations) @@ -118,6 +122,7 @@ extension SentryUserFeedbackIntegrationDriver: UIAdaptivePresentationControllerD // MARK: Private @available(iOS 13.0, *) +@available(iOSApplicationExtension, unavailable) private extension SentryUserFeedbackIntegrationDriver { func showForm(screenshot: UIImage?) { let form = SentryUserFeedbackFormController(config: configuration, delegate: self, screenshot: screenshot) @@ -156,7 +161,7 @@ private extension SentryUserFeedbackIntegrationDriver { @objc func userCapturedScreenshot() { stopObservingScreenshots() - showForm(screenshot: screenshotProvider.appScreenshots().first) + showForm(screenshot: screenshotSource.appScreenshots().first) } func stopObservingScreenshots() { diff --git a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackWidget.swift b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackWidget.swift index d23817cacb4..6be41192504 100644 --- a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackWidget.swift +++ b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackWidget.swift @@ -11,6 +11,7 @@ protocol SentryUserFeedbackWidgetDelegate: NSObjectProtocol { } @available(iOS 13.0, *) +@available(iOSApplicationExtension, unavailable) final class SentryUserFeedbackWidget { private lazy var button = { let button = SentryUserFeedbackWidgetButtonView(config: config, target: self, selector: #selector(showForm)) diff --git a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackWidgetButtonView.swift b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackWidgetButtonView.swift index 2e21c0f1961..807648418d9 100644 --- a/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackWidgetButtonView.swift +++ b/Sources/Swift/Integrations/UserFeedback/SentryUserFeedbackWidgetButtonView.swift @@ -70,8 +70,8 @@ final class SentryUserFeedbackWidgetButtonView: UIView { } constraints.append(contentsOf: [ label.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -config.padding), - label.topAnchor.constraint(equalTo: topAnchor), - label.bottomAnchor.constraint(equalTo: bottomAnchor) + label.topAnchor.constraint(equalTo: topAnchor, constant: config.padding), + label.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -config.padding) ]) } else if config.widgetConfig.showIcon { addSubview(megaphone) @@ -140,6 +140,8 @@ final class SentryUserFeedbackWidgetButtonView: UIView { }() lazy var lozengeLayer: CAShapeLayer = { + let isFontFamilyDamascus: Bool = config.theme.font.familyName == "Damascus" + var finalSize = label?.intrinsicContentSize ?? sizeWithoutLabel let hasText = config.widgetConfig.labelText != nil @@ -150,7 +152,7 @@ final class SentryUserFeedbackWidgetButtonView: UIView { let iconWidthAdditions = config.widgetConfig.showIcon ? scaledLeftPadding + scaledIconSize + scaledSpacing : config.padding finalSize.width += iconWidthAdditions + config.padding - let lozengeHeight = config.theme.font.familyName == "Damascus" ? config.theme.font.lineHeight : (2 * (config.theme.font.ascender - config.textEffectiveHeightCenter)) + let lozengeHeight = isFontFamilyDamascus ? config.theme.font.lineHeight : (2 * (config.theme.font.ascender - config.textEffectiveHeightCenter)) finalSize.height = lozengeHeight + 2 * config.padding * config.paddingScaleFactor } @@ -180,7 +182,7 @@ final class SentryUserFeedbackWidgetButtonView: UIView { let paddingDifference = (scaledLeftPadding - config.padding) / 2 let spacingDifference = scaledSpacing - config.spacing let increasedIconLeftPadAmountDueToScaling: CGFloat = config.widgetConfig.showIcon ? SentryLocale.isRightToLeftLanguage() ? paddingDifference : paddingDifference + iconSizeDifference + spacingDifference : 0 - let yTranslation = config.theme.font.familyName == "Damascus" ? -(config.padding * config.paddingScaleFactor + (config.theme.font.capHeight - config.theme.font.ascender) * config.paddingScaleFactor) : (-config.padding * config.paddingScaleFactor) + let yTranslation = isFontFamilyDamascus ? -(config.theme.font.capHeight - config.theme.font.ascender) * config.paddingScaleFactor : 0 lozengeLayer.transform = CATransform3DTranslate(lozengeLayer.transform, -increasedIconLeftPadAmountDueToScaling, yTranslation, 0) } else { lozengeLayer.transform = CATransform3DTranslate(lozengeLayer.transform, -iconSizeDifference, -iconSizeDifference, 0) diff --git a/Sources/Swift/Protocol/Codable/SentryBreadcrumbCodable.swift b/Sources/Swift/Protocol/Codable/SentryBreadcrumbCodable.swift index 489a2fbfe92..350ace4d72b 100644 --- a/Sources/Swift/Protocol/Codable/SentryBreadcrumbCodable.swift +++ b/Sources/Swift/Protocol/Codable/SentryBreadcrumbCodable.swift @@ -1,8 +1,7 @@ @_implementationOnly import _SentryPrivate import Foundation -// See `develop-docs/README.md` for an explanation of this pattern. -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 final class BreadcrumbDecodable: Breadcrumb { convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) @@ -23,7 +22,7 @@ extension BreadcrumbDecodable: Decodable { case origin } - #if !SENTRY_SWIFT_PACKAGE + #if !SDK_V9 required convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) } diff --git a/Sources/Swift/Protocol/Codable/SentryDebugMetaCodable.swift b/Sources/Swift/Protocol/Codable/SentryDebugMetaCodable.swift index b55f6f37f4f..574cb1105ca 100644 --- a/Sources/Swift/Protocol/Codable/SentryDebugMetaCodable.swift +++ b/Sources/Swift/Protocol/Codable/SentryDebugMetaCodable.swift @@ -1,8 +1,7 @@ @_implementationOnly import _SentryPrivate import Foundation -// See `develop-docs/README.md` for an explanation of this pattern. -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 final class DebugMetaDecodable: DebugMeta { convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) @@ -24,7 +23,7 @@ extension DebugMetaDecodable: Decodable { case codeFile = "code_file" } - #if !SENTRY_SWIFT_PACKAGE + #if !SDK_V9 required convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) } diff --git a/Sources/Swift/Protocol/Codable/SentryEventCodable.swift b/Sources/Swift/Protocol/Codable/SentryEventCodable.swift index ee677be0dd5..290f00d109d 100644 --- a/Sources/Swift/Protocol/Codable/SentryEventCodable.swift +++ b/Sources/Swift/Protocol/Codable/SentryEventCodable.swift @@ -5,9 +5,7 @@ import Foundation * Subclass of SentryEvent so we can add the Decodable implementation via a Swift extension. We need * this due to our mixed use of public Swift and ObjC classes. We could avoid this class by * converting SentryReplayEvent back to ObjC, but we rather accept this tradeoff as we want to - * convert all public classes to Swift in the future. This does not need to be public, but was previously - * defined in objc and was public. In the next major version of the SDK we should make it `internal` and `final` - * and remove the `@objc` annotation. + * convert all public classes to Swift in the future. * * @note: We can’t add the extension for Decodable directly on SentryEvent, because we get an error * in SentryReplayEvent: 'required' initializer 'init(from:)' must be provided by subclass of @@ -18,9 +16,26 @@ import Foundation * overridden. Therefore, we add the Decodable implementation not on the Event, but to a subclass of * the event. */ +#if !SDK_V9 @objc(SentryEventDecodable) open class SentryEventDecodable: Event, Decodable { - + required convenience public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.init() + try writePropertiesFrom(container: container) + } +} +#else +final class SentryEventDecodable: Event, Decodable { + required convenience public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.init() + try writePropertiesFrom(container: container) + } +} +#endif + +extension SentryEventDecodable { private enum CodingKeys: String, CodingKey { case eventId = "event_id" case message @@ -51,11 +66,7 @@ open class SentryEventDecodable: Event, Decodable { case request } - required convenience public init(from decoder: any Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - self.init() - + private func writePropertiesFrom(container: KeyedDecodingContainer) throws { let eventIdAsString = try container.decode(String.self, forKey: .eventId) SentryEventSwiftHelper.setEventIdString(eventIdAsString, event: self) self.message = try container.decodeIfPresent(SentryMessageDecodable.self, forKey: .message) diff --git a/Sources/Swift/Protocol/Codable/SentryExceptionCodable.swift b/Sources/Swift/Protocol/Codable/SentryExceptionCodable.swift index c1b97f58db5..508d5666b3b 100644 --- a/Sources/Swift/Protocol/Codable/SentryExceptionCodable.swift +++ b/Sources/Swift/Protocol/Codable/SentryExceptionCodable.swift @@ -1,8 +1,7 @@ @_implementationOnly import _SentryPrivate import Foundation -// See `develop-docs/README.md` for an explanation of this pattern. -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 final class ExceptionDecodable: Exception { convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) @@ -22,7 +21,7 @@ extension ExceptionDecodable: Decodable { case stacktrace } - #if !SENTRY_SWIFT_PACKAGE + #if !SDK_V9 required convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) } diff --git a/Sources/Swift/Protocol/Codable/SentryFrameCodable.swift b/Sources/Swift/Protocol/Codable/SentryFrameCodable.swift index 9c12bfeb397..77f5bbdd69b 100644 --- a/Sources/Swift/Protocol/Codable/SentryFrameCodable.swift +++ b/Sources/Swift/Protocol/Codable/SentryFrameCodable.swift @@ -1,8 +1,7 @@ @_implementationOnly import _SentryPrivate import Foundation -// See `develop-docs/README.md` for an explanation of this pattern. -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 final class FrameDecodable: Frame { convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) @@ -28,11 +27,15 @@ extension FrameDecodable: Decodable { // https://github.com/getsentry/sentry-cocoa/issues/4738 case lineNumber = "lineno" case columnNumber = "colno" + case contextLine = "context_line" + case preContext = "pre_context" + case postContext = "post_context" + case vars case inApp = "in_app" case stackStart = "stack_start" } - #if !SENTRY_SWIFT_PACKAGE + #if !SDK_V9 required convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) } @@ -52,6 +55,12 @@ extension FrameDecodable: Decodable { self.instructionAddress = try container.decodeIfPresent(String.self, forKey: .instructionAddress) self.lineNumber = (try container.decodeIfPresent(NSNumberDecodableWrapper.self, forKey: .lineNumber))?.value self.columnNumber = (try container.decodeIfPresent(NSNumberDecodableWrapper.self, forKey: .columnNumber))?.value + self.contextLine = try container.decodeIfPresent(String.self, forKey: .contextLine) + self.preContext = try container.decodeIfPresent([String].self, forKey: .preContext) + self.postContext = try container.decodeIfPresent([String].self, forKey: .postContext) + self.vars = decodeArbitraryData { + try container.decodeIfPresent([String: ArbitraryData].self, forKey: .vars) + } self.inApp = (try container.decodeIfPresent(NSNumberDecodableWrapper.self, forKey: .inApp))?.value self.stackStart = (try container.decodeIfPresent(NSNumberDecodableWrapper.self, forKey: .stackStart))?.value } diff --git a/Sources/Swift/Protocol/Codable/SentryGeoCodable.swift b/Sources/Swift/Protocol/Codable/SentryGeoCodable.swift index cb6a80ef33c..12bbb05d149 100644 --- a/Sources/Swift/Protocol/Codable/SentryGeoCodable.swift +++ b/Sources/Swift/Protocol/Codable/SentryGeoCodable.swift @@ -1,8 +1,7 @@ @_implementationOnly import _SentryPrivate import Foundation -// See `develop-docs/README.md` for an explanation of this pattern. -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 final class GeoDecodable: Geo { convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) @@ -19,7 +18,7 @@ extension GeoDecodable: Decodable { case region } - #if !SENTRY_SWIFT_PACKAGE + #if !SDK_V9 required convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) } diff --git a/Sources/Swift/Protocol/Codable/SentryMechanismCodable.swift b/Sources/Swift/Protocol/Codable/SentryMechanismCodable.swift index 60e7894eb2c..5f531bf30d9 100644 --- a/Sources/Swift/Protocol/Codable/SentryMechanismCodable.swift +++ b/Sources/Swift/Protocol/Codable/SentryMechanismCodable.swift @@ -1,8 +1,7 @@ @_implementationOnly import _SentryPrivate import Foundation -// See `develop-docs/README.md` for an explanation of this pattern. -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 final class MechanismDecodable: Mechanism { convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) @@ -23,7 +22,7 @@ extension MechanismDecodable: Decodable { case meta } - #if !SENTRY_SWIFT_PACKAGE + #if !SDK_V9 required convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) } diff --git a/Sources/Swift/Protocol/Codable/SentryMechanismMetaCodable.swift b/Sources/Swift/Protocol/Codable/SentryMechanismMetaCodable.swift index b52433b5541..252ef66682b 100644 --- a/Sources/Swift/Protocol/Codable/SentryMechanismMetaCodable.swift +++ b/Sources/Swift/Protocol/Codable/SentryMechanismMetaCodable.swift @@ -1,8 +1,7 @@ @_implementationOnly import _SentryPrivate import Foundation -// See `develop-docs/README.md` for an explanation of this pattern. -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 final class MechanismMetaDecodable: MechanismMeta { convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) @@ -19,7 +18,7 @@ extension MechanismMetaDecodable: Decodable { case error = "ns_error" } - #if !SENTRY_SWIFT_PACKAGE + #if !SDK_V9 required convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) } diff --git a/Sources/Swift/Protocol/Codable/SentryMessage.swift b/Sources/Swift/Protocol/Codable/SentryMessage.swift index 51ce75be009..3f8bbf2ce22 100644 --- a/Sources/Swift/Protocol/Codable/SentryMessage.swift +++ b/Sources/Swift/Protocol/Codable/SentryMessage.swift @@ -1,8 +1,7 @@ @_implementationOnly import _SentryPrivate import Foundation -// See `develop-docs/README.md` for an explanation of this pattern. -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 final class SentryMessageDecodable: SentryMessage { convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) @@ -19,7 +18,7 @@ extension SentryMessageDecodable: Decodable { case params } - #if !SENTRY_SWIFT_PACKAGE + #if !SDK_V9 required convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) } diff --git a/Sources/Swift/Protocol/Codable/SentryNSErrorCodable.swift b/Sources/Swift/Protocol/Codable/SentryNSErrorCodable.swift index ba80ff33bfd..e3e0f41dc07 100644 --- a/Sources/Swift/Protocol/Codable/SentryNSErrorCodable.swift +++ b/Sources/Swift/Protocol/Codable/SentryNSErrorCodable.swift @@ -1,8 +1,7 @@ @_implementationOnly import _SentryPrivate import Foundation -// See `develop-docs/README.md` for an explanation of this pattern. -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 final class SentryNSErrorDecodable: SentryNSError { convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) @@ -18,7 +17,7 @@ extension SentryNSErrorDecodable: Decodable { case code } - #if !SENTRY_SWIFT_PACKAGE + #if !SDK_V9 required convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) } diff --git a/Sources/Swift/Protocol/Codable/SentryRequestCodable.swift b/Sources/Swift/Protocol/Codable/SentryRequestCodable.swift index ed1207ba8f8..1d7415b292c 100644 --- a/Sources/Swift/Protocol/Codable/SentryRequestCodable.swift +++ b/Sources/Swift/Protocol/Codable/SentryRequestCodable.swift @@ -1,8 +1,7 @@ @_implementationOnly import _SentryPrivate import Foundation -// See `develop-docs/README.md` for an explanation of this pattern. -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 final class SentryRequestDecodable: SentryRequest { convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) @@ -23,7 +22,7 @@ extension SentryRequestDecodable: Decodable { case url } - #if !SENTRY_SWIFT_PACKAGE + #if !SDK_V9 required convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) } diff --git a/Sources/Swift/Protocol/Codable/SentryStacktraceCodable.swift b/Sources/Swift/Protocol/Codable/SentryStacktraceCodable.swift index e62073f63c6..39eecf520d2 100644 --- a/Sources/Swift/Protocol/Codable/SentryStacktraceCodable.swift +++ b/Sources/Swift/Protocol/Codable/SentryStacktraceCodable.swift @@ -1,8 +1,7 @@ @_implementationOnly import _SentryPrivate import Foundation -// See `develop-docs/README.md` for an explanation of this pattern. -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 final class SentryStacktraceDecodable: SentryStacktrace { convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) @@ -19,7 +18,7 @@ extension SentryStacktraceDecodable: Decodable { case snapshot } - #if !SENTRY_SWIFT_PACKAGE + #if !SDK_V9 required convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) } diff --git a/Sources/Swift/Protocol/Codable/SentryThreadCodable.swift b/Sources/Swift/Protocol/Codable/SentryThreadCodable.swift index fc0f458b0d7..e71628e0a85 100644 --- a/Sources/Swift/Protocol/Codable/SentryThreadCodable.swift +++ b/Sources/Swift/Protocol/Codable/SentryThreadCodable.swift @@ -1,8 +1,7 @@ @_implementationOnly import _SentryPrivate import Foundation -// See `develop-docs/README.md` for an explanation of this pattern. -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 final class SentryThreadDecodable: SentryThread { convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) @@ -22,7 +21,7 @@ extension SentryThreadDecodable: Decodable { case isMain = "main" } - #if !SENTRY_SWIFT_PACKAGE + #if !SDK_V9 required convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) } diff --git a/Sources/Swift/Protocol/Codable/SentryUserCodable.swift b/Sources/Swift/Protocol/Codable/SentryUserCodable.swift index bff75b1dd0b..24a025e58f4 100644 --- a/Sources/Swift/Protocol/Codable/SentryUserCodable.swift +++ b/Sources/Swift/Protocol/Codable/SentryUserCodable.swift @@ -1,8 +1,7 @@ @_implementationOnly import _SentryPrivate import Foundation -// See `develop-docs/README.md` for an explanation of this pattern. -#if SENTRY_SWIFT_PACKAGE +#if SDK_V9 final class UserDecodable: User { @available(*, deprecated) convenience public init(from decoder: any Decoder) throws { @@ -25,7 +24,7 @@ extension UserDecodable: Decodable { case data } - #if !SENTRY_SWIFT_PACKAGE + #if !SDK_V9 @available(*, deprecated) required convenience public init(from decoder: any Decoder) throws { try self.init(decodedFrom: decoder) @@ -48,7 +47,9 @@ extension UserDecodable: Decodable { self.email = try container.decodeIfPresent(String.self, forKey: .email) self.username = try container.decodeIfPresent(String.self, forKey: .username) self.ipAddress = try container.decodeIfPresent(String.self, forKey: .ipAddress) + #if !SDK_V9 self.segment = try container.decodeIfPresent(String.self, forKey: .segment) + #endif // !SDK_V9 self.name = try container.decodeIfPresent(String.self, forKey: .name) self.geo = try container.decodeIfPresent(GeoDecodable.self, forKey: .geo) diff --git a/Sources/Swift/Protocol/SentryLog.swift b/Sources/Swift/Protocol/SentryLog.swift index c0449b59041..33fc58e333f 100644 --- a/Sources/Swift/Protocol/SentryLog.swift +++ b/Sources/Swift/Protocol/SentryLog.swift @@ -1,48 +1,61 @@ -struct SentryLog: Codable { - let timestamp: Date - var traceId: SentryId - let level: SentryLog.Level - let body: String - let attributes: [String: SentryLog.Attribute] - let severityNumber: Int? +/// A structured log entry that captures log data with associated attribute metadata. +/// +/// Use the `options.beforeSendLog` callback to modify or filter log data. +@objc +@objcMembers +public final class SentryLog: NSObject { + /// The timestamp when the log event occurred + public var timestamp: Date + /// The trace ID to associate this log with distributed tracing + public var traceId: SentryId + /// The severity level of the log entry + public var level: Level + /// The main log message content + public var body: String + /// A dictionary of structured attributes added to the log entry + public var attributes: [String: Attribute] + /// Numeric representation of the severity level (Int) + public var severityNumber: NSNumber? - private enum CodingKeys: String, CodingKey { - case timestamp - case traceId = "trace_id" - case level - case body - case attributes - case severityNumber = "severity_number" - } - - /// The traceId is initially an empty default value and is populated during processing; - /// by the time processing completes, it is guaranteed to be a valid non-empty trace id. - init( + internal init( timestamp: Date, - traceId: SentryId? = nil, - level: SentryLog.Level, + traceId: SentryId, + level: Level, body: String, - attributes: [String: SentryLog.Attribute], - severityNumber: Int? = nil + attributes: [String: Attribute], + severityNumber: NSNumber? = nil ) { self.timestamp = timestamp - self.traceId = traceId ?? SentryId.empty + self.traceId = traceId self.level = level self.body = body self.attributes = attributes - self.severityNumber = severityNumber + self.severityNumber = severityNumber ?? NSNumber(value: level.toSeverityNumber()) + super.init() + } +} + +// MARK: - Internal Codable Support +@_spi(Private) extension SentryLog: Codable { + private enum CodingKeys: String, CodingKey { + case timestamp + case traceId = "trace_id" + case level + case body + case attributes + case severityNumber = "severity_number" } - init(from decoder: any Decoder) throws { + @_spi(Private) public convenience init(from decoder: any Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) let timestamp = try container.decode(Date.self, forKey: .timestamp) let traceIdString = try container.decode(String.self, forKey: .traceId) let traceId = SentryId(uuidString: traceIdString) - let level = try container.decode(SentryLog.Level.self, forKey: .level) + let level = try container.decode(Level.self, forKey: .level) let body = try container.decode(String.self, forKey: .body) - let attributes = try container.decode([String: SentryLog.Attribute].self, forKey: .attributes) - let severityNumber = try container.decodeIfPresent(Int.self, forKey: .severityNumber) + let attributes = try container.decode([String: Attribute].self, forKey: .attributes) + let severityNumber = try container.decodeIfPresent(Int.self, forKey: .severityNumber).map { NSNumber(value: $0) } self.init( timestamp: timestamp, @@ -54,7 +67,7 @@ struct SentryLog: Codable { ) } - func encode(to encoder: any Encoder) throws { + @_spi(Private) public func encode(to encoder: any Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(timestamp, forKey: .timestamp) @@ -62,6 +75,6 @@ struct SentryLog: Codable { try container.encode(level, forKey: .level) try container.encode(body, forKey: .body) try container.encode(attributes, forKey: .attributes) - try container.encodeIfPresent(severityNumber, forKey: .severityNumber) + try container.encodeIfPresent(severityNumber?.intValue, forKey: .severityNumber) } } diff --git a/Sources/Swift/Protocol/SentryLogAttribute.swift b/Sources/Swift/Protocol/SentryLogAttribute.swift index ed8ad42edef..daeed4ec93c 100644 --- a/Sources/Swift/Protocol/SentryLogAttribute.swift +++ b/Sources/Swift/Protocol/SentryLogAttribute.swift @@ -1,66 +1,131 @@ extension SentryLog { - enum Attribute: Codable { - case string(String) - case boolean(Bool) - case integer(Int) - case double(Double) + /// A typed attribute that can be attached to structured log entries. + /// + /// `Attribute` provides a type-safe way to store structured data alongside log messages. + /// Supports String, Bool, Int, and Double types. + @objc(SentryStructuredLogAttribute) + @objcMembers + public final class Attribute: NSObject { + /// The type identifier for this attribute ("string", "boolean", "integer", "double") + public let type: String + /// The actual value stored in this attribute + public let value: Any - var type: String { - switch self { - case .string: return "string" - case .boolean: return "boolean" - case .integer: return "integer" - case .double: return "double" - } + public init(string value: String) { + self.type = "string" + self.value = value + super.init() } - var value: Any { - switch self { - case .string(let value): return value - case .boolean(let value): return value - case .integer(let value): return value - case .double(let value): return value - } + public init(boolean value: Bool) { + self.type = "boolean" + self.value = value + super.init() + } + + public init(integer value: Int) { + self.type = "integer" + self.value = value + super.init() + } + + public init(double value: Double) { + self.type = "double" + self.value = value + super.init() } - private enum CodingKeys: String, CodingKey { - case value - case type + /// Creates a double attribute from a float value + public init(float value: Float) { + self.type = "double" + self.value = Double(value) + super.init() } - init(from decoder: any Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - let type = try container.decode(String.self, forKey: .type) - switch type { - case "string": - self = .string(try container.decode(String.self, forKey: .value)) - case "boolean": - self = .boolean(try container.decode(Bool.self, forKey: .value)) - case "integer": - self = .integer(try container.decode(Int.self, forKey: .value)) - case "double": - self = .double(try container.decode(Double.self, forKey: .value)) + internal init(value: Any) { + switch value { + case let stringValue as String: + self.type = "string" + self.value = stringValue + case let boolValue as Bool: + self.type = "boolean" + self.value = boolValue + case let intValue as Int: + self.type = "integer" + self.value = intValue + case let doubleValue as Double: + self.type = "double" + self.value = doubleValue + case let floatValue as Float: + self.type = "double" + self.value = Double(floatValue) default: - throw DecodingError.dataCorruptedError(forKey: .type, in: container, debugDescription: "Unknown type: \(type)") - } + // For any other type, convert to string representation + self.type = "string" + self.value = String(describing: value) + } + super.init() + } + } +} + +// MARK: - Internal Codable Support +@_spi(Private) extension SentryLog.Attribute: Codable { + private enum CodingKeys: String, CodingKey { + case value + case type + } + + @_spi(Private) public convenience init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + let type = try container.decode(String.self, forKey: .type) + + let value: Any + switch type { + case "string": + value = try container.decode(String.self, forKey: .value) + case "boolean": + value = try container.decode(Bool.self, forKey: .value) + case "integer": + value = try container.decode(Int.self, forKey: .value) + case "double": + value = try container.decode(Double.self, forKey: .value) + default: + throw DecodingError.dataCorruptedError(forKey: .type, in: container, debugDescription: "Unknown type: \(type)") } - func encode(to encoder: any Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) - - try container.encode(type, forKey: .type) - - switch self { - case .string(let value): - try container.encode(value, forKey: .value) - case .boolean(let value): - try container.encode(value, forKey: .value) - case .integer(let value): - try container.encode(value, forKey: .value) - case .double(let value): - try container.encode(value, forKey: .value) + self.init(value: value) + } + + @_spi(Private) public func encode(to encoder: any Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(type, forKey: .type) + + switch type { + case "string": + guard let stringValue = value as? String else { + throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: encoder.codingPath, debugDescription: "Expected String but got \(Swift.type(of: value))")) + } + try container.encode(stringValue, forKey: .value) + case "boolean": + guard let boolValue = value as? Bool else { + throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: encoder.codingPath, debugDescription: "Expected Bool but got \(Swift.type(of: value))")) + } + try container.encode(boolValue, forKey: .value) + case "integer": + guard let intValue = value as? Int else { + throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: encoder.codingPath, debugDescription: "Expected Int but got \(Swift.type(of: value))")) + } + try container.encode(intValue, forKey: .value) + case "double": + guard let doubleValue = value as? Double else { + throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: encoder.codingPath, debugDescription: "Expected Double but got \(Swift.type(of: value))")) } + try container.encode(doubleValue, forKey: .value) + default: + try container.encode(String(describing: value), forKey: .value) } } } diff --git a/Sources/Swift/Protocol/SentryLogLevel.swift b/Sources/Swift/Protocol/SentryLogLevel.swift index fff8115be69..5cf65c32c78 100644 --- a/Sources/Swift/Protocol/SentryLogLevel.swift +++ b/Sources/Swift/Protocol/SentryLogLevel.swift @@ -1,5 +1,10 @@ extension SentryLog { - enum Level: String, Codable { + /// Represents the severity level of a structured log entry. + /// + /// Log levels are ordered by severity from least (`trace`) to most severe (`fatal`). + /// Each level corresponds to a numeric severity value following the OpenTelemetry specification. + @objc(SentryStructuredLogLevel) + public enum Level: Int { case trace case debug case info @@ -7,8 +12,50 @@ extension SentryLog { case error case fatal - // Docs: https://develop.sentry.dev/sdk/telemetry/logs/#log-severity-number - func toSeverityNumber() -> Int { + /// Creates a log level from its string representation. + /// + /// - Parameter value: The string representation of the log level + /// - Throws: An error if the string doesn't match any known log level + public init(value: String) throws { + switch value { + case "trace": + self = .trace + case "debug": + self = .debug + case "info": + self = .info + case "warn": + self = .warn + case "error": + self = .error + case "fatal": + self = .fatal + default: + throw NSError(domain: "SentryLogLevel", code: 1, userInfo: [NSLocalizedDescriptionKey: "Unknown log level: \(value)"]) + } + } + + /// The string representation of the log level. + public var value: String { + switch self { + case .trace: + return "trace" + case .debug: + return "debug" + case .info: + return "info" + case .warn: + return "warn" + case .error: + return "error" + case .fatal: + return "fatal" + } + } + + /// Converts the log level to its numeric severity representation (1-21) following the OpenTelemetry specification. + /// Docs: https://develop.sentry.dev/sdk/telemetry/logs/#log-severity-number + public func toSeverityNumber() -> Int { switch self { case .trace: return 1 @@ -26,3 +73,35 @@ extension SentryLog { } } } + +// MARK: - Internal Codable Support +@_spi(Private) extension SentryLog.Level: Codable { + @_spi(Private) public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let stringValue = try container.decode(String.self) + self = try .init(value: stringValue) + } + + @_spi(Private) public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(value) + } +} + +@_spi(Private) extension SentryLog.Level { + /// Converts the structured log level to the legacy SentryLevel for compatibility with SentrySDKLog + @_spi(Private) public func toSentryLevel() -> SentryLevel { + switch self { + case .trace, .debug: + return .debug + case .info: + return .info + case .warn: + return .warning + case .error: + return .error + case .fatal: + return .fatal + } + } +} diff --git a/Sources/Swift/Protocol/SentryLogMessage.swift b/Sources/Swift/Protocol/SentryLogMessage.swift new file mode 100644 index 00000000000..8184be49379 --- /dev/null +++ b/Sources/Swift/Protocol/SentryLogMessage.swift @@ -0,0 +1,107 @@ +import Foundation + +/// A string type that supports structured logging with interpolation tracking. +/// +/// `SentryLogMessage` captures both the final message and the interpolated values +/// as structured attributes, enabling better log analysis and searchability. +/// +/// Example: +/// ```swift +/// let userId = 123 +/// let userName = "john_doe" +/// let logString: SentryLogMessage = "User \(userId) with name \(userName) authenticated" +/// // Results in: +/// // - message: "User 123 with name john_doe authenticated" +/// // - template: "User {0} with name {1} authenticated" +/// // - attributes: [.init(integer: 123), .init(string: "john_doe")] +/// ``` +public struct SentryLogMessage: ExpressibleByStringInterpolation { + /// The final formatted message with all interpolations resolved + let message: String + /// Structured attributes extracted from interpolated values + let attributes: [SentryLog.Attribute] + /// Template string with placeholders for interpolated values + let template: String + + public init(stringLiteral value: String) { + self.message = value + self.attributes = [] + self.template = value + } + + public init(stringInterpolation: StringInterpolation) { + self.message = stringInterpolation.message + self.attributes = stringInterpolation.attributes + self.template = stringInterpolation.template + } + + public struct StringInterpolation: StringInterpolationProtocol { + var message: String = "" + var attributes: [SentryLog.Attribute] = [] + var template: String = "" + private var interpolationCount = 0 + + public init(literalCapacity: Int, interpolationCount: Int) { + // Reserve 2x literal capacity to account for interpolated values which often + // equal or exceed the size of literals, avoiding expensive reallocations + message.reserveCapacity(literalCapacity * 2) + attributes.reserveCapacity(interpolationCount) + // Here we know the exact count, as the tempkate always adds `{i}`, + // with i beeing the index to the literalCapacity + template.reserveCapacity(literalCapacity + interpolationCount * 3) + } + + public mutating func appendLiteral(_ literal: String) { + message.append(literal) + template.append(literal) + } + + public mutating func appendInterpolation(_ value: @autoclosure @escaping () -> String) { + let actualValue = value() + appendInterpolationValue(stringValue: actualValue, attributeFactory: .init(string: actualValue)) + } + + public mutating func appendInterpolation(_ value: @autoclosure @escaping () -> Bool) { + let actualValue = value() + appendInterpolationValue(stringValue: String(actualValue), attributeFactory: .init(boolean: actualValue)) + } + + public mutating func appendInterpolation(_ value: @autoclosure @escaping () -> Int) { + let actualValue = value() + appendInterpolationValue(stringValue: String(actualValue), attributeFactory: .init(integer: actualValue)) + } + + public mutating func appendInterpolation(_ value: @autoclosure @escaping () -> Double) { + let actualValue = value() + appendInterpolationValue(stringValue: String(actualValue), attributeFactory: .init(double: actualValue)) + } + + public mutating func appendInterpolation(_ value: @autoclosure @escaping () -> Float) { + let actualValue = value() + appendInterpolationValue(stringValue: String(actualValue), attributeFactory: .init(double: Double(actualValue))) + } + + public mutating func appendInterpolation(_ value: @autoclosure @escaping () -> T) { + let actualValue = value() + appendInterpolationValue(stringValue: actualValue.description, attributeFactory: .init(string: actualValue.description)) + } + + // Helper + + private mutating func appendInterpolationValue( + stringValue: String, + attributeFactory: @autoclosure () -> SentryLog.Attribute + ) { + // Add the value to the message + message.append(stringValue) + + // Create placeholder in template + template.append("{\(interpolationCount)}") + + // Add attribute for structured logging + attributes.append(attributeFactory()) + + interpolationCount += 1 + } + } +} diff --git a/Sources/Swift/Protocol/SentrySDKSettings.swift b/Sources/Swift/Protocol/SentrySDKSettings.swift new file mode 100644 index 00000000000..99ffe82f335 --- /dev/null +++ b/Sources/Swift/Protocol/SentrySDKSettings.swift @@ -0,0 +1,30 @@ +/** + * Describes the settings for the Sentry SDK + * @see https://develop.sentry.dev/sdk/event-payloads/sdk/ + */ +@_spi(Private) @objc public final class SentrySDKSettings: NSObject { + + @objc public override init() { + autoInferIP = false + } + + @objc public init(options: Options?) { + autoInferIP = options?.sendDefaultPii ?? false + } + + @objc public init(dict: NSDictionary) { + if let inferIp = dict["infer_ip"] as? String { + autoInferIP = inferIp == "auto" + } else { + autoInferIP = false + } + } + + @objc public var autoInferIP: Bool + + @objc public func serialize() -> NSDictionary { + [ + "infer_ip": autoInferIP ? "auto" : "never" + ] + } +} diff --git a/Sources/Swift/SentryAppState.swift b/Sources/Swift/SentryAppState.swift new file mode 100644 index 00000000000..1779f6f5080 --- /dev/null +++ b/Sources/Swift/SentryAppState.swift @@ -0,0 +1,132 @@ +@_implementationOnly import _SentryPrivate +import Foundation + +@objcMembers @_spi(Private) public class SentryAppState: NSObject, SentrySerializable { + + public private(set) var releaseName: String? + public private(set) var osVersion: String + public private(set) var vendorId: String + public private(set) var isDebugging: Bool + + /// The boot time of the system rounded down to seconds. As the precision of the serialization is + /// only milliseconds and a precision of seconds is enough we round down to seconds. With this we + /// avoid getting different dates before and after serialization. + /// + /// - warning: We must not send this information off device because Apple forbids that. + /// We are allowed send the amount of time that has elapsed between events that occurred within the + /// app though. For more information see + /// https://developer.apple.com/documentation/bundleresources/privacy_manifest_files/describing_use_of_required_reason_api#4278394. + public private(set) var systemBootTimestamp: Date + public var isActive: Bool + public var wasTerminated: Bool + public var isANROngoing: Bool + public var isSDKRunning: Bool + + public init(releaseName: String?, osVersion: String, vendorId: String, isDebugging: Bool, systemBootTimestamp: Date) { + self.releaseName = releaseName + self.osVersion = osVersion + self.vendorId = vendorId + self.isDebugging = isDebugging + + // Round down to seconds as the precision of the serialization of the date is only + // milliseconds. With this we avoid getting different dates before and after serialization. + let interval = round(systemBootTimestamp.timeIntervalSince1970) + self.systemBootTimestamp = Date(timeIntervalSince1970: interval) + + self.isActive = false + self.wasTerminated = false + self.isANROngoing = false + self.isSDKRunning = true + + super.init() + } + + // swiftlint:disable cyclomatic_complexity + @objc(initWithJSONObject:) + public init?(jsonObject: [String: Any]) { + // Validate and extract releaseName + if let releaseName = jsonObject["release_name"] { + if !(releaseName is String) { + return nil + } + self.releaseName = releaseName as? String + } else { + self.releaseName = nil + } + + // Validate and extract osVersion + guard let osVersion = jsonObject["os_version"] as? String else { + return nil + } + self.osVersion = osVersion + + // Validate and extract vendorId + guard let vendorId = jsonObject["vendor_id"] as? String else { + return nil + } + self.vendorId = vendorId + + // Validate and extract isDebugging + guard let isDebugging = jsonObject["is_debugging"] as? Bool else { + return nil + } + self.isDebugging = isDebugging + + // Validate and extract systemBootTimestamp + guard let systemBoot = jsonObject["system_boot_timestamp"] as? String else { + return nil + } + guard let systemBootTimestamp = sentry_fromIso8601String(systemBoot) else { + return nil + } + self.systemBootTimestamp = systemBootTimestamp + + // Validate and extract isActive + guard let isActive = jsonObject["is_active"] as? Bool else { + return nil + } + self.isActive = isActive + + // Validate and extract wasTerminated + guard let wasTerminated = jsonObject["was_terminated"] as? Bool else { + return nil + } + self.wasTerminated = wasTerminated + + // Validate and extract isANROngoing + guard let isANROngoing = jsonObject["is_anr_ongoing"] as? Bool else { + return nil + } + self.isANROngoing = isANROngoing + + // Validate and extract isSDKRunning + if let isSDKRunning = jsonObject["is_sdk_running"] as? Bool { + self.isSDKRunning = isSDKRunning + } else { + // This property was added later so instead of returning nil, + // we're setting it to the default value. + self.isSDKRunning = true + } + + super.init() + } + // swiftlint:enable cyclomatic_complexity + + @objc public func serialize() -> [String: Any] { + var data: [String: Any] = [:] + + if let releaseName = self.releaseName { + data["release_name"] = releaseName + } + data["os_version"] = self.osVersion + data["vendor_id"] = self.vendorId + data["is_debugging"] = NSNumber(value: self.isDebugging) + data["system_boot_timestamp"] = sentry_toIso8601String(self.systemBootTimestamp) + data["is_active"] = NSNumber(value: self.isActive) + data["was_terminated"] = NSNumber(value: self.wasTerminated) + data["is_anr_ongoing"] = NSNumber(value: self.isANROngoing) + data["is_sdk_running"] = NSNumber(value: self.isSDKRunning) + + return data + } +} diff --git a/Sources/Swift/SentryCrash/SentryCrashWrapper.swift b/Sources/Swift/SentryCrash/SentryCrashWrapper.swift new file mode 100644 index 00000000000..badc8367cfb --- /dev/null +++ b/Sources/Swift/SentryCrash/SentryCrashWrapper.swift @@ -0,0 +1,277 @@ +@_implementationOnly import _SentryPrivate +import Darwin +import Foundation + +#if (os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT +import UIKit +#endif // (os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT + +/** + * A wrapper around SentryCrash for testability. + */ +#if DEBUG || SENTRY_TEST || SENTRY_TEST_CI +@objc @_spi(Private) +public class SentryCrashWrapper: NSObject { + let processInfoWrapper: SentryProcessInfoSource + + // Using lazy so we wait until SentryDependencyContainer is initialized + @objc + public private(set) lazy var systemInfo = SentryDependencyContainerSwiftHelper.crashReporter().systemInfo as? [String: Any] ?? [:] + + @objc + public init(processInfoWrapper: SentryProcessInfoSource) { + self.processInfoWrapper = processInfoWrapper + super.init() + sentrycrashcm_system_getAPI()?.pointee.setEnabled(true) + } + +#if SENTRY_TEST || SENTRY_TEST_CI + // This var and initializer are used to inject system info during tests + public init(processInfoWrapper: SentryProcessInfoSource, systemInfo: [String: Any]) { + self.processInfoWrapper = processInfoWrapper + // Call super.init before overriding `self.systemInfo` (cannot access self before initialization) + super.init() + + self.systemInfo = systemInfo + + } +#endif // SENTRY_TEST && SENTRY_TEST_CI +} +#else +@objc @_spi(Private) +public final class SentryCrashWrapper: NSObject { + let processInfoWrapper: SentryProcessInfoSource + + // Using lazy so we wait until SentryDependencyContainer is initialized + @objc + public private(set) lazy var systemInfo = SentryDependencyContainerSwiftHelper.crashReporter().systemInfo as? [String: Any] ?? [:] + + @objc + public init(processInfoWrapper: SentryProcessInfoSource) { + self.processInfoWrapper = processInfoWrapper + super.init() + // Always enable crash monitoring on release builds + sentrycrashcm_system_getAPI()?.pointee.setEnabled(true) + } +} +#endif + +@_spi(Private) extension SentryCrashWrapper { + @objc + public func startBinaryImageCache() { + sentrycrashbic_startCache() + } + + @objc + public func stopBinaryImageCache() { + sentrycrashbic_stopCache() + } + + @objc + public var crashedLastLaunch: Bool { + return SentryDependencyContainerSwiftHelper.crashReporter().crashedLastLaunch + } + + @objc + public var durationFromCrashStateInitToLastCrash: TimeInterval { + return sentrycrashstate_currentState()?.pointee.durationFromCrashStateInitToLastCrash ?? 0 + } + + @objc + public var activeDurationSinceLastCrash: TimeInterval { + return SentryDependencyContainerSwiftHelper.crashReporter().activeDurationSinceLastCrash + } + + @objc + public var isBeingTraced: Bool { + return sentrycrashdebug_isBeingTraced() + } + + @objc + public var isSimulatorBuild: Bool { + return sentrycrash_isSimulatorBuild() + } + + @objc + public var isApplicationInForeground: Bool { + return sentrycrashstate_currentState()?.pointee.applicationIsInForeground ?? false + } + + @objc + public var freeMemorySize: UInt64 { + return sentrycrashcm_system_freememory_size() + } + + @objc + public var appMemorySize: UInt64 { + var info = task_vm_info_data_t() + var size = mach_msg_type_number_t(MemoryLayout.stride / MemoryLayout.stride) + let kerr = withUnsafeMutablePointer(to: &info) { infoPtr in + task_info(mach_task_self_, task_flavor_t(TASK_VM_INFO), + UnsafeMutableRawPointer(infoPtr).assumingMemoryBound(to: integer_t.self), &size) + } + + if kerr == KERN_SUCCESS { + return info.internal + info.compressed + } + + return 0 + } + + @objc + public func enrichScope(_ scope: Scope) { + let systemInfo = self.systemInfo + + enrichScopeWithOSData(scope, systemInfo: systemInfo) + + // SystemInfo should only be nil when SentryCrash has not been installed + if systemInfo.isEmpty { + return + } + + enrichScopeWithDeviceData(scope, systemInfo: systemInfo) + enrichScopeWithAppData(scope, systemInfo: systemInfo) + enrichScopeWithRuntimeData(scope) + } + + // MARK: - Private Methods + + private func enrichScopeWithOSData(_ scope: Scope, systemInfo: [String: Any]) { + var osData: [String: Any] = [:] + + osData["name"] = getOSName() + osData["version"] = getOSVersion() + + // SystemInfo should only be nil when SentryCrash has not been installed + if !systemInfo.isEmpty { + osData["build"] = systemInfo["osVersion"] + osData["kernel_version"] = systemInfo["kernelVersion"] + osData["rooted"] = systemInfo["isJailbroken"] + } + + scope.setContext(value: osData, key: "os") + } + + private func enrichScopeWithDeviceData(_ scope: Scope, systemInfo: [String: Any]) { + var deviceData: [String: Any] = [:] + + deviceData["simulator"] = isSimulator() + + if let systemName = systemInfo["systemName"] as? String { + deviceData["family"] = getDeviceFamily(from: systemName) + } + + deviceData["arch"] = systemInfo["cpuArchitecture"] + deviceData["model"] = systemInfo["machine"] + deviceData["model_id"] = systemInfo["model"] + deviceData["free_memory"] = systemInfo["freeMemorySize"] + deviceData["usable_memory"] = systemInfo["usableMemorySize"] + deviceData["memory_size"] = systemInfo["memorySize"] + + deviceData["locale"] = Locale.autoupdatingCurrent.identifier + + // Set screen dimensions if available + setScreenDimensions(&deviceData) + + scope.setContext(value: deviceData, key: "device") + } + + private func enrichScopeWithAppData(_ scope: Scope, systemInfo: [String: Any]) { + var appData: [String: Any] = [:] + let infoDict = Bundle.main.infoDictionary ?? [:] + + appData["app_identifier"] = infoDict["CFBundleIdentifier"] + appData["app_name"] = infoDict["CFBundleName"] + appData["app_build"] = infoDict["CFBundleVersion"] + appData["app_version"] = infoDict["CFBundleShortVersionString"] + + appData["app_start_time"] = systemInfo["appStartTime"] + appData["device_app_hash"] = systemInfo["deviceAppHash"] + appData["app_id"] = systemInfo["appID"] + appData["build_type"] = systemInfo["buildType"] + + scope.setContext(value: appData, key: "app") + } + + private func enrichScopeWithRuntimeData(_ scope: Scope) { + var runtimeContext: [String: Any] = [:] + + // We set this info on the runtime context because the app context has no existing fields + // suitable for representing Catalyst or iOS-on-Mac execution modes. We also wanted to avoid + // adding two new Apple-specific fields to the app context. Coming up with a generic, + // reusable property on the app context proved difficult, so instead we reuse the "name" + // field of the runtime context as a pragmatic and semantically acceptable solution. + // isiOSAppOnMac and isMacCatalystApp are mutually exclusive, so we only set one of them. + if #available(iOS 14.0, macOS 11.0, watchOS 7.0, tvOS 14.0, *) { + if self.processInfoWrapper.isiOSAppOnMac { + runtimeContext["name"] = "iOS App on Mac" + runtimeContext["raw_description"] = "ios-app-on-mac" + } + } + + if #available(iOS 13.0, macOS 10.15, watchOS 6.0, tvOS 13.0, *) { + if self.processInfoWrapper.isMacCatalystApp { + runtimeContext["name"] = "Mac Catalyst App" + runtimeContext["raw_description"] = "raw_description" + } + } + + if !runtimeContext.isEmpty { + scope.setContext(value: runtimeContext, key: "runtime") + } + } + + private func getOSName() -> String? { +#if os(macOS) || targetEnvironment(macCatalyst) + return "macOS" +#elseif os(iOS) + return "iOS" +#elseif os(tvOS) + return "tvOS" +#elseif os(watchOS) + return "watchOS" +#elseif (swift(>=5.9) && os(visionOS)) + return "visionOS" +#endif + } + + private func getOSVersion() -> String { + // For MacCatalyst the UIDevice returns the current version of MacCatalyst and not the + // macOSVersion. Therefore we have to use NSProcessInfo. +#if (os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT && !targetEnvironment(macCatalyst) + return Dependencies.uiDeviceWrapper.getSystemVersion() +#else + let version = ProcessInfo.processInfo.operatingSystemVersion + return "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)" +#endif // (os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT && !targetEnvironment(macCatalyst) + } + + private func isSimulator() -> Bool { +#if targetEnvironment(simulator) + return true +#else + return false +#endif // targetEnvironment(simulator) + } + + private func getDeviceFamily(from systemName: String) -> String? { + let family = systemName.components(separatedBy: .whitespacesAndNewlines).first +#if targetEnvironment(macCatalyst) + // This would be iOS. Set it to macOS instead. + return "macOS" +#else + return family +#endif // targetEnvironment(macCatalyst) + } + + private func setScreenDimensions(_ deviceData: inout [String: Any]) { + // The UIWindowScene is unavailable on visionOS +#if (os(iOS) || os(tvOS)) && !SENTRY_NO_UIKIT + if let appWindows = SentryDependencyContainerSwiftHelper.windows(), + let appScreen = appWindows.first?.screen { + deviceData["screen_height_pixels"] = appScreen.bounds.size.height + deviceData["screen_width_pixels"] = appScreen.bounds.size.width + } +#endif // (os(iOS) || os(tvOS)) && !SENTRY_NO_UIKIT + } +} diff --git a/Sources/Swift/SentryExperimentalOptions.swift b/Sources/Swift/SentryExperimentalOptions.swift index c9ec1ecdae2..926f5782b6f 100644 --- a/Sources/Swift/SentryExperimentalOptions.swift +++ b/Sources/Swift/SentryExperimentalOptions.swift @@ -30,6 +30,11 @@ public class SentryExperimentalOptions: NSObject { * - Experiment: This is an experimental feature and is therefore disabled by default. We'll enable it by default in a future major release. */ public var enableUnhandledCPPExceptionsV2 = false + + /** + * Logs are considered beta. + */ + public var enableLogs = false @_spi(Private) public func validateOptions(_ options: [String: Any]?) { } diff --git a/Sources/Swift/SentrySession.swift b/Sources/Swift/SentrySession.swift new file mode 100644 index 00000000000..a3fccc2c3b3 --- /dev/null +++ b/Sources/Swift/SentrySession.swift @@ -0,0 +1,139 @@ +@_implementationOnly import _SentryPrivate +import Foundation + +@objc @_spi(Private) public enum SentrySessionStatus: UInt { + init(internalStatus: InternalSentrySessionStatus) { + switch internalStatus { + case .sentrySessionStatusOk: + self = .ok + case .sentrySessionStatusExited: + self = .exited + case .sentrySessionStatusCrashed: + self = .crashed + case .sentrySessionStatusAbnormal: + fallthrough + @unknown default: + self = .abnormal + } + } + + case ok = 0 + case exited = 1 + case crashed = 2 + case abnormal = 3 +} + +/// The SDK uses SentrySession to inform Sentry about release and project associated project health. +@objc @_spi(Private) public class SentrySession: NSObject, NSCopying { + + // MARK: Private + + let session: SentrySessionInternal + + @available(*, unavailable, message: "Use init(releaseName:distinctId:) instead.") + private override init() { + fatalError("Not Implemented") + } + + private init(session: SentrySessionInternal) { + self.session = session + } + + // MARK: Internal + + /// Designated initializer. + @objc public init(releaseName: String, distinctId: String) { + session = SentrySessionInternal(releaseName: releaseName, distinctId: distinctId) + } + + /** + * Initializes @c SentrySession from a JSON object. + * @param jsonObject The @c jsonObject containing the session. + * @return The @c SentrySession or @c nil if @c jsonObject contains an error. + */ + @objc(initWithJSONObject:) public init?(jsonObject: [String: Any]) { + guard let session = SentrySessionInternal(jsonObject: jsonObject) else { + return nil + } + self.session = session + } + + @objc(endSessionExitedWithTimestamp:) + public func endExited(withTimestamp timestamp: Date) { + session.endSessionExited(withTimestamp: timestamp) + } + + @objc(endSessionCrashedWithTimestamp:) + public func endCrashed(withTimestamp timestamp: Date) { + session.endSessionCrashed(withTimestamp: timestamp) + } + + @objc(endSessionAbnormalWithTimestamp:) + public func endAbnormal(withTimestamp timestamp: Date) { + session.endSessionAbnormal(withTimestamp: timestamp) + } + + @objc public func incrementErrors() { + session.incrementErrors() + } + + @objc public var sessionId: UUID { + session.sessionId + } + @objc public var started: Date { + session.started + } + @objc public var status: SentrySessionStatus { + SentrySessionStatus(internalStatus: session.status) + } + @objc public var errors: UInt { + get { session.errors } + set { session.errors = newValue } + } + @objc public var sequence: UInt { + session.sequence + } + @objc public var distinctId: String { + session.distinctId + } + + @objc public var flagInit: NSNumber? { + session.flagInit + } + + @objc public var timestamp: Date? { + session.timestamp + } + @objc public var duration: NSNumber? { + session.duration + } + + @objc public var releaseName: String? { + session.releaseName + } + @objc public var environment: String? { + get { session.environment } + set { session.environment = newValue } + } + @objc public var user: User? { + get { session.user } + set { session.user = newValue } + } + @objc public var abnormalMechanism: String? { + get { session.abnormalMechanism } + set { session.abnormalMechanism = newValue } + } + + @objc public func serialize() -> [String: Any] { + session.serialize() + } + + @objc public func setFlagInit() { + session.setFlagInit() + } + + public func copy(with zone: NSZone? = nil) -> Any { + let copy = session.safeCopy(with: zone) + return SentrySession(session: copy) + } +} diff --git a/Sources/Swift/Tools/LoadValidator.swift b/Sources/Swift/Tools/LoadValidator.swift new file mode 100644 index 00000000000..da6f863f024 --- /dev/null +++ b/Sources/Swift/Tools/LoadValidator.swift @@ -0,0 +1,84 @@ +@_implementationOnly import _SentryPrivate +import Darwin +import Foundation +import MachO + +@objc +@_spi(Private) public final class LoadValidator: NSObject { + // Any class should be fine, ObjC classes are better + static let targetClassName = NSStringFromClass(SentryDependencyContainerSwiftHelper.self) + + // This function is used to check for duplicated SDKs in the binary. + // Since `SentryBinaryImageInfo` is not public and only available through the Hybrid SDK, we use the expanded parameters. + @objc + @_spi(Private) public class func checkForDuplicatedSDK(imageName: String, + imageAddress: NSNumber, + imageSize: NSNumber, + objcRuntimeWrapper: SentryObjCRuntimeWrapper, + dispatchQueueWrapper: SentryDispatchQueueWrapper) { + internalCheckForDuplicatedSDK(imageName, imageAddress.uint64Value, imageSize.uint64Value, + objcRuntimeWrapper: objcRuntimeWrapper, + dispatchQueueWrapper: dispatchQueueWrapper) + } + + class func internalCheckForDuplicatedSDK(_ imageName: String, _ imageAddress: UInt64, _ imageSize: UInt64, objcRuntimeWrapper: SentryObjCRuntimeWrapper, dispatchQueueWrapper: SentryDispatchQueueWrapper, resultHandler: ((Bool) -> Void)? = nil) { + let systemLibraryPath = "/usr/lib/" + let ignoredPathDevelopers = "/Library/Developer/CoreSimulator/Volumes/" + let ignoredPathSystem = "/System/Library/" + guard !imageName.hasPrefix(ignoredPathDevelopers) && !imageName.hasPrefix(ignoredPathSystem) && !imageName.hasPrefix(systemLibraryPath) else { + resultHandler?(false) + return + } + dispatchQueueWrapper.dispatchAsync { + var duplicateFound = false + defer { + resultHandler?(duplicateFound) + } + + let loadValidatorAddress = self.getCurrentFrameworkTextPointer() + let loadValidatorAddressValue = UInt(bitPattern: loadValidatorAddress) + // The SDK looks for classes on each image. We might find: + // - Unrelated Classes, nothing to do + // - Classes with the exact name (`SentryDependencyContainerSwiftHelper`), if it is present in the same text section as LoadValidator is, it is our implementation, it isn't it is a duplicate class + // - Classes containing `SentryDependencyContainerSwiftHelper`, it also is a duplicate + let isCurrentImageContainingLoadValidator = (loadValidatorAddressValue >= imageAddress) && (loadValidatorAddressValue < (imageAddress + imageSize)) + + var classCount: UInt32 = 0 + imageName.withCString { cImageName in + if let classNames = objcRuntimeWrapper.copyClassNamesForImage(cImageName, &classCount) { + defer { + free(classNames) + } + for j in 0.. UnsafeRawPointer { + let cFunction: @convention(c) () -> Void = { } + let c = unsafeBitCast(cFunction, to: UnsafeRawPointer.self) + return c + } +} diff --git a/Sources/Swift/Tools/SentryClientReport.swift b/Sources/Swift/Tools/SentryClientReport.swift new file mode 100644 index 00000000000..8c98cf83482 --- /dev/null +++ b/Sources/Swift/Tools/SentryClientReport.swift @@ -0,0 +1,25 @@ +@objc +@_spi(Private) public final class SentryClientReport: NSObject, SentrySerializable { + + @objc(initWithDiscardedEvents:dateProvider:) + public init(discardedEvents: [SentryDiscardedEvent], dateProvider: SentryCurrentDateProvider) { + timestamp = dateProvider.date() + self.discardedEvents = discardedEvents + } + + @objc + public func serialize() -> [String: Any] { + let events = discardedEvents.map { $0.serialize() } + return [ + "timestamp": NSNumber(value: self.timestamp.timeIntervalSince1970), + "discarded_events": events + ] + } + + /** + * The timestamp of when the client report was created. + */ + private let timestamp: Date + let discardedEvents: [SentryDiscardedEvent] + +} diff --git a/Sources/Swift/Tools/SentryDiscardedEvent.swift b/Sources/Swift/Tools/SentryDiscardedEvent.swift new file mode 100644 index 00000000000..09504c731b2 --- /dev/null +++ b/Sources/Swift/Tools/SentryDiscardedEvent.swift @@ -0,0 +1,25 @@ +import Foundation + +@objcMembers +@_spi(Private) +public final class SentryDiscardedEvent: NSObject, SentrySerializable { + + let reason: String + let category: String + public let quantity: UInt + + public init(reason: String, category: String, quantity: UInt) { + self.reason = reason + self.category = category + self.quantity = quantity + super.init() + } + + public func serialize() -> [String: Any] { + return [ + "reason": reason, + "category": category, + "quantity": quantity + ] + } +} diff --git a/Sources/Swift/Tools/SentryEnvelope.swift b/Sources/Swift/Tools/SentryEnvelope.swift new file mode 100644 index 00000000000..dd796c7876e --- /dev/null +++ b/Sources/Swift/Tools/SentryEnvelope.swift @@ -0,0 +1,53 @@ +@_implementationOnly import _SentryPrivate + +@_spi(Private) @objc public final class SentryEnvelope: NSObject { + + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + @objc(initWithId:singleItem:) public convenience init(id: SentryId?, singleItem item: SentryEnvelopeItem) { + self.init(header: SentryEnvelopeHeader(id: id), singleItem: item) + } + + @objc(initWithHeader:singleItem:) public convenience init(header: SentryEnvelopeHeader, singleItem item: SentryEnvelopeItem) { + self.init(header: header, items: [item]) + } + + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + @objc(initWithId:items:) public convenience init(id: SentryId?, items: [SentryEnvelopeItem]) { + self.init(header: SentryEnvelopeHeader(id: id), items: items) + } + + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + convenience init(session: SentrySession) { + let item = SentryEnvelopeItem(session: session) + self.init(header: SentryEnvelopeHeader(id: nil), singleItem: item) + } + + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + convenience init(sessions: [SentrySession]) { + let items = sessions.map { SentryEnvelopeItem(session: $0) } + self.init(header: SentryEnvelopeHeader(id: nil), items: items) + } + + @objc(initWithHeader:items:) public init(header: SentryEnvelopeHeader, items: [SentryEnvelopeItem]) { + self.header = header + self.items = items + } + + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + convenience init(event: Event) { + let item = SentryEnvelopeItem(event: event) + let headerId = SentryEnvelopeHeaderHelper.headerId(from: event) + self.init(header: SentryEnvelopeHeader(id: headerId.sentryId), singleItem: item) + } + + #if !SDK_V9 + @available(*, deprecated, message: "Building the envelopes for the new SentryFeedback type is done directly in -[SentryClient captureFeedback:withScope:].") + convenience init(userFeedback: UserFeedback) { + let item = SentryEnvelopeItem(userFeedback: userFeedback) + self.init(header: SentryEnvelopeHeader(id: userFeedback.eventId), singleItem: item) + } + #endif // !SDK_V9 + + @objc public let header: SentryEnvelopeHeader + @objc public let items: [SentryEnvelopeItem] +} diff --git a/Sources/Swift/Tools/SentryEnvelopeHeader.swift b/Sources/Swift/Tools/SentryEnvelopeHeader.swift new file mode 100644 index 00000000000..e28b6afb1b1 --- /dev/null +++ b/Sources/Swift/Tools/SentryEnvelopeHeader.swift @@ -0,0 +1,66 @@ +@_implementationOnly import _SentryPrivate + +@_spi(Private) @objc public final class SentryEnvelopeHeader: NSObject { + /** + * Initializes an @c SentryEnvelopeHeader object with the specified eventId. + * @note Sets the @c sdkInfo from @c SentryMeta. + * @param eventId The identifier of the event. Can be nil if no event in the envelope or attachment + * related to event. + */ + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + @objc public convenience init(id eventId: SentryId?) { + self.init(id: eventId, traceContext: nil) + } + + /** + * Initializes a @c SentryEnvelopeHeader object with the specified @c eventId and @c traceContext. + * @param eventId The identifier of the event. Can be @c nil if no event in the envelope or + * attachment related to event. + * @param traceContext Current trace state. + */ + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + @objc public convenience init(id eventId: SentryId?, traceContext: TraceContext?) { + self.init(id: eventId, sdkInfo: SentrySdkInfo.global(), traceContext: traceContext) + } + + /** + * Initializes a @c SentryEnvelopeHeader object with the specified @c eventId, @c skdInfo and + * @c traceContext. It is recommended to use @c initWithId:traceContext: because it sets the + * @c sdkInfo for you. + * @param eventId The identifier of the event. Can be @c nil if no event in the envelope or + * attachment related to event. + * @param sdkInfo Describes the Sentry SDK. Can be @c nil for backwards compatibility. New + * instances should always provide a version. + * @param traceContext Current trace state. + */ + @objc public + init(id eventId: SentryId?, sdkInfo: SentrySdkInfo?, traceContext: TraceContext?) { + self.eventId = eventId + self.sdkInfo = sdkInfo + self.traceContext = traceContext + } + + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + @objc public static func empty() -> Self { + Self(id: nil, traceContext: nil) + } + + /** + * The event identifier, if available. + * An event id exist if the envelope contains an event of items within it are related. i.e + * Attachments + */ + @objc public var eventId: SentryId? + @objc public var sdkInfo: SentrySdkInfo? + @objc public var traceContext: TraceContext? + + /** + * The timestamp when the event was sent from the SDK as string in RFC 3339 format. Used + * for clock drift correction of the event timestamp. The time zone must be UTC. + * + * The timestamp should be generated as close as possible to the transmision of the event, + * so that the delay between sending the envelope and receiving it on the server-side is + * minimized. + */ + @objc public var sentAt: Date? +} diff --git a/Sources/Swift/Tools/SentryEnvelopeItem.swift b/Sources/Swift/Tools/SentryEnvelopeItem.swift new file mode 100644 index 00000000000..d0b6381e97a --- /dev/null +++ b/Sources/Swift/Tools/SentryEnvelopeItem.swift @@ -0,0 +1,211 @@ +@_implementationOnly import _SentryPrivate + +@_spi(Private) @objc public final class SentryEnvelopeItem: NSObject { + + // MARK: - Properties + + /** + * The envelope item header. + */ + @objc public let header: SentryEnvelopeItemHeader + + /** + * The envelope payload. + */ + @objc public let data: Data? + + // MARK: - Initializers + + /** + * Designated initializer for creating an envelope item with a header and data. + */ + @objc public init(header: SentryEnvelopeItemHeader, data: Data?) { + self.header = header + self.data = data + } + + /** + * Initializes an envelope item with an event. + */ + @objc public convenience init(event: Event) { + var json = SentrySerialization.data(withJSONObject: event.serialize()) + if json == nil { + // We don't know what caused the serialization to fail. + let errorEvent = Event() + SentryLevelBridge.setBreadcrumbLevelOn(errorEvent, level: SentryLevel.warning.rawValue) + + // Add some context to the event. We can only set simple properties otherwise we + // risk that the conversion fails again. + let message = "JSON conversion error for event with message: '\(event.message?.description ?? "")'" + errorEvent.message = SentryMessage(formatted: message) + errorEvent.releaseName = event.releaseName + errorEvent.environment = event.environment + errorEvent.platform = event.platform + errorEvent.timestamp = event.timestamp + + // We accept the risk that this simple serialization fails. Therefore we ignore the + // error on purpose. + json = SentrySerialization.data(withJSONObject: errorEvent.serialize()) + } + + // event.type can be nil and the server infers error if there's a stack trace, otherwise + // default. In any case in the envelope type it should be event. Except for transactions + let envelopeType = event.type == SentryEnvelopeItemTypes.transaction ? SentryEnvelopeItemTypes.transaction : (event.type == SentryEnvelopeItemTypes.feedback ? SentryEnvelopeItemTypes.feedback : SentryEnvelopeItemTypes.event) + + let itemHeader = SentryEnvelopeItemHeader(type: envelopeType, length: UInt(json?.count ?? 0)) + self.init(header: itemHeader, data: json) + } + + /** + * Initializes an envelope item with a session. + */ + @objc public convenience init(session: SentrySession) { + let json = try? JSONSerialization.data(withJSONObject: session.serialize(), options: []) + let itemHeader = SentryEnvelopeItemHeader(type: SentryEnvelopeItemTypes.session, length: UInt(json?.count ?? 0)) + self.init(header: itemHeader, data: json) + } + + #if !SDK_V9 + /** + * @deprecated Building the envelopes for the new @c SentryFeedback type is done directly in @c + * -[SentryClient @c captureFeedback:withScope:] + */ + @available(*, deprecated, message: "Building the envelopes for the new SentryFeedback type is done directly in -[SentryClient captureFeedback:withScope:] so there will be no analog to this initializer for SentryFeedback at this time.") + @objc public convenience init(userFeedback: UserFeedback) { + do { + let json = try JSONSerialization.data(withJSONObject: userFeedback.serialize(), options: []) + let itemHeader = SentryEnvelopeItemHeader(type: SentryEnvelopeItemTypes.userFeedback, length: UInt(json.count)) + self.init(header: itemHeader, data: json) + } catch { + SentrySDKLog.error("Couldn't serialize user feedback.") + let itemHeader = SentryEnvelopeItemHeader(type: SentryEnvelopeItemTypes.userFeedback, length: 0) + self.init(header: itemHeader, data: Data()) + } + } + #endif // !SDK_V9 + + /** + * Initializes an envelope item with an attachment. + * @param attachment The attachment to create the envelope item from. + * @param maxAttachmentSize The maximum allowed size for the attachment. + * @return The envelope item or nil if the attachment is too large or cannot be processed. + */ + @objc public convenience init?(attachment: Attachment, maxAttachmentSize: UInt) { + var data: Data? + + if let attachmentData = attachment.data { + if attachmentData.count > maxAttachmentSize { + SentrySDKLog.debug("Dropping attachment with filename '\(attachment.filename)', because the size of the passed data with \(attachmentData.count) bytes is bigger than the maximum allowed attachment size of \(maxAttachmentSize) bytes.") + return nil + } + + #if DEBUG || SENTRY_TEST || SENTRY_TEST_CI + if ProcessInfo.processInfo.arguments.contains("--io.sentry.other.base64-attachment-data") { + data = attachmentData.base64EncodedString().data(using: .utf8) + } else { + data = attachmentData + } + #else + data = attachmentData + #endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI + } else if let attachmentPath = attachment.path { + do { + let fileManager = FileManager.default + let attributes = try fileManager.attributesOfItem(atPath: attachmentPath) + + if let fileSize = attributes[.size] as? UInt64, fileSize > maxAttachmentSize { + SentrySDKLog.debug("Dropping attachment, because the size of the it located at '\(attachmentPath)' with \(fileSize) bytes is bigger than the maximum allowed attachment size of \(maxAttachmentSize) bytes.") + return nil + } + + #if DEBUG || SENTRY_TEST || SENTRY_TEST_CI + if ProcessInfo.processInfo.arguments.contains("--io.sentry.other.base64-attachment-data") { + let fileData = fileManager.contents(atPath: attachmentPath) + data = fileData?.base64EncodedString().data(using: .utf8) + } else { + data = fileManager.contents(atPath: attachmentPath) + } + #else + data = fileManager.contents(atPath: attachmentPath) + #endif // DEBUG || SENTRY_TEST || SENTRY_TEST_CI + } catch { + SentrySDKLog.error("Couldn't check file size of attachment with path: \(attachmentPath). Error: \(error.localizedDescription)") + return nil + } + } + + guard let finalData = data else { + SentrySDKLog.error("Couldn't init Attachment.") + return nil + } + + let itemHeader = SentryEnvelopeAttachmentHeader( + type: SentryEnvelopeItemTypes.attachment, + length: UInt(finalData.count), + filename: attachment.filename, + contentType: attachment.contentType, + attachmentType: attachment.attachmentType + ) + + self.init(header: itemHeader, data: finalData) + } + + // MARK: - Private Initializers + + /** + * Initializes an envelope item with a client report. + */ + @objc public convenience init(clientReport: SentryClientReport) { + do { + let json = try JSONSerialization.data(withJSONObject: clientReport.serialize(), options: []) + let itemHeader = SentryEnvelopeItemHeader(type: SentryEnvelopeItemTypes.clientReport, length: UInt(json.count)) + self.init(header: itemHeader, data: json) + } catch { + SentrySDKLog.error("Couldn't serialize client report.") + let itemHeader = SentryEnvelopeItemHeader(type: SentryEnvelopeItemTypes.clientReport, length: 0) + self.init(header: itemHeader, data: Data()) + } + } + + /** + * Initializes an envelope item with replay event and recording data. + */ + @objc public convenience init?(replayEvent: SentryReplayEvent, replayRecording: SentryReplayRecording, video: URL) { + guard let replayEventData = SentrySerialization.data(withJSONObject: replayEvent.serialize()) else { + SentrySDKLog.error("Could not serialize replay event data for envelope item. Event will be nil.") + return nil + } + + guard let recording = replayRecording.data() else { + SentrySDKLog.error("Could not serialize replay recording data for envelope item. Recording will be nil.") + return nil + } + + let envelopeContentUrl = video.deletingPathExtension().appendingPathExtension("dat") + + let pack: [String: SentryStreamable] = [ + "replay_event": replayEventData as NSData, + "replay_recording": recording as NSData, + "replay_video": video as NSURL + ] + let success = SentryMsgPackSerializer.serializeDictionary(toMessagePack: + pack, + intoFile: envelopeContentUrl + ) + + guard success else { + SentrySDKLog.error("Could not create MessagePack for session replay envelope item.") + return nil + } + + let envelopeItemContent = try? Data(contentsOf: envelopeContentUrl) + do { + try FileManager.default.removeItem(at: envelopeContentUrl) + } catch { + SentrySDKLog.error("Could not delete temporary replay content from disk: \(error)") + } + + let itemHeader = SentryEnvelopeItemHeader(type: SentryEnvelopeItemTypes.replayVideo, length: UInt(envelopeItemContent?.count ?? 0)) + self.init(header: itemHeader, data: envelopeItemContent) + } +} diff --git a/Sources/Swift/Tools/SentryLogBatcher.swift b/Sources/Swift/Tools/SentryLogBatcher.swift new file mode 100644 index 00000000000..09055b30a92 --- /dev/null +++ b/Sources/Swift/Tools/SentryLogBatcher.swift @@ -0,0 +1,144 @@ +@_implementationOnly import _SentryPrivate +import Foundation + +@objc +@objcMembers +@_spi(Private) public class SentryLogBatcher: NSObject { + + private let client: SentryClient + private let flushTimeout: TimeInterval + private let maxBufferSizeBytes: Int + private let dispatchQueue: SentryDispatchQueueWrapper + + internal let options: Options + + // All mutable state is accessed from the same serial dispatch queue. + + // Every logs data is added sepratley. They are flushed together in an envelope. + private var encodedLogs: [Data] = [] + private var encodedLogsSize: Int = 0 + private var timerWorkItem: DispatchWorkItem? + + /// Initializes a new SentryLogBatcher. + /// - Parameters: + /// - client: The SentryClient to use for sending logs + /// - flushTimeout: The timeout interval after which buffered logs will be flushed + /// - maxBufferSizeBytes: The maximum buffer size in bytes before triggering an immediate flush + /// - dispatchQueue: A **serial** dispatch queue wrapper for thread-safe access to mutable state + /// + /// - Important: The `dispatchQueue` parameter MUST be a serial queue to ensure thread safety. + /// Passing a concurrent queue will result in undefined behavior and potential data races. + @_spi(Private) public init( + client: SentryClient, + flushTimeout: TimeInterval, + maxBufferSizeBytes: Int, + dispatchQueue: SentryDispatchQueueWrapper + ) { + self.client = client + self.options = client.options + self.flushTimeout = flushTimeout + self.maxBufferSizeBytes = maxBufferSizeBytes + self.dispatchQueue = dispatchQueue + super.init() + } + + /// Convenience initializer with default flush timeout and buffer size. + /// - Parameters: + /// - client: The SentryClient to use for sending logs + /// - dispatchQueue: A **serial** dispatch queue wrapper for thread-safe access to mutable state + /// + /// - Important: The `dispatchQueue` parameter MUST be a serial queue to ensure thread safety. + /// Passing a concurrent queue will result in undefined behavior and potential data races. + @_spi(Private) public convenience init(client: SentryClient, dispatchQueue: SentryDispatchQueueWrapper) { + self.init( + client: client, + flushTimeout: 5, + maxBufferSizeBytes: 1_024 * 1_024, // 1MB + dispatchQueue: dispatchQueue + ) + } + + @_spi(Private) func add(_ log: SentryLog) { + dispatchQueue.dispatchAsync { [weak self] in + self?.encodeAndBuffer(log: log) + } + } + + // Captures batched logs sync and returns the duration. + @discardableResult + @_spi(Private) func captureLogs() -> TimeInterval { + let startTimeNs = SentryDefaultCurrentDateProvider.getAbsoluteTime() + dispatchQueue.dispatchSync { [weak self] in + self?.performCaptureLogs() + } + let endTimeNs = SentryDefaultCurrentDateProvider.getAbsoluteTime() + return TimeInterval(endTimeNs - startTimeNs) / 1_000_000_000.0 // Convert nanoseconds to seconds + } + + // Helper + + // Only ever call this from the serial dispatch queue. + private func encodeAndBuffer(log: SentryLog) { + do { + let encodedLog = try encodeToJSONData(data: log) + + let encodedLogsWereEmpty = encodedLogs.isEmpty + + encodedLogs.append(encodedLog) + encodedLogsSize += encodedLog.count + + if encodedLogsSize >= maxBufferSizeBytes { + performCaptureLogs() + } else if encodedLogsWereEmpty && timerWorkItem == nil { + startTimer() + } + } catch { + SentrySDKLog.error("Failed to encode log: \(error)") + } + } + + // Only ever call this from the serial dispatch queue. + private func startTimer() { + let timerWorkItem = DispatchWorkItem { [weak self] in + SentrySDKLog.debug("SentryLogBatcher: Timer fired, calling performFlush().") + self?.performCaptureLogs() + } + self.timerWorkItem = timerWorkItem + dispatchQueue.dispatch(after: flushTimeout, workItem: timerWorkItem) + } + + // Only ever call this from the serial dispatch queue. + private func performCaptureLogs() { + // Reset logs on function exit + defer { + encodedLogs.removeAll() + encodedLogsSize = 0 + } + + // Reset timer state + timerWorkItem?.cancel() + timerWorkItem = nil + + guard encodedLogs.count > 0 else { + SentrySDKLog.debug("SentryLogBatcher: No logs to flush.") + return + } + + // Create the payload. + + var payloadData = Data() + payloadData.append(Data("{\"items\":[".utf8)) + let separator = Data(",".utf8) + for (index, encodedLog) in encodedLogs.enumerated() { + if index > 0 { + payloadData.append(separator) + } + payloadData.append(encodedLog) + } + payloadData.append(Data("]}".utf8)) + + // Send the payload. + + client.captureLogsData(payloadData, with: NSNumber(value: encodedLogs.count)) + } +} diff --git a/Sources/Swift/Tools/SentryLogger.swift b/Sources/Swift/Tools/SentryLogger.swift new file mode 100644 index 00000000000..dd5bbff5d60 --- /dev/null +++ b/Sources/Swift/Tools/SentryLogger.swift @@ -0,0 +1,309 @@ +@_implementationOnly import _SentryPrivate + +import Foundation + +/// **EXPERIMENTAL** - A structured logging API for Sentry. +/// +/// `SentryLogger` provides a structured logging interface that captures log entries +/// and sends them to Sentry. Supports multiple log levels (trace, debug, info, warn, +/// error, fatal) and allows attaching arbitrary attributes for enhanced context. +/// +/// ## Supported Attribute Types +/// - `String`, `Bool`, `Int`, `Double` +/// - `Float` (converted to `Double`) +/// - Other types (converted to string) +/// +/// - Note: Sentry Logs is currently in Beta. See the [Sentry Logs Documentation](https://docs.sentry.io/product/explore/logs/). +/// - Warning: This API is experimental and subject to change without notice. +/// +/// ## Usage +/// ```swift +/// let logger = SentrySDK.logger +/// logger.info("User logged in", attributes: ["userId": "12345"]) +/// logger.error("Payment failed", attributes: ["errorCode": 500]) +/// +/// // Structured string interpolation with automatic type detection +/// logger.info("User \(userId) processed \(count) items with \(percentage)% success") +/// logger.debug("Processing \(itemCount) items, active: \(isActive)") +/// logger.warn("Retry attempt \(currentAttempt) of \(maxAttempts) failed") +/// ``` +@objc +public final class SentryLogger: NSObject { + private let hub: SentryHub + private let dateProvider: SentryCurrentDateProvider + // Nil in the case where the Hub's client is nil or logs are disabled through options. + private let batcher: SentryLogBatcher? + + @_spi(Private) public init(hub: SentryHub, dateProvider: SentryCurrentDateProvider, batcher: SentryLogBatcher?) { + self.hub = hub + self.dateProvider = dateProvider + self.batcher = batcher + super.init() + } + + // MARK: - Trace Level + + /// Logs a trace-level message with structured string interpolation and optional attributes. + public func trace(_ message: SentryLogMessage, attributes: [String: Any] = [:]) { + captureLog(level: .trace, logMessage: message, attributes: attributes) + } + + /// Logs a trace-level message. + @objc(trace:) + public func trace(_ body: String) { + let message = SentryLogMessage(stringLiteral: body) + captureLog(level: .trace, logMessage: message, attributes: [:]) + } + + /// Logs a trace-level message with additional attributes. + @objc(trace:attributes:) + public func trace(_ body: String, attributes: [String: Any]) { + let message = SentryLogMessage(stringLiteral: body) + captureLog(level: .trace, logMessage: message, attributes: attributes) + } + + // MARK: - Debug Level + + /// Logs a debug-level message with structured string interpolation and optional attributes. + public func debug(_ message: SentryLogMessage, attributes: [String: Any] = [:]) { + captureLog(level: .debug, logMessage: message, attributes: attributes) + } + + /// Logs a debug-level message. + @objc(debug:) + public func debug(_ body: String) { + let message = SentryLogMessage(stringLiteral: body) + captureLog(level: .debug, logMessage: message, attributes: [:]) + } + + /// Logs a debug-level message with additional attributes. + @objc(debug:attributes:) + public func debug(_ body: String, attributes: [String: Any]) { + let message = SentryLogMessage(stringLiteral: body) + captureLog(level: .debug, logMessage: message, attributes: attributes) + } + + // MARK: - Info Level + + /// Logs an info-level message with structured string interpolation and optional attributes. + public func info(_ message: SentryLogMessage, attributes: [String: Any] = [:]) { + captureLog(level: .info, logMessage: message, attributes: attributes) + } + + /// Logs an info-level message. + @objc(info:) + public func info(_ body: String) { + let message = SentryLogMessage(stringLiteral: body) + captureLog(level: .info, logMessage: message, attributes: [:]) + } + + /// Logs an info-level message with additional attributes. + @objc(info:attributes:) + public func info(_ body: String, attributes: [String: Any]) { + let message = SentryLogMessage(stringLiteral: body) + captureLog(level: .info, logMessage: message, attributes: attributes) + } + + // MARK: - Warn Level + + /// Logs a warning-level message with structured string interpolation and optional attributes. + public func warn(_ message: SentryLogMessage, attributes: [String: Any] = [:]) { + captureLog(level: .warn, logMessage: message, attributes: attributes) + } + + /// Logs a warning-level message. + @objc(warn:) + public func warn(_ body: String) { + let message = SentryLogMessage(stringLiteral: body) + captureLog(level: .warn, logMessage: message, attributes: [:]) + } + + /// Logs a warning-level message with additional attributes. + @objc(warn:attributes:) + public func warn(_ body: String, attributes: [String: Any]) { + let message = SentryLogMessage(stringLiteral: body) + captureLog(level: .warn, logMessage: message, attributes: attributes) + } + + // MARK: - Error Level + + /// Logs an error-level message with structured string interpolation and optional attributes. + public func error(_ message: SentryLogMessage, attributes: [String: Any] = [:]) { + captureLog(level: .error, logMessage: message, attributes: attributes) + } + + /// Logs an error-level message. + @objc(error:) + public func error(_ body: String) { + let message = SentryLogMessage(stringLiteral: body) + captureLog(level: .error, logMessage: message, attributes: [:]) + } + + /// Logs an error-level message with additional attributes. + @objc(error:attributes:) + public func error(_ body: String, attributes: [String: Any]) { + let message = SentryLogMessage(stringLiteral: body) + captureLog(level: .error, logMessage: message, attributes: attributes) + } + + // MARK: - Fatal Level + + /// Logs a fatal-level message with structured string interpolation and optional attributes. + public func fatal(_ message: SentryLogMessage, attributes: [String: Any] = [:]) { + captureLog(level: .fatal, logMessage: message, attributes: attributes) + } + + /// Logs a fatal-level message. + @objc(fatal:) + public func fatal(_ body: String) { + let message = SentryLogMessage(stringLiteral: body) + captureLog(level: .fatal, logMessage: message, attributes: [:]) + } + + /// Logs a fatal-level message with additional attributes. + @objc(fatal:attributes:) + public func fatal(_ body: String, attributes: [String: Any]) { + let message = SentryLogMessage(stringLiteral: body) + captureLog(level: .fatal, logMessage: message, attributes: attributes) + } + + // MARK: - Internal + + // Captures batched logs sync and return the duration. + func captureLogs() -> TimeInterval { + return batcher?.captureLogs() ?? 0.0 + } + + // MARK: - Private + + private func captureLog(level: SentryLog.Level, logMessage: SentryLogMessage, attributes: [String: Any]) { + guard let batcher else { + return + } + + // Convert provided attributes to SentryLog.Attribute format + var logAttributes = attributes.mapValues { SentryLog.Attribute(value: $0) } + + // Add template string if there are interpolations + if !logMessage.attributes.isEmpty { + logAttributes["sentry.message.template"] = .init(string: logMessage.template) + } + + // Add attributes from the SentryLogMessage + for (index, attribute) in logMessage.attributes.enumerated() { + logAttributes["sentry.message.parameter.\(index)"] = attribute + } + + addDefaultAttributes(to: &logAttributes) + addOSAttributes(to: &logAttributes) + addDeviceAttributes(to: &logAttributes) + addUserAttributes(to: &logAttributes) + + let propagationContextTraceIdString = hub.scope.propagationContextTraceIdString + let propagationContextTraceId = SentryId(uuidString: propagationContextTraceIdString) + + let log = SentryLog( + timestamp: dateProvider.date(), + traceId: propagationContextTraceId, + level: level, + body: logMessage.message, + attributes: logAttributes + ) + + var processedLog: SentryLog? = log + if let beforeSendLog = batcher.options.beforeSendLog { + processedLog = beforeSendLog(log) + } + + if let processedLog { + SentrySDKLog.log( + message: "[SentryLogger] \(processedLog.body)", + andLevel: processedLog.level.toSentryLevel() + ) + batcher.add(processedLog) + } + } + + private func addDefaultAttributes(to attributes: inout [String: SentryLog.Attribute]) { + guard let batcher else { + return + } + attributes["sentry.sdk.name"] = .init(string: SentryMeta.sdkName) + attributes["sentry.sdk.version"] = .init(string: SentryMeta.versionString) + attributes["sentry.environment"] = .init(string: batcher.options.environment) + if let releaseName = batcher.options.releaseName { + attributes["sentry.release"] = .init(string: releaseName) + } + if let span = hub.scope.span { + attributes["sentry.trace.parent_span_id"] = .init(string: span.spanId.sentrySpanIdString) + } + } + + private func addOSAttributes(to attributes: inout [String: SentryLog.Attribute]) { + guard let osContext = hub.scope.getContextForKey(SENTRY_CONTEXT_OS_KEY) else { + return + } + if let osName = osContext["name"] as? String { + attributes["os.name"] = .init(string: osName) + } + if let osVersion = osContext["version"] as? String { + attributes["os.version"] = .init(string: osVersion) + } + } + + private func addDeviceAttributes(to attributes: inout [String: SentryLog.Attribute]) { + guard let deviceContext = hub.scope.getContextForKey(SENTRY_CONTEXT_DEVICE_KEY) else { + return + } + // For Apple devices, brand is always "Apple" + attributes["device.brand"] = .init(string: "Apple") + + if let deviceModel = deviceContext["model"] as? String { + attributes["device.model"] = .init(string: deviceModel) + } + if let deviceFamily = deviceContext["family"] as? String { + attributes["device.family"] = .init(string: deviceFamily) + } + } + + private func addUserAttributes(to attributes: inout [String: SentryLog.Attribute]) { + guard let user = hub.scope.userObject else { + return + } + if let userId = user.userId { + attributes["user.id"] = .init(string: userId) + } + if let userName = user.name { + attributes["user.name"] = .init(string: userName) + } + if let userEmail = user.email { + attributes["user.email"] = .init(string: userEmail) + } + } +} + +#if SWIFT_PACKAGE +/** + * Use this callback to drop or modify a log before the SDK sends it to Sentry. Return `nil` to + * drop the log. + */ +public typealias SentryBeforeSendLogCallback = (SentryLog) -> SentryLog? + +// Makes the `beforeSendLog` property visible as the Swift type `SentryBeforeSendLogCallback`. +// This works around `SentryLog` being only forward declared in the objc header, resulting in +// compile time issues with SPM builds. +@objc +public extension Options { + /** + * Use this callback to drop or modify a log before the SDK sends it to Sentry. Return `nil` to + * drop the log. + */ + @objc + var beforeSendLog: SentryBeforeSendLogCallback? { + // Note: This property provides SentryLog type safety for SPM builds where the native Objective-C + // property cannot be used due to Swift-to-Objective-C bridging limitations. + get { return value(forKey: "beforeSendLogDynamic") as? SentryBeforeSendLogCallback } + set { setValue(newValue, forKey: "beforeSendLogDynamic") } + } +} +#endif // SWIFT_PACKAGE diff --git a/Sources/Swift/Transaction/SentryMeasurementValue.swift b/Sources/Swift/Transaction/SentryMeasurementValue.swift new file mode 100644 index 00000000000..7f0999648be --- /dev/null +++ b/Sources/Swift/Transaction/SentryMeasurementValue.swift @@ -0,0 +1,25 @@ +@_spi(Private) @objc public final class SentryMeasurementValue: NSObject { + + @objc public let value: NSNumber + @objc public let unit: MeasurementUnit? + + @objc public init(value: NSNumber) { + self.value = value + self.unit = nil + } + + @objc public init(value: NSNumber, unit: MeasurementUnit) { + self.value = value + self.unit = unit + } + + @objc public func serialize() -> [String: Any] { + var result: [String: Any] = [ + "value": self.value + ] + if let unit { + result["unit"] = unit.unit + } + return result + } +} diff --git a/TestSamples/SwiftUITestSample/Shared/Config/Deployment.xcconfig b/TestSamples/Common.xcconfig similarity index 77% rename from TestSamples/SwiftUITestSample/Shared/Config/Deployment.xcconfig rename to TestSamples/Common.xcconfig index 452c33ebb66..05fb2c44fe3 100644 --- a/TestSamples/SwiftUITestSample/Shared/Config/Deployment.xcconfig +++ b/TestSamples/Common.xcconfig @@ -1,7 +1,6 @@ +GENERATE_INFOPLIST_FILE = YES + // Only for testing IPHONEOS_DEPLOYMENT_TARGET = 16.0 - - - COPY_PHASE_STRIP = NO TARGETED_DEVICE_FAMILY = 1,2 diff --git a/TestSamples/SwiftUICrashTest/SwiftUICrashTest.xcconfig b/TestSamples/SwiftUICrashTest/SwiftUICrashTest.xcconfig index f8ad7182821..f27d3548a62 100644 --- a/TestSamples/SwiftUICrashTest/SwiftUICrashTest.xcconfig +++ b/TestSamples/SwiftUICrashTest/SwiftUICrashTest.xcconfig @@ -1,29 +1,7 @@ -#include "../SwiftUITestSample/Shared/Config/Architectures.xcconfig" -#include "../SwiftUITestSample/Shared/Config/BuildOptions.xcconfig" -#include "../SwiftUITestSample/Shared/Config/Deployment.xcconfig" -#include "../SwiftUITestSample/Shared/Config/Linking.xcconfig" -#include "../SwiftUITestSample/Shared/Config/Localization.xcconfig" -#include "../SwiftUITestSample/Shared/Config/Packaging.xcconfig" -#include "../SwiftUITestSample/Shared/Config/SearchPaths.xcconfig" -#include "../SwiftUITestSample/Shared/Config/Signing.xcconfig" -#include "../SwiftUITestSample/Shared/Config/Versioning.xcconfig" -#include "../SwiftUITestSample/Shared/Config/CodeGeneration.xcconfig" -#include "../SwiftUITestSample/Shared/Config/ClangLanguage.xcconfig" -#include "../SwiftUITestSample/Shared/Config/ClangCppLanguage.xcconfig" -#include "../SwiftUITestSample/Shared/Config/ClangModules.xcconfig" -#include "../SwiftUITestSample/Shared/Config/ClangObjCLanguage.xcconfig" -#include "../SwiftUITestSample/Shared/Config/ClangPreprocessing.xcconfig" -#include "../SwiftUITestSample/Shared/Config/ClangWarnings.xcconfig" -#include "../SwiftUITestSample/Shared/Config/ClangWarningsCpp.xcconfig" -#include "../SwiftUITestSample/Shared/Config/ClangWarningsObjC.xcconfig" -#include "../SwiftUITestSample/Shared/Config/AssetCatalog.xcconfig" -#include "../SwiftUITestSample/Shared/Config/ClangAnalyzer.xcconfig" -#include "../SwiftUITestSample/Shared/Config/Swift.xcconfig" -#include "../SwiftUITestSample/Shared/Config/Metal.xcconfig" +#include "../../Samples/Shared/Config/_Common.xcconfig" +#include "../Common.xcconfig" PRODUCT_NAME = SwiftUICrashTest PRODUCT_BUNDLE_IDENTIFIER = io.sentry.tests.SwiftUICrashTest -GENERATE_INFOPLIST_FILE = YES SUPPORTED_PLATFORMS = iphoneos iphonesimulator -MARKETING_VERSION = 1 diff --git a/TestSamples/SwiftUICrashTest/SwiftUICrashTest/ContentView.swift b/TestSamples/SwiftUICrashTest/SwiftUICrashTest/ContentView.swift index 7c39b655063..f3b7f568f5a 100644 --- a/TestSamples/SwiftUICrashTest/SwiftUICrashTest/ContentView.swift +++ b/TestSamples/SwiftUICrashTest/SwiftUICrashTest/ContentView.swift @@ -7,7 +7,8 @@ struct ContentView: View { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) - Text("Hello, world!") + let userDefaultsKey = "crash-on-launch" + Text("Crash flag value: \(UserDefaults.standard.bool(forKey: userDefaultsKey))") } .padding() } diff --git a/TestSamples/SwiftUICrashTest/SwiftUICrashTest/SwiftUICrashTestApp.swift b/TestSamples/SwiftUICrashTest/SwiftUICrashTest/SwiftUICrashTestApp.swift index aa219a34116..55ac06a81e7 100644 --- a/TestSamples/SwiftUICrashTest/SwiftUICrashTest/SwiftUICrashTestApp.swift +++ b/TestSamples/SwiftUICrashTest/SwiftUICrashTest/SwiftUICrashTestApp.swift @@ -5,21 +5,31 @@ import SwiftUI struct SwiftUICrashTestApp: App { init() { + // Using `NSLog` so it shows up in the logs and `SwiftUICrashTestApp` to easily find it in the logs. + NSLog("SwiftUICrashTestApp - app launched") SentrySDK.start { options in options.dsn = "https://6cc9bae94def43cab8444a99e0031c28@o447951.ingest.sentry.io/5428557" } - - let userDefaultsKey = "crash-on-launch" - if UserDefaults.standard.bool(forKey: userDefaultsKey) { - - UserDefaults.standard.removeObject(forKey: userDefaultsKey) - SentrySDK.crash() - } + NSLog("SwiftUICrashTestApp - SDK Started") } var body: some Scene { WindowGroup { ContentView() + .onAppear { + // Moved the crash from init to onAppear to ensure the app is fully loaded before crashing. + // This prevents test flakiness on CI that occurred when the crash happened during the app launch. + let userDefaultsKey = "crash-on-launch" + if UserDefaults.standard.bool(forKey: userDefaultsKey) { + NSLog("SwiftUICrashTestApp - will crash") + UserDefaults.standard.removeObject(forKey: userDefaultsKey) + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + SentrySDK.crash() + } + } else { + NSLog("SwiftUICrashTestApp - will not crash") + } + } } } } diff --git a/TestSamples/SwiftUICrashTest/test-crash-and-relaunch.sh b/TestSamples/SwiftUICrashTest/test-crash-and-relaunch.sh index 7902b4bf215..40008b2448e 100755 --- a/TestSamples/SwiftUICrashTest/test-crash-and-relaunch.sh +++ b/TestSamples/SwiftUICrashTest/test-crash-and-relaunch.sh @@ -52,15 +52,56 @@ log() { take_simulator_screenshot() { local name="$1" - # Create screenshots directory if it doesn't exist mkdir -p "$SCREENSHOTS_DIR" # Generate timestamp-based filename with custom name timestamp=$(date '+%H%M%S') screenshot_name="$SCREENSHOTS_DIR/${timestamp}_${name}.png" + full_screen_screenshot_name="$SCREENSHOTS_DIR/${timestamp}_${name}_full_screen.png" + + log "Taking screenshot with name: $screenshot_name" + + # Use native timeout implementation with background process and kill + # Note: macOS doesn't include 'timeout' by default. While it's available via + # 'brew install coreutils' as 'gtimeout', we avoid external dependencies + # for this single use case. This native approach works with built-in commands. + + # Start screenshot command in background + xcrun simctl io booted screenshot "$screenshot_name" & + screenshot_pid=$! + + # take a screenshot of the whole screen + screencapture -x "$full_screen_screenshot_name" - # Take screenshot - xcrun simctl io booted screenshot "$screenshot_name" 2>/dev/null || true + # Wait for 10 seconds or until process completes + start_time=$(date +%s) + while true; do + if ! kill -0 $screenshot_pid 2>/dev/null; then + # Process has finished + wait $screenshot_pid + exit_code=$? + if [ $exit_code -eq 0 ]; then + log "Screenshot taken: $screenshot_name" + else + log "⚠️ Failed to take screenshot (exit code: $exit_code), continuing without screenshot" + fi + return + fi + + current_time=$(date +%s) + elapsed=$((current_time - start_time)) + + if [ $elapsed -ge 10 ]; then + # Timeout reached - terminate the process + log "Terminating screenshot process due to timeout" + kill $screenshot_pid 2>/dev/null || true + wait $screenshot_pid 2>/dev/null || true + log "⚠️ Taking screenshot timed out after 10 seconds, continuing without screenshot." + break + fi + + sleep 0.1 + done } # Check if the app is currently running @@ -78,12 +119,14 @@ log "🔨 Building SwiftUI Crash Test app for simulator 🔨" xcodebuild -workspace Sentry.xcworkspace \ -scheme SwiftUICrashTest \ - -destination "platform=iOS Simulator,name=iPhone 16" \ + -destination "platform=iOS Simulator,name=iPhone 16 Pro" \ -derivedDataPath DerivedData \ -configuration Debug \ CODE_SIGNING_REQUIRED=NO \ build 2>&1 | tee raw-build.log | xcbeautify +xcrun simctl runtime dyld_shared_cache update iOS18.4 + log "Installing app on simulator." xcrun simctl install $DEVICE_ID DerivedData/Build/Products/Debug-iphonesimulator/SwiftUICrashTest.app @@ -100,7 +143,9 @@ xcrun simctl spawn $DEVICE_ID defaults write $BUNDLE_ID $USER_DEFAULT_KEY -bool log "Launching app with expected crash." xcrun simctl launch $DEVICE_ID $BUNDLE_ID -# Check every 100ms for 5 seconds if the app is still running. +log "Starting to check if app crashed as expected." + +# Check for 20 seconds if the app is still running. start_time=$(date +%s) while true; do if is_app_running; then @@ -113,10 +158,12 @@ while true; do current_time=$(date +%s) elapsed=$((current_time - start_time)) - if [ $elapsed -ge 5 ]; then - log "❌ App is still running after 5 seconds but it should have crashed instead." + if [ $elapsed -ge 20 ]; then + log "❌ App is still running after 20 seconds but it should have crashed instead." + take_simulator_screenshot "app-did-not-crash" exit 1 fi + done take_simulator_screenshot "after-crash" @@ -134,19 +181,21 @@ xcrun simctl launch $DEVICE_ID $BUNDLE_ID & take_simulator_screenshot "after-crash-check" -# Check for 5 seconds if the app is running. +log "Starting to check if app is running." + +# Check for 20 seconds if the app is still running. start_time=$(date +%s) while true; do if is_app_running; then log "⏳ App is still running." else - log "❌ App is not running." + log "❌ App is not running." fi current_time=$(date +%s) elapsed=$((current_time - start_time)) - if [ $elapsed -ge 5 ]; then + if [ $elapsed -ge 20 ]; then log "✅ Completed checking if app is still running." break fi diff --git a/TestSamples/SwiftUITestSample/Shared/Config/Architectures.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/Architectures.xcconfig deleted file mode 100644 index 38bc21077fd..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/Architectures.xcconfig +++ /dev/null @@ -1,7 +0,0 @@ -ONLY_ACTIVE_ARCH_Debug = YES -ONLY_ACTIVE_ARCH_Test = YES -ONLY_ACTIVE_ARCH_TestCI = YES -ONLY_ACTIVE_ARCH_Release = NO -ONLY_ACTIVE_ARCH = $(ONLY_ACTIVE_ARCH_$(CONFIGURATION)) - -SDKROOT = auto diff --git a/TestSamples/SwiftUITestSample/Shared/Config/AssetCatalog.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/AssetCatalog.xcconfig deleted file mode 100644 index f3989d10373..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/AssetCatalog.xcconfig +++ /dev/null @@ -1,3 +0,0 @@ -ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon -ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor -ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES diff --git a/TestSamples/SwiftUITestSample/Shared/Config/BuildOptions.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/BuildOptions.xcconfig deleted file mode 100644 index d5351b51be4..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/BuildOptions.xcconfig +++ /dev/null @@ -1,17 +0,0 @@ -DEBUG_INFORMATION_FORMAT_Debug = dwarf -DEBUG_INFORMATION_FORMAT_Test = dwarf-with-dsym -DEBUG_INFORMATION_FORMAT_TestCI = dwarf-with-dsym -DEBUG_INFORMATION_FORMAT_Release = dwarf-with-dsym -DEBUG_INFORMATION_FORMAT = $(DEBUG_INFORMATION_FORMAT_$(CONFIGURATION)) - -ENABLE_TESTABILITY_Debug = YES -ENABLE_TESTABILITY_Test = YES -ENABLE_TESTABILITY_TestCI = YES -ENABLE_TESTABILITY_Release = NO -ENABLE_TESTABILITY = $(ENABLE_TESTABILITY_$(CONFIGURATION)) - -VALIDATE_PRODUCT_Debug = NO -VALIDATE_PRODUCT_Test = YES -VALIDATE_PRODUCT_TestCI = YES -VALIDATE_PRODUCT_Release = YES -VALIDATE_PRODUCT = $(VALIDATE_PRODUCT_$(CONFIGURATION)) diff --git a/TestSamples/SwiftUITestSample/Shared/Config/ClangAnalyzer.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/ClangAnalyzer.xcconfig deleted file mode 100644 index f75a82686fd..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/ClangAnalyzer.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -CLANG_ANALYZER_NONNULL = YES -CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE diff --git a/TestSamples/SwiftUITestSample/Shared/Config/ClangCppLanguage.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/ClangCppLanguage.xcconfig deleted file mode 100644 index 233466b1970..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/ClangCppLanguage.xcconfig +++ /dev/null @@ -1 +0,0 @@ -CLANG_CXX_LANGUAGE_STANDARD = c++14 diff --git a/TestSamples/SwiftUITestSample/Shared/Config/ClangLanguage.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/ClangLanguage.xcconfig deleted file mode 100644 index b1c8d13ef44..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/ClangLanguage.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -GCC_C_LANGUAGE_STANDARD = gnu17 -CLANG_CXX_LIBRARY = libc++ diff --git a/TestSamples/SwiftUITestSample/Shared/Config/ClangModules.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/ClangModules.xcconfig deleted file mode 100644 index 04069aea3ec..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/ClangModules.xcconfig +++ /dev/null @@ -1 +0,0 @@ -CLANG_ENABLE_MODULES = YES diff --git a/TestSamples/SwiftUITestSample/Shared/Config/ClangObjCLanguage.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/ClangObjCLanguage.xcconfig deleted file mode 100644 index 8b73231b495..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/ClangObjCLanguage.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -CLANG_ENABLE_OBJC_ARC = YES -CLANG_ENABLE_OBJC_WEAK = YES diff --git a/TestSamples/SwiftUITestSample/Shared/Config/ClangPreprocessing.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/ClangPreprocessing.xcconfig deleted file mode 100644 index 6f5d9055978..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/ClangPreprocessing.xcconfig +++ /dev/null @@ -1,13 +0,0 @@ -ENABLE_STRICT_OBJC_MSGSEND = YES - -ENABLE_NS_ASSERTIONS_Debug = YES -ENABLE_NS_ASSERTIONS_Test = NO -ENABLE_NS_ASSERTIONS_TestCI = NO -ENABLE_NS_ASSERTIONS_Release = NO -ENABLE_NS_ASSERTIONS = $(ENABLE_NS_ASSERTIONS_$(CONFIGURATION)) - -GCC_PREPROCESSOR_DEFINITIONS_Debug = DEBUG=1 $(inherited) -GCC_PREPROCESSOR_DEFINITIONS_Test = TEST=1 $(inherited) -GCC_PREPROCESSOR_DEFINITIONS_TestCI = TESTCI=1 $(inherited) -GCC_PREPROCESSOR_DEFINITIONS_Release = RELEASE=1 $(inherited) -GCC_PREPROCESSOR_DEFINITIONS = $(GCC_PREPROCESSOR_DEFINITIONS_$(CONFIGURATION)) diff --git a/TestSamples/SwiftUITestSample/Shared/Config/ClangWarnings.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/ClangWarnings.xcconfig deleted file mode 100644 index 1b5fdd2dc3f..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/ClangWarnings.xcconfig +++ /dev/null @@ -1,21 +0,0 @@ -CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES -CLANG_WARN_BOOL_CONVERSION = YES -CLANG_WARN_COMMA = YES -CLANG_WARN_CONSTANT_CONVERSION = YES -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_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES -CLANG_WARN_STRICT_PROTOTYPES = YES -CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE -CLANG_WARN_UNREACHABLE_CODE = 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 diff --git a/TestSamples/SwiftUITestSample/Shared/Config/ClangWarningsCpp.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/ClangWarningsCpp.xcconfig deleted file mode 100644 index a251305116d..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/ClangWarningsCpp.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -CLANG_WARN_RANGE_LOOP_ANALYSIS = YES -CLANG_WARN_SUSPICIOUS_MOVE = YES diff --git a/TestSamples/SwiftUITestSample/Shared/Config/ClangWarningsObjC.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/ClangWarningsObjC.xcconfig deleted file mode 100644 index 842c3887d02..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/ClangWarningsObjC.xcconfig +++ /dev/null @@ -1,6 +0,0 @@ -CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES -CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR -CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES -CLANG_WARN_OBJC_LITERAL_CONVERSION = YES -CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR -CLANG_WARN__DUPLICATE_METHOD_MATCH = YES diff --git a/TestSamples/SwiftUITestSample/Shared/Config/CodeGeneration.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/CodeGeneration.xcconfig deleted file mode 100644 index ae321911ec9..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/CodeGeneration.xcconfig +++ /dev/null @@ -1,8 +0,0 @@ -GCC_DYNAMIC_NO_PIC = NO -GCC_NO_COMMON_BLOCKS = YES - -GCC_OPTIMIZATION_LEVEL_Debug = 0 -GCC_OPTIMIZATION_LEVEL_Test = 0 -GCC_OPTIMIZATION_LEVEL_TestCI = 0 -GCC_OPTIMIZATION_LEVEL_Release = s -GCC_OPTIMIZATION_LEVEL = $(GCC_OPTIMIZATION_LEVEL_$(CONFIGURATION)) diff --git a/TestSamples/SwiftUITestSample/Shared/Config/Linking.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/Linking.xcconfig deleted file mode 100644 index 5c8a0de1ad9..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/Linking.xcconfig +++ /dev/null @@ -1 +0,0 @@ -LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks diff --git a/TestSamples/SwiftUITestSample/Shared/Config/Localization.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/Localization.xcconfig deleted file mode 100644 index a7c7bae6faa..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/Localization.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -LOCALIZATION_PREFERS_STRING_CATALOGS = YES -SWIFT_EMIT_LOC_STRINGS = YES diff --git a/TestSamples/SwiftUITestSample/Shared/Config/Metal.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/Metal.xcconfig deleted file mode 100644 index 60d39505e62..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/Metal.xcconfig +++ /dev/null @@ -1,7 +0,0 @@ -MTL_ENABLE_DEBUG_INFO_Debug = INCLUDE_SOURCE -MTL_ENABLE_DEBUG_INFO_Release = NO -MTL_ENABLE_DEBUG_INFO_Test = NO -MTL_ENABLE_DEBUG_INFO_TestCI = NO -MTL_ENABLE_DEBUG_INFO = $(MTL_ENABLE_DEBUG_INFO_$(CONFIGURATION) - -MTL_FAST_MATH = YES diff --git a/TestSamples/SwiftUITestSample/Shared/Config/Packaging.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/Packaging.xcconfig deleted file mode 100644 index ca5399ab1b1..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/Packaging.xcconfig +++ /dev/null @@ -1,5 +0,0 @@ -GENERATE_INFOPLIST_FILE = YES -PRODUCT_NAME = $(TARGET_NAME) -INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = UIInterfaceOrientationPortrait -INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES -INFOPLIST_KEY_UILaunchScreen_Generation = YES diff --git a/TestSamples/SwiftUITestSample/Shared/Config/SearchPaths.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/SearchPaths.xcconfig deleted file mode 100644 index b1dcd44dd38..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/SearchPaths.xcconfig +++ /dev/null @@ -1 +0,0 @@ -ALWAYS_SEARCH_USER_PATHS = NO diff --git a/TestSamples/SwiftUITestSample/Shared/Config/Signing.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/Signing.xcconfig deleted file mode 100644 index 6e49bd1c92f..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/Signing.xcconfig +++ /dev/null @@ -1,14 +0,0 @@ -CODE_SIGN_STYLE = Automatic -DEVELOPMENT_TEAM = 97JCY7859U - -CODE_SIGN_IDENTITY_Debug = iPhone Developer -CODE_SIGN_IDENTITY_Test = iPhone Developer -CODE_SIGN_IDENTITY_TestCI = iPhone Developer -CODE_SIGN_IDENTITY_Release = iPhone Distribution -CODE_SIGN_IDENTITY_Debug[sdk=macosx*] = Apple Development -CODE_SIGN_IDENTITY_Test[sdk=macosx*] = Apple Development -CODE_SIGN_IDENTITY_TestCI[sdk=macosx*] = Apple Development -CODE_SIGN_IDENTITY_Release[sdk=macosx*] = Apple Distribution - -CODE_SIGN_IDENTITY = $(CODE_SIGN_IDENTITY_$(CONFIGURATION)) -CODE_SIGN_IDENTITY[sdk=macosx*] = $(CODE_SIGN_IDENTITY_$(CONFIGURATION)) diff --git a/TestSamples/SwiftUITestSample/Shared/Config/Swift.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/Swift.xcconfig deleted file mode 100644 index f8d427426da..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/Swift.xcconfig +++ /dev/null @@ -1,19 +0,0 @@ -SWIFT_VERSION = 5.0 - -SWIFT_ACTIVE_COMPILATION_CONDITIONS_Debug = DEBUG $(inherited) -SWIFT_ACTIVE_COMPILATION_CONDITIONS_Test = SENTRY_TEST $(inherited) -SWIFT_ACTIVE_COMPILATION_CONDITIONS_TestCI = SENTRY_TESTCI $(inherited) -SWIFT_ACTIVE_COMPILATION_CONDITIONS_Release = $(inherited) -SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(SWIFT_ACTIVE_COMPILATION_CONDITIONS_$(CONFIGURATION)) - -SWIFT_COMPILATION_MODE_Debug = singlefile -SWIFT_COMPILATION_MODE_Test = wholemodule -SWIFT_COMPILATION_MODE_TestCI = wholemodule -SWIFT_COMPILATION_MODE_Release = wholemodule -SWIFT_COMPILATION_MODE = $(SWIFT_COMPILATION_MODE_$(CONFIGURATION)) - -SWIFT_OPTIMIZATION_LEVEL_Debug = -Onone -SWIFT_OPTIMIZATION_LEVEL_Test = -Onone -SWIFT_OPTIMIZATION_LEVEL_TestCI = -Onone -SWIFT_OPTIMIZATION_LEVEL_Release = -O -SWIFT_OPTIMIZATION_LEVEL = $(SWIFT_OPTIMIZATION_LEVEL_$(CONFIGURATION)) diff --git a/TestSamples/SwiftUITestSample/Shared/Config/Versioning.xcconfig b/TestSamples/SwiftUITestSample/Shared/Config/Versioning.xcconfig deleted file mode 100644 index 51928251e98..00000000000 --- a/TestSamples/SwiftUITestSample/Shared/Config/Versioning.xcconfig +++ /dev/null @@ -1,2 +0,0 @@ -CURRENT_PROJECT_VERSION = 1 -MARKETING_VERSION = 8.52.1 diff --git a/TestSamples/SwiftUITestSample/SwiftUITestSample.xcconfig b/TestSamples/SwiftUITestSample/SwiftUITestSample.xcconfig index f51337e2f4b..0a8b1e2a939 100644 --- a/TestSamples/SwiftUITestSample/SwiftUITestSample.xcconfig +++ b/TestSamples/SwiftUITestSample/SwiftUITestSample.xcconfig @@ -1,28 +1,7 @@ -#include "Shared/Config/Architectures.xcconfig" -#include "Shared/Config/BuildOptions.xcconfig" -#include "Shared/Config/Deployment.xcconfig" -#include "Shared/Config/Linking.xcconfig" -#include "Shared/Config/Localization.xcconfig" -#include "Shared/Config/Packaging.xcconfig" -#include "Shared/Config/SearchPaths.xcconfig" -#include "Shared/Config/Signing.xcconfig" -#include "Shared/Config/Versioning.xcconfig" -#include "Shared/Config/CodeGeneration.xcconfig" -#include "Shared/Config/ClangLanguage.xcconfig" -#include "Shared/Config/ClangCppLanguage.xcconfig" -#include "Shared/Config/ClangModules.xcconfig" -#include "Shared/Config/ClangObjCLanguage.xcconfig" -#include "Shared/Config/ClangPreprocessing.xcconfig" -#include "Shared/Config/ClangWarnings.xcconfig" -#include "Shared/Config/ClangWarningsCpp.xcconfig" -#include "Shared/Config/ClangWarningsObjC.xcconfig" -#include "Shared/Config/AssetCatalog.xcconfig" -#include "Shared/Config/ClangAnalyzer.xcconfig" -#include "Shared/Config/Swift.xcconfig" -#include "Shared/Config/Metal.xcconfig" +#include "../../Samples/Shared/Config/_Common.xcconfig" +#include "../Common.xcconfig" PRODUCT_NAME = SwiftUITestSample PRODUCT_BUNDLE_IDENTIFIER = io.sentry.tests.SwiftUITestSample SUPPORTED_PLATFORMS = iphoneos iphonesimulator -MARKETING_VERSION = 1 diff --git a/TestSamples/SwiftUITestSample/SwiftUITestSampleUITests.xcconfig b/TestSamples/SwiftUITestSample/SwiftUITestSampleUITests.xcconfig index 865ef711e37..378f3f648bc 100644 --- a/TestSamples/SwiftUITestSample/SwiftUITestSampleUITests.xcconfig +++ b/TestSamples/SwiftUITestSample/SwiftUITestSampleUITests.xcconfig @@ -1,29 +1,7 @@ -#include "Shared/Config/Architectures.xcconfig" -#include "Shared/Config/BuildOptions.xcconfig" -#include "Shared/Config/Deployment.xcconfig" -#include "Shared/Config/Linking.xcconfig" -#include "Shared/Config/Localization.xcconfig" -#include "Shared/Config/Packaging.xcconfig" -#include "Shared/Config/SearchPaths.xcconfig" -#include "Shared/Config/Signing.xcconfig" -#include "Shared/Config/Versioning.xcconfig" -#include "Shared/Config/CodeGeneration.xcconfig" -#include "Shared/Config/ClangLanguage.xcconfig" -#include "Shared/Config/ClangCppLanguage.xcconfig" -#include "Shared/Config/ClangModules.xcconfig" -#include "Shared/Config/ClangObjCLanguage.xcconfig" -#include "Shared/Config/ClangPreprocessing.xcconfig" -#include "Shared/Config/ClangWarnings.xcconfig" -#include "Shared/Config/ClangWarningsCpp.xcconfig" -#include "Shared/Config/ClangWarningsObjC.xcconfig" -#include "Shared/Config/AssetCatalog.xcconfig" -#include "Shared/Config/ClangAnalyzer.xcconfig" -#include "Shared/Config/Swift.xcconfig" -#include "Shared/Config/Metal.xcconfig" +#include "../../Samples/Shared/Config/_Common.xcconfig" +#include "../Common.xcconfig" PRODUCT_BUNDLE_IDENTIFIER = io.sentry.SwiftUITestSampleUITests -GENERATE_INFOPLIST_FILE = YES SUPPORTED_PLATFORMS = iphoneos iphonesimulator TEST_TARGET_NAME = SwiftUITestSample -MARKETING_VERSION = 1 diff --git a/Tests/.swiftlint.yml b/Tests/.swiftlint.yml index ea3d52ac831..ffd89b62cda 100755 --- a/Tests/.swiftlint.yml +++ b/Tests/.swiftlint.yml @@ -1,8 +1,21 @@ parent_config: ../.swiftlint.yml -enabled_rules: +opt_in_rules: - test_case_accessibility +custom_rules: + avoid_background_qos_for_dispatch_queue: + name: "Avoid background QoS for dispatch queues in tests" + regex: 'qos:\s*\.background' + message: "Avoid background QoS for dispatch queues in tests, as in CI, work on dispatch queues with background QoS can take a long time to run and lead to flaky tests." + severity: error + + avoid_dispatch_groups_in_tests: + name: "Avoid DispatchGroups in tests" + regex: 'DispatchGroup\(\)' + message: "Avoid dispatch groups in tests as waiting on them doesn't fail the test. Consider to use a XCTestExpectation instead, which will fail the test if the expectation is not fulfilled and also have the possibility for asserting for overfulfilled expectations." + severity: error + disabled_rules: - force_cast - force_try diff --git a/Tests/DuplicatedSDKTest/DuplicatedSDKTest.xcodeproj/project.pbxproj b/Tests/DuplicatedSDKTest/DuplicatedSDKTest.xcodeproj/project.pbxproj index 6c8bb740b94..90d519656ef 100644 --- a/Tests/DuplicatedSDKTest/DuplicatedSDKTest.xcodeproj/project.pbxproj +++ b/Tests/DuplicatedSDKTest/DuplicatedSDKTest.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 77; + objectVersion = 63; objects = { /* Begin PBXBuildFile section */ @@ -15,6 +15,11 @@ D89DD6572CEF652B009C3509 /* Sentry.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D89DD6552CEF652B009C3509 /* Sentry.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; D89DD6592CEF6535009C3509 /* Sentry.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = D89DD6552CEF652B009C3509 /* Sentry.xcframework */; }; D89DD65A2CEF6535009C3509 /* Sentry.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D89DD6552CEF652B009C3509 /* Sentry.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + F41CE14C2E2EE7AC001123A5 /* SomeWork.swift in Sources */ = {isa = PBXBuildFile; fileRef = F474CB292E2B3DFC0001DF41 /* SomeWork.swift */; }; + F41CE14D2E2EE7AC001123A5 /* SomeWork.swift in Sources */ = {isa = PBXBuildFile; fileRef = F474CB292E2B3DFC0001DF41 /* SomeWork.swift */; }; + F474CB2E2E2B3DFC0001DF41 /* DuplicatedSDKTestApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = F474CB282E2B3DFC0001DF41 /* DuplicatedSDKTestApp.swift */; }; + F474CB2F2E2B3E180001DF41 /* UITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = F474CB2A2E2B3DFC0001DF41 /* UITest.swift */; }; + F474CB322E2B3E270001DF41 /* Unit_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F474CB302E2B3E270001DF41 /* Unit_Tests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -39,6 +44,13 @@ remoteGlobalIDString = D8C030CD2CEF633A007FC5B4; remoteInfo = DuplicatedSDKTest; }; + F45243162DE56862003E8F50 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D8C030C62CEF633A007FC5B4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = D8C030CD2CEF633A007FC5B4; + remoteInfo = DuplicatedSDKTest; + }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -84,54 +96,15 @@ D89DD6552CEF652B009C3509 /* Sentry.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Sentry.xcframework; path = ../../Carthage/Sentry.xcframework; sourceTree = ""; }; D89DD6732CEF7ADF009C3509 /* UITest-DuplicatedSDK.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "UITest-DuplicatedSDK.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; D8C030CE2CEF633A007FC5B4 /* DuplicatedSDKTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DuplicatedSDKTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + F45243122DE56862003E8F50 /* Unit Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Unit Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + F458F7462E271BC80001644E /* DuplicatedSDKTest.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = DuplicatedSDKTest.xctestplan; sourceTree = ""; }; + F474CB272E2B3DFC0001DF41 /* DuplicatedSDKTest-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "DuplicatedSDKTest-Bridging-Header.h"; sourceTree = ""; }; + F474CB282E2B3DFC0001DF41 /* DuplicatedSDKTestApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DuplicatedSDKTestApp.swift; sourceTree = ""; }; + F474CB292E2B3DFC0001DF41 /* SomeWork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SomeWork.swift; sourceTree = ""; }; + F474CB2A2E2B3DFC0001DF41 /* UITest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITest.swift; sourceTree = ""; }; + F474CB302E2B3E270001DF41 /* Unit_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Unit_Tests.swift; sourceTree = ""; }; /* End PBXFileReference section */ -/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */ - D89DD66C2CEF7940009C3509 /* Exceptions for "DuplicatedSDKTest" folder in "DuplicatedSDKTest" target */ = { - isa = PBXFileSystemSynchronizedBuildFileExceptionSet; - membershipExceptions = ( - SomeWork.swift, - UITest.swift, - ); - target = D8C030CD2CEF633A007FC5B4 /* DuplicatedSDKTest */; - }; - D89DD66D2CEF7940009C3509 /* Exceptions for "DuplicatedSDKTest" folder in "ModuleA" target */ = { - isa = PBXFileSystemSynchronizedBuildFileExceptionSet; - membershipExceptions = ( - SomeWork.swift, - ); - target = D89DD6352CEF650A009C3509 /* ModuleA */; - }; - D89DD66E2CEF7940009C3509 /* Exceptions for "DuplicatedSDKTest" folder in "ModuleB" target */ = { - isa = PBXFileSystemSynchronizedBuildFileExceptionSet; - membershipExceptions = ( - SomeWork.swift, - ); - target = D89DD6472CEF6516009C3509 /* ModuleB */; - }; - D89DD67E2CEF8389009C3509 /* Exceptions for "DuplicatedSDKTest" folder in "UITest-DuplicatedSDK" target */ = { - isa = PBXFileSystemSynchronizedBuildFileExceptionSet; - membershipExceptions = ( - UITest.swift, - ); - target = D89DD6722CEF7ADF009C3509 /* UITest-DuplicatedSDK */; - }; -/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */ - -/* Begin PBXFileSystemSynchronizedRootGroup section */ - D8C030D02CEF633A007FC5B4 /* DuplicatedSDKTest */ = { - isa = PBXFileSystemSynchronizedRootGroup; - exceptions = ( - D89DD66C2CEF7940009C3509 /* Exceptions for "DuplicatedSDKTest" folder in "DuplicatedSDKTest" target */, - D89DD66D2CEF7940009C3509 /* Exceptions for "DuplicatedSDKTest" folder in "ModuleA" target */, - D89DD66E2CEF7940009C3509 /* Exceptions for "DuplicatedSDKTest" folder in "ModuleB" target */, - D89DD67E2CEF8389009C3509 /* Exceptions for "DuplicatedSDKTest" folder in "UITest-DuplicatedSDK" target */, - ); - path = DuplicatedSDKTest; - sourceTree = ""; - }; -/* End PBXFileSystemSynchronizedRootGroup section */ - /* Begin PBXFrameworksBuildPhase section */ D89DD6332CEF650A009C3509 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; @@ -165,6 +138,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F452430F2DE56862003E8F50 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -179,7 +159,9 @@ D8C030C52CEF633A007FC5B4 = { isa = PBXGroup; children = ( - D8C030D02CEF633A007FC5B4 /* DuplicatedSDKTest */, + F458F7462E271BC80001644E /* DuplicatedSDKTest.xctestplan */, + F474CB2B2E2B3DFC0001DF41 /* DuplicatedSDKTest */, + F474CB312E2B3E270001DF41 /* Unit Tests */, D89DD6542CEF652B009C3509 /* Frameworks */, D8C030CF2CEF633A007FC5B4 /* Products */, ); @@ -192,10 +174,30 @@ D89DD6362CEF650A009C3509 /* ModuleA.framework */, D89DD6482CEF6516009C3509 /* ModuleB.framework */, D89DD6732CEF7ADF009C3509 /* UITest-DuplicatedSDK.xctest */, + F45243122DE56862003E8F50 /* Unit Tests.xctest */, ); name = Products; sourceTree = ""; }; + F474CB2B2E2B3DFC0001DF41 /* DuplicatedSDKTest */ = { + isa = PBXGroup; + children = ( + F474CB272E2B3DFC0001DF41 /* DuplicatedSDKTest-Bridging-Header.h */, + F474CB282E2B3DFC0001DF41 /* DuplicatedSDKTestApp.swift */, + F474CB292E2B3DFC0001DF41 /* SomeWork.swift */, + F474CB2A2E2B3DFC0001DF41 /* UITest.swift */, + ); + path = DuplicatedSDKTest; + sourceTree = ""; + }; + F474CB312E2B3E270001DF41 /* Unit Tests */ = { + isa = PBXGroup; + children = ( + F474CB302E2B3E270001DF41 /* Unit_Tests.swift */, + ); + path = "Unit Tests"; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -293,9 +295,6 @@ D89DD63B2CEF650A009C3509 /* PBXTargetDependency */, D89DD64D2CEF6516009C3509 /* PBXTargetDependency */, ); - fileSystemSynchronizedGroups = ( - D8C030D02CEF633A007FC5B4 /* DuplicatedSDKTest */, - ); name = DuplicatedSDKTest; packageProductDependencies = ( ); @@ -303,6 +302,26 @@ productReference = D8C030CE2CEF633A007FC5B4 /* DuplicatedSDKTest.app */; productType = "com.apple.product-type.application"; }; + F45243112DE56862003E8F50 /* Unit Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = F452431A2DE56862003E8F50 /* Build configuration list for PBXNativeTarget "Unit Tests" */; + buildPhases = ( + F452430E2DE56862003E8F50 /* Sources */, + F452430F2DE56862003E8F50 /* Frameworks */, + F45243102DE56862003E8F50 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + F45243172DE56862003E8F50 /* PBXTargetDependency */, + ); + name = "Unit Tests"; + packageProductDependencies = ( + ); + productName = "Unit Tests"; + productReference = F45243122DE56862003E8F50 /* Unit Tests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -310,7 +329,7 @@ isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1610; + LastSwiftUpdateCheck = 1630; LastUpgradeCheck = 1610; TargetAttributes = { D89DD6352CEF650A009C3509 = { @@ -329,9 +348,14 @@ CreatedOnToolsVersion = 16.1; LastSwiftMigration = 1610; }; + F45243112DE56862003E8F50 = { + CreatedOnToolsVersion = 16.3; + TestTargetID = D8C030CD2CEF633A007FC5B4; + }; }; }; buildConfigurationList = D8C030C92CEF633A007FC5B4 /* Build configuration list for PBXProject "DuplicatedSDKTest" */; + compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( @@ -340,7 +364,6 @@ ); mainGroup = D8C030C52CEF633A007FC5B4; minimizedProjectReferenceProxies = 1; - preferredProjectObjectVersion = 77; productRefGroup = D8C030CF2CEF633A007FC5B4 /* Products */; projectDirPath = ""; projectRoot = ""; @@ -349,6 +372,7 @@ D89DD6352CEF650A009C3509 /* ModuleA */, D89DD6472CEF6516009C3509 /* ModuleB */, D89DD6722CEF7ADF009C3509 /* UITest-DuplicatedSDK */, + F45243112DE56862003E8F50 /* Unit Tests */, ); }; /* End PBXProject section */ @@ -382,6 +406,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F45243102DE56862003E8F50 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -389,6 +420,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F41CE14C2E2EE7AC001123A5 /* SomeWork.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -396,6 +428,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F41CE14D2E2EE7AC001123A5 /* SomeWork.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -403,6 +436,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F474CB2F2E2B3E180001DF41 /* UITest.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -410,6 +444,15 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F474CB2E2E2B3DFC0001DF41 /* DuplicatedSDKTestApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + F452430E2DE56862003E8F50 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F474CB322E2B3E270001DF41 /* Unit_Tests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -431,6 +474,11 @@ target = D8C030CD2CEF633A007FC5B4 /* DuplicatedSDKTest */; targetProxy = D89DD6792CEF7ADF009C3509 /* PBXContainerItemProxy */; }; + F45243172DE56862003E8F50 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = D8C030CD2CEF633A007FC5B4 /* DuplicatedSDKTest */; + targetProxy = F45243162DE56862003E8F50 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -800,6 +848,42 @@ }; name = Release; }; + F45243182DE56862003E8F50 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.Unit-Tests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/DuplicatedSDKTest.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/DuplicatedSDKTest"; + }; + name = Debug; + }; + F45243192DE56862003E8F50 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.6; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.Unit-Tests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/DuplicatedSDKTest.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/DuplicatedSDKTest"; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -848,6 +932,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + F452431A2DE56862003E8F50 /* Build configuration list for PBXNativeTarget "Unit Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F45243182DE56862003E8F50 /* Debug */, + F45243192DE56862003E8F50 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = D8C030C62CEF633A007FC5B4 /* Project object */; diff --git a/Tests/DuplicatedSDKTest/DuplicatedSDKTest.xcodeproj/xcshareddata/xcschemes/DuplicatedSDKTest.xcscheme b/Tests/DuplicatedSDKTest/DuplicatedSDKTest.xcodeproj/xcshareddata/xcschemes/DuplicatedSDKTest.xcscheme new file mode 100644 index 00000000000..49aaf789170 --- /dev/null +++ b/Tests/DuplicatedSDKTest/DuplicatedSDKTest.xcodeproj/xcshareddata/xcschemes/DuplicatedSDKTest.xcscheme @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tests/DuplicatedSDKTest/DuplicatedSDKTest.xctestplan b/Tests/DuplicatedSDKTest/DuplicatedSDKTest.xctestplan new file mode 100644 index 00000000000..5c5b21e3fbf --- /dev/null +++ b/Tests/DuplicatedSDKTest/DuplicatedSDKTest.xctestplan @@ -0,0 +1,36 @@ +{ + "configurations" : [ + { + "id" : "56E63385-97E2-48DB-B364-C72450F8D572", + "name" : "Test Scheme Action", + "options" : { + + } + } + ], + "defaultOptions" : { + "targetForVariableExpansion" : { + "containerPath" : "container:DuplicatedSDKTest.xcodeproj", + "identifier" : "D8C030CD2CEF633A007FC5B4", + "name" : "DuplicatedSDKTest" + } + }, + "testTargets" : [ + { + "parallelizable" : false, + "target" : { + "containerPath" : "container:DuplicatedSDKTest.xcodeproj", + "identifier" : "F45243112DE56862003E8F50", + "name" : "Unit Tests" + } + }, + { + "target" : { + "containerPath" : "container:DuplicatedSDKTest.xcodeproj", + "identifier" : "D89DD6722CEF7ADF009C3509", + "name" : "UITest-DuplicatedSDK" + } + } + ], + "version" : 1 +} diff --git a/Tests/DuplicatedSDKTest/DuplicatedSDKTest/DuplicatedSDKTest-Bridging-Header.h b/Tests/DuplicatedSDKTest/DuplicatedSDKTest/DuplicatedSDKTest-Bridging-Header.h index 2072e1b3463..dc1c569169a 100644 --- a/Tests/DuplicatedSDKTest/DuplicatedSDKTest/DuplicatedSDKTest-Bridging-Header.h +++ b/Tests/DuplicatedSDKTest/DuplicatedSDKTest/DuplicatedSDKTest-Bridging-Header.h @@ -1,7 +1,8 @@ #import -@interface SentrySDK (DuplicatedSDKTest) +// Added to run integration tests, do not attempt this in your app +@interface SentrySDKInternal : NSObject + (SentryHub *)currentHub; diff --git a/Tests/DuplicatedSDKTest/DuplicatedSDKTest/DuplicatedSDKTestApp.swift b/Tests/DuplicatedSDKTest/DuplicatedSDKTest/DuplicatedSDKTestApp.swift index 1041f463eb6..294ad36665d 100644 --- a/Tests/DuplicatedSDKTest/DuplicatedSDKTest/DuplicatedSDKTestApp.swift +++ b/Tests/DuplicatedSDKTest/DuplicatedSDKTest/DuplicatedSDKTestApp.swift @@ -12,6 +12,8 @@ struct DuplicatedSDKTestApp: App { init () { SentrySDK.start { options in options.dsn = "https://6cc9bae94def43cab8444a99e0031c28@o447951.ingest.sentry.io/5428557" + options.debug = true + options.diagnosticLevel = .error } } @@ -33,7 +35,7 @@ struct ContentView: View { } func checkIntegrations() -> Bool { - guard let integrations = SentrySDK.currentHub().installedIntegrations else { + guard let integrations = SentrySDKInternal.currentHub().installedIntegrations else { return false } diff --git a/Tests/DuplicatedSDKTest/Unit Tests/Unit_Tests.swift b/Tests/DuplicatedSDKTest/Unit Tests/Unit_Tests.swift new file mode 100644 index 00000000000..658e0ef6793 --- /dev/null +++ b/Tests/DuplicatedSDKTest/Unit Tests/Unit_Tests.swift @@ -0,0 +1,94 @@ +import Foundation +import Sentry +import XCTest + +final class TestLog: XCTestCase { + private var pipe: Pipe? + private var originalStdOut: Int32? + private var capturedOutput = "" + private var isCapturing = false + + override func tearDown() { + stopCapturingOutput() + super.tearDown() + } + + func testDuplicatedLoadMessageOnSDKInit() throws { + let expectation = XCTestExpectation(description: "Wait for duplicated SDK load message") + + capturedOutput = "" + startCapturingOutput() + + // Initialize Sentry SDK + let options = Options() + options.debug = true + options.diagnosticLevel = .error + SentrySDK.start(options: options) + + // Force loading another library to trigger validation + let path = Bundle(for: type(of: self)).bundlePath + let fullpath = "\(path)/../../Frameworks/ModuleA.framework/ModuleA" + guard dlopen(fullpath, RTLD_NOW) != nil else { + let error = String(cString: dlerror()) + XCTFail("Could not open framework: \(error)") + return + } + + // Check for the message periodically + let checkQueue = DispatchQueue(label: "message.check") + checkQueue.async { + while self.isCapturing { + if self.capturedOutput.contains("Sentry SDK was loaded multiple times in the same binary") { + expectation.fulfill() + break + } + Thread.sleep(forTimeInterval: 0.1) // Check every 100ms + } + } + + // This expectation is fulfilled immediately on a mac, but takes way longer on CI + wait(for: [expectation], timeout: 600.0) + + XCTAssertTrue(capturedOutput.contains("Sentry SDK was loaded multiple times in the same binary")) + } + + private func startCapturingOutput() { + pipe = Pipe() + originalStdOut = dup(fileno(stdout)) + + guard let pipe = pipe else { + XCTFail("Failed to setup output capture") + return + } + + dup2(pipe.fileHandleForWriting.fileDescriptor, fileno(stdout)) + isCapturing = true + + // Start reading from pipe in background + pipe.fileHandleForReading.readabilityHandler = { [weak self] handle in + let data = handle.availableData + if let output = String(data: data, encoding: .utf8) { + DispatchQueue.main.async { + self?.capturedOutput += output + } + } + } + } + + private func stopCapturingOutput() { + guard let pipe = pipe, let originalStdOut = originalStdOut else { return } + + isCapturing = false + pipe.fileHandleForReading.readabilityHandler = nil + + fflush(stdout) + dup2(originalStdOut, fileno(stdout)) + close(originalStdOut) + + pipe.fileHandleForWriting.closeFile() + pipe.fileHandleForReading.closeFile() + + self.pipe = nil + self.originalStdOut = nil + } +} diff --git a/Tests/HybridSDKTest/HybridPod.podspec b/Tests/HybridSDKTest/HybridPod.podspec index 6a55f3d6f49..d42357baacd 100644 --- a/Tests/HybridSDKTest/HybridPod.podspec +++ b/Tests/HybridSDKTest/HybridPod.podspec @@ -13,6 +13,6 @@ Pod::Spec.new do |s| s.requires_arc = true s.frameworks = 'Foundation' s.swift_versions = "5.5" - s.dependency "Sentry/HybridSDK", "8.53.2" + s.dependency "Sentry/HybridSDK", "8.56.0" s.source_files = "HybridTest.swift" end diff --git a/Tests/Perf/metrics-test.yml b/Tests/Perf/metrics-test.yml index 2feb3fa93e5..29e8789fcf0 100644 --- a/Tests/Perf/metrics-test.yml +++ b/Tests/Perf/metrics-test.yml @@ -11,4 +11,4 @@ startupTimeTest: binarySizeTest: diffMin: 200 KiB - diffMax: 870 KiB + diffMax: 950 KiB diff --git a/Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.swift b/Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.swift index b522c52aa47..dc05d5193eb 100644 --- a/Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.swift +++ b/Tests/SentryProfilerTests/SentryAppLaunchProfilingTests.swift @@ -2,6 +2,7 @@ import XCTest #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) +@available(*, deprecated, message: "App launch profiling is deprecated in favor of continuous profiling.") final class SentryAppLaunchProfilingTests: XCTestCase { private var fixture: SentryProfileTestFixture! @@ -17,6 +18,7 @@ final class SentryAppLaunchProfilingTests: XCTestCase { } // MARK: transaction based profiling +@available(*, deprecated, message: "App launch profiling is deprecated in favor of continuous profiling.") extension SentryAppLaunchProfilingTests { // test that the launch trace instance is nil after stopping the launch // profiler @@ -24,7 +26,7 @@ extension SentryAppLaunchProfilingTests { fixture.options.enableAppLaunchProfiling = true fixture.options.profilesSampleRate = 1 fixture.options.tracesSampleRate = 1 - sentry_configureLaunchProfiling(fixture.options) + sentry_configureLaunchProfilingForNextLaunch(fixture.options) _sentry_nondeduplicated_startLaunchProfile() XCTAssertNotNil(sentry_launchTracer) sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) @@ -50,7 +52,7 @@ extension SentryAppLaunchProfilingTests { // -- Assert -- XCTAssert(appLaunchProfileConfigFileExists()) - let dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + let dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyTracesSampleRate], expectedTracesSampleRate) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyTracesSampleRand], expectedTracesSampleRand) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyProfilesSampleRate], expectedProfilesSampleRate) @@ -93,28 +95,37 @@ extension SentryAppLaunchProfilingTests { } } -// MARK: transaction based profiling iOS-only +// MARK: transaction based profiling (iOS-only) #if !os(macOS) +@available(*, deprecated, message: "App launch profiling is deprecated in favor of continuous profiling.") extension SentryAppLaunchProfilingTests { // test that if a launch trace profiler is running and SentryTimeToDisplayTracker reports the app had its initial frame drawn and isn't waiting for full drawing, that the profile is stopped func testLaunchTraceProfileStoppedOnInitialDisplayWithoutWaitingForFullDisplay() throws { // start a launch profile fixture.options.enableAppLaunchProfiling = true - fixture.options.profilesSampleRate = nil - sentry_configureLaunchProfiling(fixture.options) + fixture.options.profilesSampleRate = 1.0 + sentry_configureLaunchProfilingForNextLaunch(fixture.options) _sentry_nondeduplicated_startLaunchProfile() - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - XCTAssertNil(sentry_launchTracer) + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssert(sentry_isLaunchProfileCorrelatedToTraces()) + XCTAssertNotNil(sentry_launchTracer) let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) - SentrySDK.setAppStartMeasurement(appStartMeasurement) - let tracer = try fixture.newTransaction(testingAppLaunchSpans: true, automaticTransaction: true) - let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) - ttd.start(for: tracer) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) + + // Ensure frames tracker is running (required for TTD tracker) + SentryDependencyContainer.sharedInstance().framesTracker = fixture.framesTracker + + // Use sentry_launchTracer directly as the parent tracer since your modifications + // make the performance tracker create child spans (not SentryTracer objects) + let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: false, dispatchQueueWrapper: fixture.dispatchQueueWrapper) + XCTAssertTrue(ttd.start(for: try XCTUnwrap(sentry_launchTracer))) + ttd.reportInitialDisplay() ttd.reportFullyDisplayed() + fixture.displayLinkWrapper.call() - XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) } func testContentsOfLaunchTraceProfileTransactionContext() { @@ -130,11 +141,11 @@ extension SentryAppLaunchProfilingTests { fixture.options.enableAppLaunchProfiling = true fixture.options.profilesSampleRate = 1 fixture.options.tracesSampleRate = 1 - sentry_configureLaunchProfiling(fixture.options) + sentry_configureLaunchProfilingForNextLaunch(fixture.options) _sentry_nondeduplicated_startLaunchProfile() XCTAssert(try XCTUnwrap(SentryTraceProfiler.getCurrentProfiler()).isRunning()) - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setStart(with: fixture.options) let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: false, dispatchQueueWrapper: fixture.dispatchQueueWrapper) ttd.start(for: try XCTUnwrap(sentry_launchTracer)) ttd.reportInitialDisplay() @@ -145,8 +156,8 @@ extension SentryAppLaunchProfilingTests { #endif // !os(macOS) // MARK: continuous profiling v1 +@available(*, deprecated, message: "Continuos profiling V1 is deprecated.") extension SentryAppLaunchProfilingTests { - // test continuous launch profiling configuration func testContinuousLaunchProfileV1Configuration() throws { let options = Options() options.enableAppLaunchProfiling = true @@ -158,7 +169,8 @@ extension SentryAppLaunchProfilingTests { XCTAssertFalse(appLaunchProfileConfigFileExists()) sentry_sdkInitProfilerTasks(options, TestHub(client: nil, andScope: nil)) XCTAssert(appLaunchProfileConfigFileExists()) - let dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + + let dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyContinuousProfiling], true) _sentry_nondeduplicated_startLaunchProfile() @@ -183,7 +195,7 @@ extension SentryAppLaunchProfilingTests { // -- Assert -- XCTAssert(appLaunchProfileConfigFileExists()) - var dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + var dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyTracesSampleRate], options.tracesSampleRate) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyTracesSampleRand] as? Double, fixture.fixedRandomValue) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyProfilesSampleRate], options.profilesSampleRate) @@ -194,7 +206,7 @@ extension SentryAppLaunchProfilingTests { sentry_sdkInitProfilerTasks(options, TestHub(client: nil, andScope: nil)) // -- Assert -- - dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyContinuousProfiling], true) XCTAssertNil(dict[kSentryLaunchProfileConfigKeyTracesSampleRate]) XCTAssertNil(dict[kSentryLaunchProfileConfigKeyTracesSampleRand]) @@ -203,21 +215,22 @@ extension SentryAppLaunchProfilingTests { } } -// MARK: continuous profiling v1 iOS-only +// MARK: continuous profiling v1 (iOS-only) #if !os(macOS) +@available(*, deprecated, message: "Continuos profiling V1 is deprecated.") extension SentryAppLaunchProfilingTests { // test that if a launch continuous profiler is running and SentryTimeToDisplayTracker reports the app is fully drawn, that the profiler continues running func testLaunchContinuousProfileV1NotStoppedOnFullyDisplayed() throws { // start a launch profile fixture.options.enableAppLaunchProfiling = true fixture.options.profilesSampleRate = nil - sentry_configureLaunchProfiling(fixture.options) + sentry_configureLaunchProfilingForNextLaunch(fixture.options) _sentry_nondeduplicated_startLaunchProfile() XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) XCTAssertNil(sentry_launchTracer) let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) - SentrySDK.setAppStartMeasurement(appStartMeasurement) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) let tracer = try fixture.newTransaction(testingAppLaunchSpans: true, automaticTransaction: true) let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) ttd.start(for: tracer) @@ -232,13 +245,13 @@ extension SentryAppLaunchProfilingTests { // start a launch profile fixture.options.enableAppLaunchProfiling = true fixture.options.profilesSampleRate = nil - sentry_configureLaunchProfiling(fixture.options) + sentry_configureLaunchProfilingForNextLaunch(fixture.options) _sentry_nondeduplicated_startLaunchProfile() XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) XCTAssertNil(sentry_launchTracer) let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) - SentrySDK.setAppStartMeasurement(appStartMeasurement) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) let tracer = try fixture.newTransaction(testingAppLaunchSpans: true, automaticTransaction: true) let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: false, dispatchQueueWrapper: fixture.dispatchQueueWrapper) ttd.start(for: tracer) @@ -250,6 +263,7 @@ extension SentryAppLaunchProfilingTests { #endif // !os(macOS) // MARK: continuous profiling v2 +@available(*, deprecated, message: "This is only deprecated because SentryAppLaunchProfilingTests is deprecated. Once trace based and continuous profiling v1 is removed this deprecation can be removed.") extension SentryAppLaunchProfilingTests { func testContinuousLaunchProfileV2TraceLifecycleConfiguration() throws { // Arrange @@ -270,7 +284,7 @@ extension SentryAppLaunchProfilingTests { // Assert XCTAssert(appLaunchProfileConfigFileExists()) - let dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + let dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertEqual(try XCTUnwrap(dict[kSentryLaunchProfileConfigKeyContinuousProfilingV2]), true) XCTAssertEqual(try XCTUnwrap(dict[kSentryLaunchProfileConfigKeyProfilesSampleRate]), 1) XCTAssertEqual(try XCTUnwrap(dict[kSentryLaunchProfileConfigKeyProfilesSampleRand]), 0.5) @@ -303,7 +317,7 @@ extension SentryAppLaunchProfilingTests { // Assert XCTAssert(appLaunchProfileConfigFileExists()) - let dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + let dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertEqual(try XCTUnwrap(dict[kSentryLaunchProfileConfigKeyContinuousProfilingV2]), true) XCTAssertEqual(try XCTUnwrap(dict[kSentryLaunchProfileConfigKeyProfilesSampleRate]), 1) XCTAssertEqual(try XCTUnwrap(dict[kSentryLaunchProfileConfigKeyProfilesSampleRand]), 0.5) @@ -333,7 +347,7 @@ extension SentryAppLaunchProfilingTests { // -- Assert -- XCTAssert(appLaunchProfileConfigFileExists()) - var dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + var dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyTracesSampleRate], options.tracesSampleRate) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyTracesSampleRand] as? Double, fixture.fixedRandomValue) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyProfilesSampleRate], options.profilesSampleRate) @@ -349,7 +363,7 @@ extension SentryAppLaunchProfilingTests { sentry_sdkInitProfilerTasks(options, TestHub(client: nil, andScope: nil)) // -- Assert -- - dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertNil(dict[kSentryLaunchProfileConfigKeyContinuousProfiling]) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyContinuousProfilingV2], true) XCTAssertNil(dict[kSentryLaunchProfileConfigKeyTracesSampleRate]) @@ -374,7 +388,7 @@ extension SentryAppLaunchProfilingTests { // -- Assert -- XCTAssert(appLaunchProfileConfigFileExists()) - var dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + var dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyTracesSampleRate], options.tracesSampleRate) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyTracesSampleRand] as? Double, fixture.fixedRandomValue) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyProfilesSampleRate], options.profilesSampleRate) @@ -390,7 +404,7 @@ extension SentryAppLaunchProfilingTests { sentry_sdkInitProfilerTasks(options, TestHub(client: nil, andScope: nil)) // -- Assert -- - dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertNil(dict[kSentryLaunchProfileConfigKeyContinuousProfiling]) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyContinuousProfilingV2], true) XCTAssertEqual(try XCTUnwrap(dict[kSentryLaunchProfileConfigKeyTracesSampleRate]), 0.789) @@ -415,7 +429,7 @@ extension SentryAppLaunchProfilingTests { sentry_sdkInitProfilerTasks(options, TestHub(client: nil, andScope: nil)) // -- Assert -- - var dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + var dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyContinuousProfiling], true) XCTAssertNil(dict[kSentryLaunchProfileConfigKeyTracesSampleRate]) XCTAssertNil(dict[kSentryLaunchProfileConfigKeyTracesSampleRand]) @@ -432,7 +446,7 @@ extension SentryAppLaunchProfilingTests { sentry_sdkInitProfilerTasks(options, TestHub(client: nil, andScope: nil)) // -- Assert -- - dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertNil(dict[kSentryLaunchProfileConfigKeyContinuousProfiling]) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyContinuousProfilingV2], true) XCTAssertNil(dict[kSentryLaunchProfileConfigKeyTracesSampleRate]) @@ -457,7 +471,7 @@ extension SentryAppLaunchProfilingTests { sentry_sdkInitProfilerTasks(options, TestHub(client: nil, andScope: nil)) // -- Assert -- - var dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + var dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyContinuousProfiling], true) XCTAssertNil(dict[kSentryLaunchProfileConfigKeyTracesSampleRate]) XCTAssertNil(dict[kSentryLaunchProfileConfigKeyTracesSampleRand]) @@ -475,7 +489,7 @@ extension SentryAppLaunchProfilingTests { sentry_sdkInitProfilerTasks(options, TestHub(client: nil, andScope: nil)) // -- Assert -- - dict = try XCTUnwrap(sentry_appLaunchProfileConfiguration()) + dict = try XCTUnwrap(sentry_persistedLaunchProfileConfigurationOptions()) XCTAssertNil(dict[kSentryLaunchProfileConfigKeyContinuousProfiling]) XCTAssertEqual(dict[kSentryLaunchProfileConfigKeyContinuousProfilingV2], true) XCTAssertEqual(try XCTUnwrap(dict[kSentryLaunchProfileConfigKeyTracesSampleRate]), 0.789) @@ -486,8 +500,9 @@ extension SentryAppLaunchProfilingTests { } } -// MARK: continuous profiling v2 iOS-only +// MARK: continuous profiling v2 (iOS-only) #if !os(macOS) +@available(*, deprecated, message: "This is only deprecated because SentryAppLaunchProfilingTests is deprecated. Once trace based and continuous profiling v1 is removed this deprecation can be removed.") extension SentryAppLaunchProfilingTests { func testLaunchContinuousProfileV2TraceLifecycleNotStoppedOnFullyDisplayed() throws { // Arrange @@ -499,7 +514,7 @@ extension SentryAppLaunchProfilingTests { $0.lifecycle = .trace } sentry_configureContinuousProfiling(fixture.options) - sentry_configureLaunchProfiling(fixture.options) + sentry_configureLaunchProfilingForNextLaunch(fixture.options) // Act _sentry_nondeduplicated_startLaunchProfile() @@ -510,7 +525,7 @@ extension SentryAppLaunchProfilingTests { // Act let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) - SentrySDK.setAppStartMeasurement(appStartMeasurement) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) let tracer = try fixture.newTransaction(testingAppLaunchSpans: true, automaticTransaction: true) let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) ttd.start(for: tracer) @@ -531,7 +546,7 @@ extension SentryAppLaunchProfilingTests { $0.lifecycle = .manual } sentry_configureContinuousProfiling(fixture.options) - sentry_configureLaunchProfiling(fixture.options) + sentry_configureLaunchProfilingForNextLaunch(fixture.options) // Act _sentry_nondeduplicated_startLaunchProfile() @@ -542,7 +557,7 @@ extension SentryAppLaunchProfilingTests { // Act let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) - SentrySDK.setAppStartMeasurement(appStartMeasurement) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) let tracer = try fixture.newTransaction(testingAppLaunchSpans: true, automaticTransaction: true) let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) ttd.start(for: tracer) @@ -564,7 +579,7 @@ extension SentryAppLaunchProfilingTests { $0.lifecycle = .trace } sentry_configureContinuousProfiling(fixture.options) - sentry_configureLaunchProfiling(fixture.options) + sentry_configureLaunchProfilingForNextLaunch(fixture.options) // Act _sentry_nondeduplicated_startLaunchProfile() @@ -575,7 +590,7 @@ extension SentryAppLaunchProfilingTests { // Act let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) - SentrySDK.setAppStartMeasurement(appStartMeasurement) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) let tracer = try fixture.newTransaction(testingAppLaunchSpans: true, automaticTransaction: true) let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: false, dispatchQueueWrapper: fixture.dispatchQueueWrapper) ttd.start(for: tracer) @@ -595,7 +610,7 @@ extension SentryAppLaunchProfilingTests { $0.lifecycle = .manual } sentry_configureContinuousProfiling(fixture.options) - sentry_configureLaunchProfiling(fixture.options) + sentry_configureLaunchProfilingForNextLaunch(fixture.options) // Act _sentry_nondeduplicated_startLaunchProfile() @@ -606,7 +621,7 @@ extension SentryAppLaunchProfilingTests { // Act let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) - SentrySDK.setAppStartMeasurement(appStartMeasurement) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) let tracer = try fixture.newTransaction(testingAppLaunchSpans: true, automaticTransaction: true) let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: false, dispatchQueueWrapper: fixture.dispatchQueueWrapper) ttd.start(for: tracer) @@ -618,5 +633,4 @@ extension SentryAppLaunchProfilingTests { } } #endif // !os(macOS) - #endif // os(iOS) || os(macOS) || targetEnvironment(macCatalyst) diff --git a/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationChangeTests.swift b/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationChangeTests.swift new file mode 100644 index 00000000000..cebbfe432e5 --- /dev/null +++ b/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationChangeTests.swift @@ -0,0 +1,1636 @@ +//swiftlint:disable file_length + +@_spi(Private) import SentryTestUtils +import XCTest + +#if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) +/// Validate stopping behavior of launch profiles that run with one set of configured options, where the SDK is started on that launch with a different set of options, to validate that the configured options persisted to disk from the previous launch are the ones used to determine how/when to stop the profiler, and not the new options currently in memory +@available(*, deprecated, message: "This is only marked as deprecated because it must still test some deprecated profiling APIs, but the deprecation warnings are converted to errors in our test targets. Once the deprecated API are removed, this can also be removed.") +final class SentryAppStartProfilingConfigurationChangeTests: XCTestCase { + private var fixture: SentryProfileTestFixture! + + override func setUp() { + super.setUp() + fixture = SentryProfileTestFixture() + } + + override func tearDown() { + super.tearDown() + clearTestState() + } +} + +// MARK: configuration changes between launches (no TTFD combinations, see iOS-only tests) +@available(*, deprecated, message: "This is only marked as deprecated because it must still test some deprecated profiling APIs, but the deprecation warnings are converted to errors in our test targets. Once the deprecated API are removed, this can also be removed.") +extension SentryAppStartProfilingConfigurationChangeTests { + func test_lastLaunch_traceBased_currentLaunch_continuousV1() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyTracesSampleRate: 1, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.tracesSampleRate = 1 + fixture.options.profilesSampleRate = nil + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_traceBased_currentLaunch_continuousV2_traceLifecycle() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyTracesSampleRate: 1, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .trace + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.tracesSampleRate = 1 + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_traceBased_currentLaunch_continuousV2_manualLifecycle() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyTracesSampleRate: 1, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .manual + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV1_currentLaunch_continuousV2_traceLifecycle() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfiling: true, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .trace + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.tracesSampleRate = 1 + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV1_currentLaunch_continuousV2_manualLifecycle() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfiling: true, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .manual + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV1_currentLaunch_traceBased() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfiling: true, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.tracesSampleRate = 1 + fixture.options.profilesSampleRate = 1 + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_traceLifecycle_currentLaunch_continuousV1() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.profilesSampleRate = nil + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate elapsed time to finish UI profile chunk + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_manualLifecycle_currentLaunch_continuousV1() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.profilesSampleRate = nil + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_traceLifecycle_currentLaunch_traceBased() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.tracesSampleRate = 1 + fixture.options.profilesSampleRate = 1 + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate elapsed time to finish UI profile chunk + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_manualLifecycle_currentLaunch_traceBased() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.tracesSampleRate = 1 + fixture.options.profilesSampleRate = 1 + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } +} + +#if !os(macOS) +// MARK: configuring launch profiling with TTFD disabled, then launching with it enabled (iOS-only) +@available(*, deprecated, message: "This is only marked as deprecated because it must still test some deprecated profiling APIs, but the deprecation warnings are converted to errors in our test targets. Once the deprecated API are removed, this can also be removed.") +extension SentryAppStartProfilingConfigurationChangeTests { + // MARK: starting with trace-based no TTFD + func test_lastLaunch_traceBased_noTTFD_currentLaunch_continuousV1_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyTracesSampleRate: 1, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.tracesSampleRate = 1 + fixture.options.profilesSampleRate = nil + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_traceBased_noTTFD_currentLaunch_continuousV2_traceLifecycle_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyTracesSampleRate: 1, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .trace + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.tracesSampleRate = 1 + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_traceBased_noTTFD_currentLaunch_continuousV2_manualLifecycle_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyTracesSampleRate: 1, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .manual + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_traceBased_noTTFD_currentLaunch_traceBased_withTTFD() throws { + + } + + // MARK: starting with continuous v1 no TTFD + func test_lastLaunch_continuousV1_noTTFD_currentLaunch_continuousV1_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfiling: true, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.profilesSampleRate = nil + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV1_noTTFD_currentLaunch_continuousV2_traceLifecycle_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfiling: true, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .trace + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.tracesSampleRate = 1 + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV1_noTTFD_currentLaunch_continuousV2_manualLifecycle_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfiling: true, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .manual + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV1_noTTFD_currentLaunch_traceBased_withTTFD() throws { + + } + + // MARK: starting with continuous v2 manual lifecycle no TTFD + func test_lastLaunch_continuousV2_manualLifecycle_noTTFD_currentLaunch_continuousV1_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.profilesSampleRate = nil + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_manualLifecycle_noTTFD_currentLaunch_continuousV2_traceLifecycle_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .trace + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.tracesSampleRate = 1 + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_manualLifecycle_noTTFD_currentLaunch_continuousV2_manualLifecycle_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .manual + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_manualLifecycle_noTTFD_currentLaunch_traceBased_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.tracesSampleRate = 1 + fixture.options.profilesSampleRate = 1 + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + // MARK: starting with continuous v2 trace lifecycle no TTFD + func test_lastLaunch_continuousV2_traceLifecycle_noTTFD_currentLaunch_continuousV1_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.profilesSampleRate = nil + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate elapsed time to finish UI profile chunk + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_traceLifecycle_noTTFD_currentLaunch_continuousV2_traceLifecycle_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .trace + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.tracesSampleRate = 1 + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate elapsed time to finish UI profile chunk + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_traceLifecycle_noTTFD_currentLaunch_continuousV2_manualLifecycle_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .manual + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate elapsed time to finish UI profile chunk + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_traceLifecycle_noTTFD_currentLaunch_traceBased_withTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: false + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.tracesSampleRate = 1 + fixture.options.profilesSampleRate = 1 + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate elapsed time to finish UI profile chunk + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } +} + +// MARK: configuring launch profiling with TTFD enabled, then launching with it disabled (iOS-only) +@available(*, deprecated, message: "This is only marked as deprecated because it must still test some deprecated profiling APIs, but the deprecation warnings are converted to errors in our test targets. Once the deprecated API are removed, this can also be removed.") +extension SentryAppStartProfilingConfigurationChangeTests { + // MARK: starting with trace-based with TTFD + func test_lastLaunch_traceBased_withTTFD_currentLaunch_continuousV1_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyTracesSampleRate: 1, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration (continuous V1) + fixture.options.profilesSampleRate = nil // Enables continuous profiling V1 + fixture.options.enableTimeToFullDisplayTracing = true + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started (trace-based from launch config) + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Assert profiler not stopped initially (waiting for TTFD due to launch config) + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate TTFD using launch tracer (not a new transaction) + // Since the launch profiler is trace-based, we use the existing launch tracer + let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) + + // Use the launch tracer for TTFD simulation + let launchTracer = try XCTUnwrap(sentry_launchTracer) + let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) + ttd.start(for: launchTracer) + ttd.reportInitialDisplay() + ttd.reportFullyDisplayed() + fixture.displayLinkWrapper.call() + + // Assert profile stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_traceBased_withTTFD_currentLaunch_continuousV2_traceLifecycle_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyTracesSampleRate: 1, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .trace + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.tracesSampleRate = 1 + fixture.options.enableTimeToFullDisplayTracing = false + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Assert profiler not stopped (waiting for TTFD) + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate TTFD + let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) + + // Use the launch tracer for TTFD simulation + let launchTracer = try XCTUnwrap(sentry_launchTracer) + + let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) + ttd.start(for: launchTracer) + ttd.reportInitialDisplay() + ttd.reportFullyDisplayed() + fixture.displayLinkWrapper.call() + + // Assert profile stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_traceBased_withTTFD_currentLaunch_continuousV2_manualLifecycle_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyTracesSampleRate: 1, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .manual + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.enableTimeToFullDisplayTracing = false + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Assert profiler not stopped (waiting for TTFD) + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate TTFD + let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) + let launchTracer = try XCTUnwrap(sentry_launchTracer) + let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) + ttd.start(for: launchTracer) + ttd.reportInitialDisplay() + ttd.reportFullyDisplayed() + fixture.displayLinkWrapper.call() + + // Assert profile stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_traceBased_withTTFD_currentLaunch_traceBased_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyTracesSampleRate: 1, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.tracesSampleRate = 1 + fixture.options.profilesSampleRate = 1 + fixture.options.enableTimeToFullDisplayTracing = false + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Assert profiler not stopped (waiting for TTFD) + XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate TTFD + let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) + let launchTracer = try XCTUnwrap(sentry_launchTracer) + let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) + ttd.start(for: launchTracer) + ttd.reportInitialDisplay() + ttd.reportFullyDisplayed() + fixture.displayLinkWrapper.call() + + // Assert profile stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + // MARK: starting with continuous v1 with TTFD + func test_lastLaunch_continuousV1_withTTFD_currentLaunch_continuousV1_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfiling: true, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.profilesSampleRate = nil + fixture.options.enableTimeToFullDisplayTracing = false + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler not stopped initially, continuous profiler doesn't wait for TTFD + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV1_withTTFD_currentLaunch_continuousV2_traceLifecycle_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfiling: true, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .trace + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.tracesSampleRate = 1 + fixture.options.enableTimeToFullDisplayTracing = false + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV1_withTTFD_currentLaunch_continuousV2_manualLifecycle_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfiling: true, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .manual + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.enableTimeToFullDisplayTracing = false + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV1_withTTFD_currentLaunch_traceBased() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfiling: true, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.tracesSampleRate = 1 + fixture.options.profilesSampleRate = 1 + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate stopping the continuous profiler + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + // MARK: starting with continuous v2 manual lifecycle with TTFD + func test_lastLaunch_continuousV2_manualLifecycle_withTTFD_currentLaunch_continuousV1_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.profilesSampleRate = nil + fixture.options.enableTimeToFullDisplayTracing = false + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate elapsed time to finish UI profile chunk + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_manualLifecycle_withTTFD_currentLaunch_continuousV2_traceLifecycle_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .trace + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.tracesSampleRate = 1 + fixture.options.enableTimeToFullDisplayTracing = false + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate elapsed time to finish UI profile chunk + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_manualLifecycle_withTTFD_currentLaunch_continuousV2_manualLifecycle_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .manual + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.enableTimeToFullDisplayTracing = false + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate elapsed time to finish UI profile chunk + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_manualLifecycle_withTTFD_currentLaunch_traceBased_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.manual.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.tracesSampleRate = 1 + fixture.options.profilesSampleRate = 1 + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate elapsed time to finish UI profile chunk + SentrySDK.stopProfiler() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + // MARK: starting with continuous v2 trace lifecycle with TTFD + func test_lastLaunch_continuousV2_traceLifecycle_withTTFD_currentLaunch_continuousV1_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.profilesSampleRate = nil + fixture.options.enableTimeToFullDisplayTracing = false + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate TTFD stoppage + let launchTracer = try XCTUnwrap(sentry_launchTracer) + let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) + ttd.start(for: launchTracer) + ttd.reportInitialDisplay() + ttd.reportFullyDisplayed() + fixture.displayLinkWrapper.call() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_traceLifecycle_withTTFD_currentLaunch_continuousV2_traceLifecycle_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .trace + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.tracesSampleRate = 1 + fixture.options.enableTimeToFullDisplayTracing = false + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate TTFD stoppage + let launchTracer = try XCTUnwrap(sentry_launchTracer) + let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) + ttd.start(for: launchTracer) + ttd.reportInitialDisplay() + ttd.reportFullyDisplayed() + fixture.displayLinkWrapper.call() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_traceLifecycle_withTTFD_currentLaunch_continuousV2_manualLifecycle_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.configureProfiling = { + $0.lifecycle = .manual + $0.sessionSampleRate = 1 + $0.profileAppStarts = true + } + fixture.options.enableTimeToFullDisplayTracing = false + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate TTFD stoppage + let launchTracer = try XCTUnwrap(sentry_launchTracer) + let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) + ttd.start(for: launchTracer) + ttd.reportInitialDisplay() + ttd.reportFullyDisplayed() + fixture.displayLinkWrapper.call() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } + + func test_lastLaunch_continuousV2_traceLifecycle_withTTFD_currentLaunch_traceBased_noTTFD() throws { + // Arrange + // persisted configuration simulating previous launch + let configDict: [String: Any] = [ + kSentryLaunchProfileConfigKeyContinuousProfilingV2: true, + kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle: SentryProfileLifecycle.trace.rawValue, + kSentryLaunchProfileConfigKeyProfilesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyProfilesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRate: 0.5, + kSentryLaunchProfileConfigKeyTracesSampleRand: 0.5, + kSentryLaunchProfileConfigKeyWaitForFullDisplay: true + ] + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + try (configDict as NSDictionary).write(to: configURL) + + // new options simulating current launch configuration + fixture.options.tracesSampleRate = 1 + fixture.options.profilesSampleRate = 1 + + // Act: simulate app launch + _sentry_nondeduplicated_startLaunchProfile() + + // Assert correct type of profile started + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) + + // Act: simulate SDK start + sentry_sdkInitProfilerTasks(fixture.options, TestHub(client: nil, andScope: nil)) + + // Act: simulate TTFD stoppage + let launchTracer = try XCTUnwrap(sentry_launchTracer) + let ttd = SentryTimeToDisplayTracker(name: "UIViewController", waitForFullDisplay: true, dispatchQueueWrapper: fixture.dispatchQueueWrapper) + ttd.start(for: launchTracer) + ttd.reportInitialDisplay() + ttd.reportFullyDisplayed() + fixture.displayLinkWrapper.call() + fixture.currentDateProvider.advance(by: 60) + try fixture.timeoutTimerFactory.check() + + // Assert profiler stopped + XCTAssertFalse(SentryTraceProfiler.isCurrentlyProfiling()) + XCTAssertFalse(SentryContinuousProfiler.isCurrentlyProfiling()) + } +} +#endif // !os(macOS) + +#endif // os(iOS) || os(macOS) || targetEnvironment(macCatalyst) + +//swiftlint:enable file_length diff --git a/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationTests.swift b/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationTests.swift index 63e7fb6ae88..a853faab98e 100644 --- a/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationTests.swift +++ b/Tests/SentryProfilerTests/SentryAppStartProfilingConfigurationTests.swift @@ -1,4 +1,4 @@ -import SentryTestUtils +@_spi(Private) import SentryTestUtils import XCTest #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) @@ -28,6 +28,7 @@ final class SentryAppStartProfilingConfigurationTests: XCTestCase { } } +@available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") extension SentryAppStartProfilingConfigurationTests { func testValidCombinations() { for config in SentryAppStartProfilingConfigurationTests.validConfigurations { @@ -61,6 +62,7 @@ extension SentryAppStartProfilingConfigurationTests { } private extension SentryAppStartProfilingConfigurationTests { + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") private func performTest(expectedOptions: LaunchProfileOptions, shouldProfileLaunch: Bool) { let actualOptions = Options() actualOptions.enableAppLaunchProfiling = expectedOptions.enableAppLaunchProfiling diff --git a/Tests/SentryProfilerTests/SentryApplaunchProfilingMalformedConfigFileTests.swift b/Tests/SentryProfilerTests/SentryApplaunchProfilingMalformedConfigFileTests.swift index f6193f00663..e23bb1c3043 100644 --- a/Tests/SentryProfilerTests/SentryApplaunchProfilingMalformedConfigFileTests.swift +++ b/Tests/SentryProfilerTests/SentryApplaunchProfilingMalformedConfigFileTests.swift @@ -15,13 +15,13 @@ class SentryAppLaunchProfilingMalformedConfigFileTests: XCTestCase { func testMalformedConfigFile_CorruptedPlist_DoesNotStartProfilingAndRemovesFile() throws { // Create a corrupted plist file that can't be parsed - let configURL = launchProfileConfigFileURL() + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) let corruptedData = Data("this is not a valid plist file {[}".utf8) try corruptedData.write(to: configURL) XCTAssertTrue(appLaunchProfileConfigFileExists()) - XCTAssertNil(sentry_appLaunchProfileConfiguration()) + XCTAssertNil(sentry_persistedLaunchProfileConfigurationOptions()) _sentry_nondeduplicated_startLaunchProfile() @@ -41,11 +41,11 @@ class SentryAppLaunchProfilingMalformedConfigFileTests: XCTestCase { // Missing: kSentryLaunchProfileConfigKeyContinuousProfilingV2Lifecycle ] - let configURL = launchProfileConfigFileURL() + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) try (configDict as NSDictionary).write(to: configURL) XCTAssertTrue(appLaunchProfileConfigFileExists()) - XCTAssertNotNil(sentry_appLaunchProfileConfiguration()) + XCTAssertNotNil(sentry_persistedLaunchProfileConfigurationOptions()) _sentry_nondeduplicated_startLaunchProfile() @@ -65,11 +65,11 @@ class SentryAppLaunchProfilingMalformedConfigFileTests: XCTestCase { // Missing: kSentryLaunchProfileConfigKeyProfilesSampleRate ] - let configURL = launchProfileConfigFileURL() + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) try (configDict as NSDictionary).write(to: configURL) XCTAssertTrue(appLaunchProfileConfigFileExists()) - XCTAssertNotNil(sentry_appLaunchProfileConfiguration()) + XCTAssertNotNil(sentry_persistedLaunchProfileConfigurationOptions()) _sentry_nondeduplicated_startLaunchProfile() @@ -89,11 +89,11 @@ class SentryAppLaunchProfilingMalformedConfigFileTests: XCTestCase { // Missing: kSentryLaunchProfileConfigKeyProfilesSampleRand ] - let configURL = launchProfileConfigFileURL() + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) try (configDict as NSDictionary).write(to: configURL) XCTAssertTrue(appLaunchProfileConfigFileExists()) - XCTAssertNotNil(sentry_appLaunchProfileConfiguration()) + XCTAssertNotNil(sentry_persistedLaunchProfileConfigurationOptions()) _sentry_nondeduplicated_startLaunchProfile() @@ -113,11 +113,11 @@ class SentryAppLaunchProfilingMalformedConfigFileTests: XCTestCase { // Missing: kSentryLaunchProfileConfigKeyProfilesSampleRate ] - let configURL = launchProfileConfigFileURL() + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) try (configDict as NSDictionary).write(to: configURL) XCTAssertTrue(appLaunchProfileConfigFileExists()) - XCTAssertNotNil(sentry_appLaunchProfileConfiguration()) + XCTAssertNotNil(sentry_persistedLaunchProfileConfigurationOptions()) _sentry_nondeduplicated_startLaunchProfile() @@ -137,11 +137,11 @@ class SentryAppLaunchProfilingMalformedConfigFileTests: XCTestCase { // Missing: kSentryLaunchProfileConfigKeyProfilesSampleRand ] - let configURL = launchProfileConfigFileURL() + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) try (configDict as NSDictionary).write(to: configURL) XCTAssertTrue(appLaunchProfileConfigFileExists()) - XCTAssertNotNil(sentry_appLaunchProfileConfiguration()) + XCTAssertNotNil(sentry_persistedLaunchProfileConfigurationOptions()) _sentry_nondeduplicated_startLaunchProfile() @@ -161,11 +161,11 @@ class SentryAppLaunchProfilingMalformedConfigFileTests: XCTestCase { // Missing: kSentryLaunchProfileConfigKeyTracesSampleRate ] - let configURL = launchProfileConfigFileURL() + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) try (configDict as NSDictionary).write(to: configURL) XCTAssertTrue(appLaunchProfileConfigFileExists()) - XCTAssertNotNil(sentry_appLaunchProfileConfiguration()) + XCTAssertNotNil(sentry_persistedLaunchProfileConfigurationOptions()) _sentry_nondeduplicated_startLaunchProfile() @@ -185,11 +185,11 @@ class SentryAppLaunchProfilingMalformedConfigFileTests: XCTestCase { // Missing: kSentryLaunchProfileConfigKeyTracesSampleRand ] - let configURL = launchProfileConfigFileURL() + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) try (configDict as NSDictionary).write(to: configURL) XCTAssertTrue(appLaunchProfileConfigFileExists()) - XCTAssertNotNil(sentry_appLaunchProfileConfiguration()) + XCTAssertNotNil(sentry_persistedLaunchProfileConfigurationOptions()) _sentry_nondeduplicated_startLaunchProfile() @@ -204,11 +204,11 @@ class SentryAppLaunchProfilingMalformedConfigFileTests: XCTestCase { // Create an empty but valid plist file let configDict: [String: Any] = [:] - let configURL = launchProfileConfigFileURL() + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) try (configDict as NSDictionary).write(to: configURL) XCTAssertTrue(appLaunchProfileConfigFileExists()) - XCTAssertNotNil(sentry_appLaunchProfileConfiguration()) + XCTAssertNotNil(sentry_persistedLaunchProfileConfigurationOptions()) _sentry_nondeduplicated_startLaunchProfile() @@ -230,11 +230,11 @@ class SentryAppLaunchProfilingMalformedConfigFileTests: XCTestCase { // Missing: kSentryLaunchProfileConfigKeyTracesSampleRate ] - let configURL = launchProfileConfigFileURL() + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) try (configDict as NSDictionary).write(to: configURL) XCTAssertTrue(appLaunchProfileConfigFileExists()) - XCTAssertNotNil(sentry_appLaunchProfileConfiguration()) + XCTAssertNotNil(sentry_persistedLaunchProfileConfigurationOptions()) _sentry_nondeduplicated_startLaunchProfile() diff --git a/Tests/SentryProfilerTests/SentryContinuousProfilerTests.swift b/Tests/SentryProfilerTests/SentryContinuousProfilerTests.swift index bdff1506883..f840ee452a9 100644 --- a/Tests/SentryProfilerTests/SentryContinuousProfilerTests.swift +++ b/Tests/SentryProfilerTests/SentryContinuousProfilerTests.swift @@ -5,6 +5,7 @@ import XCTest #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) +@available(*, deprecated, message: "This is only marked as deprecated because profilesSampleRate is marked as deprecated. Once that is removed this can be removed.") final class SentryContinuousProfilerTests: XCTestCase { private var fixture: SentryProfileTestFixture! @@ -156,23 +157,40 @@ final class SentryContinuousProfilerTests: XCTestCase { XCTAssertEqual(2, self.fixture.client?.captureEnvelopeInvocations.count) } - func testChunkSerializationAfterBufferInterval() throws { + func testChunkSerializationExecutesOnBackgroundThread() throws { SentryContinuousProfiler.start() XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - // Advance time by the buffer interval to trigger chunk serialization + // Prevent background serialization from executing automatically + fixture.dispatchQueueWrapper.dispatchAsyncExecutesBlock = false + + // Memoize how many dispatch asyncs were called during system setup; we'll expect one more for the serialization after simulating the timer elapse below where the serialization should take place + let currentAsyncDispatches = fixture.dispatchQueueWrapper.dispatchAsyncCalled + + // Trigger chunk creation by advancing time and firing timer fixture.currentDateProvider.advanceBy(interval: 60) try fixture.timeoutTimerFactory.check() - // Check that a chunk was serialized and sent - let envelope = try XCTUnwrap(self.fixture.client?.captureEnvelopeInvocations.last) + // Validate that no envelope was captured yet (serialization hasn't completed) + XCTAssertTrue(fixture.client?.captureEnvelopeInvocations.isEmpty ?? true) + + // Validate that background work was queued (serialization will be performed on background thread) + XCTAssertEqual(fixture.dispatchQueueWrapper.dispatchAsyncCalled, currentAsyncDispatches + 1) + + // Execute the background serialization work + fixture.dispatchQueueWrapper.dispatchAsyncExecutesBlock = true + fixture.dispatchQueueWrapper.invokeLastDispatchAsync() + + // Validate that background work completed: + // - Envelope was captured with profile chunk + let envelope = try XCTUnwrap(fixture.client?.captureEnvelopeInvocations.last) let profileItem = try XCTUnwrap(envelope.items.first) XCTAssertEqual("profile_chunk", profileItem.header.type) - // Ensure the profiler is still running + // Profiler should still be running after chunk serialization XCTAssert(SentryContinuousProfiler.isCurrentlyProfiling()) - // Stop the profiler + // Clean up SentryContinuousProfiler.stop() try assertContinuousProfileStoppage() } @@ -206,6 +224,7 @@ final class SentryContinuousProfilerTests: XCTestCase { } } +@available(*, deprecated, message: "This is only marked as deprecated because profilesSampleRate is marked as deprecated. Once that is removed this can be removed.") private extension SentryContinuousProfilerTests { func addMockSamples(mockAddresses: [NSNumber]) throws { let mockThreadMetadata = SentryProfileTestFixture.ThreadMetadata(id: 1, priority: 2, name: "main") @@ -258,7 +277,7 @@ private extension SentryContinuousProfilerTests { let profileItem = try XCTUnwrap(envelope.items.first) XCTAssertEqual("profile_chunk", profileItem.header.type) XCTAssertEqual("cocoa", profileItem.header.platform) - let data = profileItem.data + let data = try XCTUnwrap(profileItem.data) let profile = try XCTUnwrap(try JSONSerialization.jsonObject(with: data) as? [String: Any]) XCTAssertEqual(try XCTUnwrap(profile["version"] as? String), "2") @@ -337,8 +356,10 @@ private extension SentryContinuousProfilerTests { try assertMetricValue(measurements: measurements, key: kSentryMetricProfilerSerializationKeyMemoryFootprint, expectedValue: fixture.mockMetrics.memoryFootprint, expectedUnits: kSentryMetricProfilerSerializationUnitBytes, chunkStartTime: chunkStartTime, chunkEndTime: chunkEndTime, readingsPerBatch: expectedReadingsPerBatch) + #if arch(arm) || arch(arm64) // we wind up with one less energy reading for the first chunk's metric sample. since we must use the difference between readings to get actual values, the first one is only the baseline reading. try assertMetricValue(measurements: measurements, key: kSentryMetricProfilerSerializationKeyCPUEnergyUsage, expectedValue: fixture.mockMetrics.cpuEnergyUsage, expectedUnits: kSentryMetricProfilerSerializationUnitNanoJoules, chunkStartTime: chunkStartTime, chunkEndTime: chunkEndTime, readingsPerBatch: expectedReadingsPerBatch, expectOneLessEnergyReading: countMetricsReadingAtProfileStart) + #endif // arch(arm) || arch(arm64) #if !os(macOS) try assertMetricEntries(measurements: measurements, key: kSentryProfilerSerializationKeySlowFrameRenders, expectedEntries: fixture.expectedContinuousProfileSlowFrames, chunkStartTime: chunkStartTime, chunkEndTime: chunkEndTime) diff --git a/Tests/SentryProfilerTests/SentryNSProcessInfoWrapperTests.swift b/Tests/SentryProfilerTests/SentryNSProcessInfoWrapperTests.swift index 8159280745c..414abb15445 100644 --- a/Tests/SentryProfilerTests/SentryNSProcessInfoWrapperTests.swift +++ b/Tests/SentryProfilerTests/SentryNSProcessInfoWrapperTests.swift @@ -1,12 +1,13 @@ +@_spi(Private) @testable import SentryTestUtils import XCTest class SentryNSProcessInfoWrapperTests: XCTestCase { private struct Fixture { - lazy var processInfoWrapper = SentryNSProcessInfoWrapper() + lazy var processInfoWrapper = MockSentryProcessInfo() } lazy private var fixture = Fixture() func testProcessorCount() { - XCTAssert((0...UInt.max).contains(fixture.processInfoWrapper.processorCount)) + XCTAssert((0...Int.max).contains(fixture.processInfoWrapper.processorCount)) } } diff --git a/Tests/SentryProfilerTests/SentryNSTimerFactoryTest.swift b/Tests/SentryProfilerTests/SentryNSTimerFactoryTest.swift index 987dbdec424..90e9bd04adb 100644 --- a/Tests/SentryProfilerTests/SentryNSTimerFactoryTest.swift +++ b/Tests/SentryProfilerTests/SentryNSTimerFactoryTest.swift @@ -1,3 +1,4 @@ +@_spi(Private) @testable import Sentry import XCTest class SentryNSTimerFactoryTests: XCTestCase { diff --git a/Tests/SentryProfilerTests/SentryProfileTestFixture.swift b/Tests/SentryProfilerTests/SentryProfileTestFixture.swift index 9a83d66d9e5..aa3ae6a20aa 100644 --- a/Tests/SentryProfilerTests/SentryProfileTestFixture.swift +++ b/Tests/SentryProfilerTests/SentryProfileTestFixture.swift @@ -25,7 +25,7 @@ class SentryProfileTestFixture { let fixedRandomValue = 0.5 let systemWrapper = TestSentrySystemWrapper() - let processInfoWrapper = TestSentryNSProcessInfoWrapper() + let processInfoWrapper = MockSentryProcessInfo() let dispatchFactory = TestDispatchFactory() var metricTimerFactory: TestDispatchSourceWrapper? var timeoutTimerFactory: TestSentryNSTimerFactory @@ -39,6 +39,7 @@ class SentryProfileTestFixture { lazy var framesTracker = TestFramesTracker(displayLinkWrapper: displayLinkWrapper, dateProvider: currentDateProvider, dispatchQueueWrapper: dispatchQueueWrapper, notificationCenter: notificationCenter, keepDelayedFramesDuration: 0) #endif // !os(macOS) + @available(*, deprecated, message: "This is only marked as deprecated because profilesSampleRate is marked as deprecated. Once that is removed this can be removed.") init() { SentryDependencyContainer.sharedInstance().dispatchQueueWrapper = dispatchQueueWrapper SentryDependencyContainer.sharedInstance().dateProvider = currentDateProvider @@ -78,7 +79,7 @@ class SentryProfileTestFixture { client = TestClient(options: options) hub = SentryHub(client: client, andScope: scope) hub.bindClient(client) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) options.profilesSampleRate = 1.0 options.tracesSampleRate = 1.0 diff --git a/Tests/SentryProfilerTests/SentryProfileTimeseriesTests.m b/Tests/SentryProfilerTests/SentryProfileTimeseriesTests.m new file mode 100644 index 00000000000..b1ea01502c8 --- /dev/null +++ b/Tests/SentryProfilerTests/SentryProfileTimeseriesTests.m @@ -0,0 +1,287 @@ +#import "SentryProfileTimeseries.h" +#import + +#if SENTRY_UIKIT_AVAILABLE && SENTRY_TARGET_PROFILING_SUPPORTED + +@interface SentryProfileTimeseriesTests : XCTestCase + +@end + +@implementation SentryProfileTimeseriesTests { + uint64_t startSystemTime; + uint64_t endSystemTime; +} + +- (void)setUp +{ + [super setUp]; + startSystemTime = 1000000000; // 1 second in nanoseconds + endSystemTime = 3000000000; // 3 seconds in nanoseconds +} + +# pragma mark - sentry_sliceTraceProfileGPUData Tests + +- (void)testSliceTraceProfileGPUData_WithValueKey_ReturnsCorrectEntries +{ + // -- Arrange -- + SentryFrameInfoTimeSeries *frameInfo = @[ + @{ + @"timestamp" : @(startSystemTime + 500000000), // 1.5s + @"value" : @(60.0) + }, + @{ + @"timestamp" : @(startSystemTime + 1000000000), // 2s + @"value" : @(30.0) + }, + @{ + @"timestamp" : @(startSystemTime + 1500000000), // 2.5s + @"value" : @(120.0) + } + ]; + + // -- Act -- + NSArray *result + = sentry_sliceTraceProfileGPUData(frameInfo, startSystemTime, endSystemTime, NO); + + // -- Assert -- + XCTAssertEqual(result.count, 3); + + XCTAssertEqualObjects(result[0][@"elapsed_since_start_ns"], @"500000000"); + XCTAssertEqualObjects(result[0][@"value"], @(60.0)); + + XCTAssertEqualObjects(result[1][@"elapsed_since_start_ns"], @"1000000000"); + XCTAssertEqualObjects(result[1][@"value"], @(30.0)); + + XCTAssertEqualObjects(result[2][@"elapsed_since_start_ns"], @"1500000000"); + XCTAssertEqualObjects(result[2][@"value"], @(120.0)); +} + +- (void)testSliceTraceProfileGPUData_WithNSNullValue_ExcludesNSNull +{ + // -- Arrange -- + SentryFrameInfoTimeSeries *frameInfo = @[ + @{ + @"timestamp" : @(startSystemTime + 500000000), // 1.5s + @"value" : [NSNull null] // NSNull represents nil in collections + }, + @{ + @"timestamp" : @(startSystemTime + 1000000000), // 2s + @"value" : @(30.0) // Valid value for comparison + } + ]; + + // -- Act -- + NSArray *result + = sentry_sliceTraceProfileGPUData(frameInfo, startSystemTime, endSystemTime, NO); + + // -- Assert -- + XCTAssertEqual(result.count, 2); + + // Verify first entry (with nil value) - NSNull is excluded from the value key + XCTAssertEqualObjects(result[0][@"elapsed_since_start_ns"], @"500000000"); + XCTAssertNil(result[0][@"value"]); + + // Verify second entry (with valid value) + XCTAssertEqualObjects(result[1][@"elapsed_since_start_ns"], @"1000000000"); + XCTAssertEqualObjects(result[1][@"value"], @(30.0)); +} + +- (void)testSliceTraceProfileGPUData_WithMissingValueKey_ExcludesValueKey +{ + // -- Arrange -- + SentryFrameInfoTimeSeries *frameInfo = @[ + @{ + @"timestamp" : @(startSystemTime + 500000000) // 1.5s + // No 'value' key at all + }, + @{ + @"timestamp" : @(startSystemTime + 1000000000), // 2s + @"value" : @(30.0) // Valid value for comparison + } + ]; + + // -- Act -- + NSArray *result + = sentry_sliceTraceProfileGPUData(frameInfo, startSystemTime, endSystemTime, NO); + + // -- Assert -- + XCTAssertEqual(result.count, 2); + + // Verify first entry (missing value key) - should not include value key + XCTAssertEqualObjects(result[0][@"elapsed_since_start_ns"], @"500000000"); + XCTAssertNil(result[0][@"value"]); + + // Verify second entry (with valid value) + XCTAssertEqualObjects(result[1][@"elapsed_since_start_ns"], @"1000000000"); + XCTAssertEqualObjects(result[1][@"value"], @(30.0)); +} + +- (void)testSliceTraceProfileGPUData_EmptyArray_ReturnsEmptyArray +{ + // -- Arrange -- + SentryFrameInfoTimeSeries *frameInfo = @[]; + + // -- Act -- + NSArray *result + = sentry_sliceTraceProfileGPUData(frameInfo, startSystemTime, endSystemTime, NO); + + // -- Assert -- + XCTAssertEqual(result.count, 0); +} + +- (void)testSliceTraceProfileGPUData_TimestampsOutsideRange_FiltersCorrectly +{ + // -- Arrange -- + SentryFrameInfoTimeSeries *frameInfo = @[ + @{ + @"timestamp" : @(startSystemTime - 500000000), // Before start + @"value" : @(60.0) + }, + @{ + @"timestamp" : @(startSystemTime + 500000000), // Within range + @"value" : @(30.0) + }, + @{ + @"timestamp" : @(endSystemTime + 500000000), // After end + @"value" : @(120.0) + } + ]; + + // -- Act -- + NSArray *result + = sentry_sliceTraceProfileGPUData(frameInfo, startSystemTime, endSystemTime, NO); + + // -- Assert -- + // Should only include the middle entry that's within the time range + XCTAssertEqual(result.count, 1); + XCTAssertEqualObjects(result[0][@"elapsed_since_start_ns"], @"500000000"); + XCTAssertEqualObjects(result[0][@"value"], @(30.0)); +} + +- (void)testSliceTraceProfileGPUData_UseMostRecentRecording_WithEmptyResult +{ + // -- Arrange -- + SentryFrameInfoTimeSeries *frameInfo = @[ + @{ + @"timestamp" : @(startSystemTime - 500000000), // Before start + @"value" : @(60.0) + }, + @{ + @"timestamp" : @(endSystemTime + 500000000), // After end + @"value" : @(120.0) + } + ]; + + // -- Act -- + NSArray *result + = sentry_sliceTraceProfileGPUData(frameInfo, startSystemTime, endSystemTime, YES); + + // -- Assert -- + // Should include the most recent predecessor value + XCTAssertEqual(result.count, 1); + XCTAssertEqualObjects(result[0][@"elapsed_since_start_ns"], @"0"); + XCTAssertEqualObjects(result[0][@"value"], @(60.0)); +} + +- (void)testSliceTraceProfileGPUData_UseMostRecentRecording_WithExistingResults +{ + // -- Arrange -- + SentryFrameInfoTimeSeries *frameInfo = @[ + @{ + @"timestamp" : @(startSystemTime - 500000000), // Before start + @"value" : @(60.0) + }, + @{ + @"timestamp" : @(startSystemTime + 500000000), // Within range + @"value" : @(30.0) + } + ]; + + // -- Act -- + NSArray *result + = sentry_sliceTraceProfileGPUData(frameInfo, startSystemTime, endSystemTime, YES); + + // -- Assert -- + // Should not add the predecessor value since we already have results + XCTAssertEqual(result.count, 1); + XCTAssertEqualObjects(result[0][@"elapsed_since_start_ns"], @"500000000"); + XCTAssertEqualObjects(result[0][@"value"], @(30.0)); +} + +- (void)testSliceTraceProfileGPUData_UseMostRecentRecording_WithNSNullPredecessor +{ + // -- Arrange -- + SentryFrameInfoTimeSeries *frameInfo = @[ + @{ + @"timestamp" : @(startSystemTime - 500000000), // Before start + @"value" : [NSNull null] // NSNull value + }, + @{ + @"timestamp" : @(endSystemTime + 500000000), // After end + @"value" : @(120.0) + } + ]; + + // -- Act -- + NSArray *result + = sentry_sliceTraceProfileGPUData(frameInfo, startSystemTime, endSystemTime, YES); + + // -- Assert -- + // Should not add any entry since NSNull is treated as no data + XCTAssertEqual(result.count, 0); +} + +- (void)testSliceTraceProfileGPUData_UseMostRecentRecording_WithTrueNilPredecessor +{ + // -- Arrange -- + SentryFrameInfoTimeSeries *frameInfo = @[ + @{ + @"timestamp" : @(startSystemTime - 500000000) // Before start, no value key + }, + @{ + @"timestamp" : @(endSystemTime + 500000000), // After end + @"value" : @(120.0) + } + ]; + + // -- Act -- + NSArray *result + = sentry_sliceTraceProfileGPUData(frameInfo, startSystemTime, endSystemTime, YES); + + // -- Assert -- + // Should not add any entry since predecessor has no value key (truly nil) + XCTAssertEqual(result.count, 0); +} + +- (void)testSliceTraceProfileGPUData_BoundaryTimestamps_IncludesCorrectly +{ + // -- Arrange -- + SentryFrameInfoTimeSeries *frameInfo = @[ + @{ + @"timestamp" : @(startSystemTime), // Exactly at start + @"value" : @(60.0) + }, + @{ + @"timestamp" : @(endSystemTime), // Exactly at end + @"value" : @(30.0) + } + ]; + + // -- Act -- + NSArray *result + = sentry_sliceTraceProfileGPUData(frameInfo, startSystemTime, endSystemTime, NO); + + // -- Assert -- + // Both boundary timestamps should be included + XCTAssertEqual(result.count, 2); + + XCTAssertEqualObjects(result[0][@"elapsed_since_start_ns"], @"0"); + XCTAssertEqualObjects(result[0][@"value"], @(60.0)); + + XCTAssertEqualObjects(result[1][@"elapsed_since_start_ns"], @"2000000000"); + XCTAssertEqualObjects(result[1][@"value"], @(30.0)); +} + +@end + +#endif // SENTRY_TARGET_PROFILING_SUPPORTED diff --git a/Tests/SentryProfilerTests/SentryProfilingPublicAPITests.swift b/Tests/SentryProfilerTests/SentryProfilingPublicAPITests.swift index 86a8b2cec72..0552de089f9 100644 --- a/Tests/SentryProfilerTests/SentryProfilingPublicAPITests.swift +++ b/Tests/SentryProfilerTests/SentryProfilingPublicAPITests.swift @@ -1,4 +1,4 @@ -@testable import Sentry +@_spi(Private) @testable import Sentry @_spi(Private) import SentryTestUtils import XCTest @@ -7,6 +7,7 @@ import XCTest // swiftlint:disable file_length class SentryProfilingPublicAPITests: XCTestCase { private class Fixture { + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") let options: Options = { let options = Options.noIntegrations() options.dsn = TestConstants.dsnAsString(username: "SentrySDKTests") @@ -35,24 +36,32 @@ class SentryProfilingPublicAPITests: XCTestCase { let currentDate = TestCurrentDateProvider() lazy var timerFactory = TestSentryNSTimerFactory(currentDateProvider: currentDate) + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") lazy var client = TestClient(options: options)! + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") lazy var hub = SentryHub(client: client, andScope: scope) } private let fixture = Fixture() + override class func setUp() { + super.setUp() + SentrySDKLogSupport.configure(true, diagnosticLevel: .debug) + } + override func setUp() { super.setUp() SentryDependencyContainer.sharedInstance().timerFactory = fixture.timerFactory SentryDependencyContainer.sharedInstance().dateProvider = fixture.currentDate } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") override func tearDown() { super.tearDown() givenSdkWithHubButNoClient() - if let autoSessionTracking = SentrySDK.currentHub().installedIntegrations().first(where: { it in + if let autoSessionTracking = SentrySDKInternal.currentHub().installedIntegrations().first(where: { it in it is SentryAutoSessionTrackingIntegration }) as? SentryAutoSessionTrackingIntegration { autoSessionTracking.stop() @@ -63,6 +72,7 @@ class SentryProfilingPublicAPITests: XCTestCase { } // MARK: transaction profiling +@available(*, deprecated, message: "Transaction profiling is deprecated") extension SentryProfilingPublicAPITests { func testSentryOptionsReportsProfilingCorrelatedToTraces_NonnilSampleRate() { // Arrange @@ -98,6 +108,7 @@ extension SentryProfilingPublicAPITests { } // MARK: continuous profiling v1 +@available(*, deprecated, message: "Continuous profiling v1 is deprecated") extension SentryProfilingPublicAPITests { func testSentryOptionsReportsContinuousProfilingEnabled() { // Arrange @@ -203,6 +214,7 @@ extension SentryProfilingPublicAPITests { } // MARK: continuous profiling v2 +@available(*, deprecated, message: "This is only deprecated because profilesSampleRate is deprecated. Once that is removed this attribute can be removed.") extension SentryProfilingPublicAPITests { func testSentryOptionsReportsContinuousProfilingV2Enabled() { // Arrange @@ -660,15 +672,17 @@ extension SentryProfilingPublicAPITests { } private extension SentryProfilingPublicAPITests { + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func givenSdkWithHub() { - SentrySDK.setCurrentHub(fixture.hub) - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setCurrentHub(fixture.hub) + SentrySDKInternal.setStart(with: fixture.options) sentry_sdkInitProfilerTasks(fixture.options, fixture.hub) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func givenSdkWithHubButNoClient() { - SentrySDK.setCurrentHub(SentryHub(client: nil, andScope: nil)) - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setCurrentHub(SentryHub(client: nil, andScope: nil)) + SentrySDKInternal.setStart(with: fixture.options) } func stopProfiler() throws { diff --git a/Tests/SentryProfilerTests/SentryProfilingSwiftHelpersTests.m b/Tests/SentryProfilerTests/SentryProfilingSwiftHelpersTests.m new file mode 100644 index 00000000000..7bbdb51d252 --- /dev/null +++ b/Tests/SentryProfilerTests/SentryProfilingSwiftHelpersTests.m @@ -0,0 +1,148 @@ +@import XCTest; +@import Sentry; +@import SentryTestUtilsDynamic; +#import "SentryOptions+Private.h" +#import "SentryProfilingSwiftHelpers.h" + +@interface SentryProfilingSwiftHelpersTests : XCTestCase +@end + +@implementation SentryProfilingSwiftHelpersTests + +#if SENTRY_TARGET_PROFILING_SUPPORTED + +- (void)testIsContinuousProfilingEnabled +{ + SentryOptions *options = [[SentryOptions alloc] init]; + options.dsn = @"https://username:password@app.getsentry.com/12345"; + SentryClient *client = [[SentryClient alloc] initWithOptions:options]; + XCTAssertEqual( + [client.options isContinuousProfilingEnabled], sentry_isContinuousProfilingEnabled(client)); +} + +- (void)testIsContinuousProfilingV2Enabled +{ + SentryOptions *options = [[SentryOptions alloc] init]; + options.dsn = @"https://username:password@app.getsentry.com/12345"; + options.profiling = [[SentryProfileOptions alloc] init]; + SentryClient *client = [[SentryClient alloc] initWithOptions:options]; + XCTAssertEqual([client.options isContinuousProfilingV2Enabled], + sentry_isContinuousProfilingV2Enabled(client)); +} + +- (void)testIsProfilingCorrelatedToTraces +{ + SentryOptions *options = [[SentryOptions alloc] init]; + options.dsn = @"https://username:password@app.getsentry.com/12345"; + options.profiling = [[SentryProfileOptions alloc] init]; + options.profiling.lifecycle = SentryProfileLifecycleTrace; + SentryClient *client = [[SentryClient alloc] initWithOptions:options]; + XCTAssertEqual([client.options isProfilingCorrelatedToTraces], + sentry_isProfilingCorrelatedToTraces(client)); +} + +- (void)testGetProfiling +{ + SentryOptions *options = [[SentryOptions alloc] init]; + options.dsn = @"https://username:password@app.getsentry.com/12345"; + options.profiling = [[SentryProfileOptions alloc] init]; + SentryClient *client = [[SentryClient alloc] initWithOptions:options]; + XCTAssertEqual(client.options.profiling, sentry_getProfiling(client)); +} + +- (void)testStringFromSentryID +{ + SentryId *sentryId = [[SentryId alloc] init]; + XCTAssertEqualObjects(sentryId.sentryIdString, sentry_stringFromSentryID(sentryId)); +} + +- (void)testGetSentryId +{ + XCTAssertNotNil(sentry_getSentryId()); +} + +- (void)testGetSentryProfileOptions +{ + XCTAssertNotNil(sentry_getSentryProfileOptions()); +} + +- (void)testIsTraceLifecycle +{ + SentryProfileOptions *options = [[SentryProfileOptions alloc] init]; + options.lifecycle = SentryProfileLifecycleTrace; + XCTAssertTrue(sentry_isTraceLifecycle(options)); + + options.lifecycle = SentryProfileLifecycleManual; + XCTAssertFalse(sentry_isTraceLifecycle(options)); +} + +- (void)testSessionSampleRate +{ + SentryProfileOptions *options = [[SentryProfileOptions alloc] init]; + options.sessionSampleRate = 0.2; + XCTAssertEqual(options.sessionSampleRate, sentry_sessionSampleRate(options)); +} + +- (void)testProfileAppStarts +{ + SentryProfileOptions *options = [[SentryProfileOptions alloc] init]; + options.profileAppStarts = true; + XCTAssertTrue(sentry_profileAppStarts(options)); + + options.profileAppStarts = false; + XCTAssertFalse(sentry_profileAppStarts(options)); +} + +- (void)testIsManual +{ + SentryProfileOptions *options = [[SentryProfileOptions alloc] init]; + options.profileAppStarts = true; + XCTAssertTrue(sentry_profileAppStarts(options)); + + options.profileAppStarts = false; + XCTAssertFalse(sentry_profileAppStarts(options)); +} + +- (void)testGetParentSpanID +{ + SentryTransactionContext *context = + [[SentryTransactionContext alloc] initWithTraceId:[[SentryId alloc] init] + spanId:[[SentrySpanId alloc] init] + parentId:[[SentrySpanId alloc] init] + operation:@"" + sampled:kSentrySampleDecisionNo]; + XCTAssertEqual(context.parentSpanId, sentry_getParentSpanID(context)); +} + +- (void)testGetTraceID +{ + SentryTransactionContext *context = + [[SentryTransactionContext alloc] initWithTraceId:[[SentryId alloc] init] + spanId:[[SentrySpanId alloc] init] + parentId:[[SentrySpanId alloc] init] + operation:@"" + sampled:kSentrySampleDecisionNo]; + XCTAssertEqual(context.traceId, sentry_getTraceID(context)); +} + +- (void)testIsNotSampled +{ + SentryTransactionContext *context = + [[SentryTransactionContext alloc] initWithTraceId:[[SentryId alloc] init] + spanId:[[SentrySpanId alloc] init] + parentId:[[SentrySpanId alloc] init] + operation:@"" + sampled:kSentrySampleDecisionNo]; + XCTAssertTrue(sentry_isNotSampled(context)); + + context = [[SentryTransactionContext alloc] initWithTraceId:[[SentryId alloc] init] + spanId:[[SentrySpanId alloc] init] + parentId:[[SentrySpanId alloc] init] + operation:@"" + sampled:kSentrySampleDecisionYes]; + XCTAssertFalse(sentry_isNotSampled(context)); +} + +#endif + +@end diff --git a/Tests/SentryProfilerTests/SentrySystemWrapperTests.swift b/Tests/SentryProfilerTests/SentrySystemWrapperTests.swift index 7c73f69695e..891802c12fd 100644 --- a/Tests/SentryProfilerTests/SentrySystemWrapperTests.swift +++ b/Tests/SentryProfilerTests/SentrySystemWrapperTests.swift @@ -1,8 +1,9 @@ import XCTest +#if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) class SentrySystemWrapperTests: XCTestCase { private struct Fixture { - lazy var systemWrapper = SentrySystemWrapper() + lazy var systemWrapper = SentrySystemWrapper(processorCount: 4) } lazy private var fixture = Fixture() @@ -20,3 +21,4 @@ class SentrySystemWrapperTests: XCTestCase { XCTAssert((0...UINT64_MAX).contains(memoryFootprint)) } } +#endif // os(iOS) || os(macOS) || targetEnvironment(macCatalyst) diff --git a/Tests/SentryProfilerTests/SentryTraceProfilerTests.swift b/Tests/SentryProfilerTests/SentryTraceProfilerTests.swift index 843b0256685..66a02b8411c 100644 --- a/Tests/SentryProfilerTests/SentryTraceProfilerTests.swift +++ b/Tests/SentryProfilerTests/SentryTraceProfilerTests.swift @@ -4,6 +4,7 @@ import _SentryPrivate import XCTest #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) +@available(*, deprecated, message: "This is only marked deprecated because SentryProfileTestFixture is marked as deprecated.") class SentryTraceProfilerTests: XCTestCase { private var fixture: SentryProfileTestFixture! @@ -335,7 +336,7 @@ class SentryTraceProfilerTests: XCTestCase { func testProfilerCleanedUpAfterTransactionDiscarded_WaitForAllChildren_StartTimeModified() throws { XCTAssertEqual(SentryTraceProfiler.currentProfiledTracers(), UInt(0)) let appStartMeasurement = fixture.getAppStartMeasurement(type: .cold) - SentrySDK.setAppStartMeasurement(appStartMeasurement) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) fixture.currentDateProvider.advance(by: 1) func performTransaction() throws { let sut = try fixture.newTransaction(testingAppLaunchSpans: true, automaticTransaction: true) @@ -360,6 +361,7 @@ class SentryTraceProfilerTests: XCTestCase { #endif // !os(macOS) } +@available(*, deprecated, message: "This is only marked deprecated because SentryProfileTestFixture is marked as deprecated.") private extension SentryTraceProfilerTests { func getLatestProfileData() throws -> Data { let envelope = try XCTUnwrap(self.fixture.client?.captureEventWithScopeInvocations.last) @@ -368,7 +370,7 @@ private extension SentryTraceProfilerTests { let profileItem = try XCTUnwrap(envelope.additionalEnvelopeItems.first) XCTAssertEqual("profile", profileItem.header.type) - return profileItem.data + return try XCTUnwrap(profileItem.data) } func getLatestTransaction() throws -> Transaction { @@ -400,7 +402,7 @@ private extension SentryTraceProfilerTests { if let uikitParameters = uikitParameters { testingAppLaunchSpans = true let appStartMeasurement = fixture.getAppStartMeasurement(type: uikitParameters.launchType, preWarmed: uikitParameters.prewarmed) - SentrySDK.setAppStartMeasurement(appStartMeasurement) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) } #endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) @@ -434,9 +436,11 @@ private extension SentryTraceProfilerTests { try assertMetricValue(measurements: measurements, key: kSentryMetricProfilerSerializationKeyMemoryFootprint, numberOfReadings: expectedUsageReadings, expectedValue: fixture.mockMetrics.memoryFootprint, transaction: transaction, expectedUnits: kSentryMetricProfilerSerializationUnitBytes) + #if arch(arm) || arch(arm64) // we wind up with one less energy reading for the first concurrent span's metric sample. since we must use the difference between readings to get actual values, the first one is only the baseline reading. let expectedEnergyReadings = oneLessEnergyReading ? expectedUsageReadings - 1 : expectedUsageReadings try assertMetricValue(measurements: measurements, key: kSentryMetricProfilerSerializationKeyCPUEnergyUsage, numberOfReadings: expectedEnergyReadings, expectedValue: fixture.mockMetrics.cpuEnergyUsage, transaction: transaction, expectedUnits: kSentryMetricProfilerSerializationUnitNanoJoules) + #endif // arch(arm) || arch(arm64) #if !os(macOS) try assertMetricEntries(measurements: measurements, key: kSentryProfilerSerializationKeySlowFrameRenders, expectedEntries: fixture.expectedTraceProfileSlowFrames, transaction: transaction) @@ -606,7 +610,7 @@ private extension SentryTraceProfilerTests { var startTimestampString = sentry_toIso8601String(latestTransactionTimestamp) #if !os(macOS) if appStartProfile { - let runtimeInitTimestamp = try XCTUnwrap(SentrySDK.getAppStartMeasurement()?.runtimeInitTimestamp) + let runtimeInitTimestamp = try XCTUnwrap(SentrySDKInternal.getAppStartMeasurement()?.runtimeInitTimestamp) startTimestampString = sentry_toIso8601String(runtimeInitTimestamp) } #endif // !os(macOS) diff --git a/Tests/SentrySwiftUITests/SentryTests-Bridging-Header.h b/Tests/SentrySwiftUITests/SentryTests-Bridging-Header.h index 4da0c045034..b6b4af873a2 100644 --- a/Tests/SentrySwiftUITests/SentryTests-Bridging-Header.h +++ b/Tests/SentrySwiftUITests/SentryTests-Bridging-Header.h @@ -1,7 +1,5 @@ #import "SentryHub+Private.h" #import "SentryPerformanceTracker.h" -#import "SentrySDK+Private.h" -#import "SentrySDK+Tests.h" #import "SentryTracer.h" #import "SentryUIViewControllerPerformanceTracker.h" @@ -14,7 +12,3 @@ @interface SentryUIViewControllerPerformanceTracker () @property (nullable, nonatomic, weak) SentryTimeToDisplayTracker *currentTTDTracker; @end - -@interface SentrySDK () -+ (void)setStartOptions:(nullable SentryOptions *)options; -@end diff --git a/Tests/SentrySwiftUITests/SentryTraceViewModelTest.swift b/Tests/SentrySwiftUITests/SentryTraceViewModelTest.swift index 24649cb3e9d..a95be5c3dad 100644 --- a/Tests/SentrySwiftUITests/SentryTraceViewModelTest.swift +++ b/Tests/SentrySwiftUITests/SentryTraceViewModelTest.swift @@ -13,7 +13,7 @@ class SentryTraceViewModelTestCase: XCTestCase { func testCreateTransaction() throws { let option = Options() - SentrySDK.setCurrentHub(SentryHub(client: SentryClient(options: option), andScope: nil)) + SentrySDKInternal.setCurrentHub(SentryHub(client: SentryClient(options: option), andScope: nil)) let viewModel = SentryTraceViewModel(name: "TestView", nameSource: .component, waitForFullDisplay: false) let spanId = viewModel.startSpan() @@ -27,7 +27,7 @@ class SentryTraceViewModelTestCase: XCTestCase { func testRootTransactionStarted() throws { let option = Options() - SentrySDK.setCurrentHub(SentryHub(client: SentryClient(options: option), andScope: nil)) + SentrySDKInternal.setCurrentHub(SentryHub(client: SentryClient(options: option), andScope: nil)) let viewModel = SentryTraceViewModel(name: "RootTransactionTest", nameSource: .component, waitForFullDisplay: true) _ = viewModel.startSpan() @@ -40,7 +40,7 @@ class SentryTraceViewModelTestCase: XCTestCase { func testNoRootTransactionForCurrentTransactionRunning() throws { let option = Options() - SentrySDK.setCurrentHub(SentryHub(client: SentryClient(options: option), andScope: nil)) + SentrySDKInternal.setCurrentHub(SentryHub(client: SentryClient(options: option), andScope: nil)) let testSpan = SentryPerformanceTracker.shared.startSpan(withName: "Test Root", nameSource: .component, operation: "Testing", origin: "Test") SentryPerformanceTracker.shared.pushActiveSpan(testSpan) @@ -58,7 +58,7 @@ class SentryTraceViewModelTestCase: XCTestCase { func testNoTransactionWhenViewAppeared() { let option = Options() - SentrySDK.setCurrentHub(SentryHub(client: SentryClient(options: option), andScope: nil)) + SentrySDKInternal.setCurrentHub(SentryHub(client: SentryClient(options: option), andScope: nil)) let viewModel = SentryTraceViewModel(name: "TestView", nameSource: .component, waitForFullDisplay: false) viewModel.viewDidAppear() @@ -69,7 +69,7 @@ class SentryTraceViewModelTestCase: XCTestCase { func testFinishSpan() throws { let option = Options() - SentrySDK.setCurrentHub(SentryHub(client: SentryClient(options: option), andScope: nil)) + SentrySDKInternal.setCurrentHub(SentryHub(client: SentryClient(options: option), andScope: nil)) let viewModel = SentryTraceViewModel(name: "FinishSpanTest", nameSource: .component, waitForFullDisplay: false) let spanId = try XCTUnwrap(viewModel.startSpan()) @@ -97,7 +97,7 @@ class SentryTraceViewModelTestCase: XCTestCase { func testUseWaitForFullDisplayFromOptions() throws { let option = Options() option.enableTimeToFullDisplayTracing = true - SentrySDK.setStart(option) + SentrySDKInternal.setStart(with: option) let viewModel = SentryTraceViewModel(name: "FinishSpanTest", nameSource: .component, waitForFullDisplay: nil) XCTAssertTrue(viewModel.waitForFullDisplay) @@ -106,7 +106,7 @@ class SentryTraceViewModelTestCase: XCTestCase { func testUseWaitForFullDisplayFromParameter() throws { let option = Options() option.enableTimeToFullDisplayTracing = true - SentrySDK.setStart(option) + SentrySDKInternal.setStart(with: option) let viewModel = SentryTraceViewModel(name: "FinishSpanTest", nameSource: .component, waitForFullDisplay: false) XCTAssertFalse(viewModel.waitForFullDisplay) diff --git a/Tests/SentryTests/Categories/SentryArrayTests.swift b/Tests/SentryTests/Categories/SentryArrayTests.swift new file mode 100644 index 00000000000..0a98fd94114 --- /dev/null +++ b/Tests/SentryTests/Categories/SentryArrayTests.swift @@ -0,0 +1,179 @@ +@testable import Sentry +import XCTest + +class SentryArrayTests: XCTestCase { + + func testSanitizeArray_emptyArray_shouldReturnEmptyArray() { + // Arrange + let array: [String] = [] + + // Act + let result = SentryArray.sanitizeArray(array) + + // Assert + XCTAssertEqual(result.count, 0) + } + + func testSanitizeArray_withStrings_shouldReturnSameStrings() throws { + // Arrange + let array = ["hello", "world", "test"] + + // Act + let result = SentryArray.sanitizeArray(array) + + // Assert + let stringArray = try XCTUnwrap(result as? [String]) + XCTAssertEqual(stringArray, ["hello", "world", "test"]) + } + + func testSanitizeArray_withNumbers_shouldReturnSameNumbers() throws { + // Arrange + let array = [NSNumber(value: 42), NSNumber(value: 3.14), NSNumber(value: true)] + + // Act + let result = SentryArray.sanitizeArray(array) + + // Assert + XCTAssertEqual(result.count, 3) + XCTAssertEqual(result[0] as? NSNumber, NSNumber(value: 42)) + XCTAssertEqual(result[1] as? NSNumber, NSNumber(value: 3.14)) + XCTAssertEqual(result[2] as? NSNumber, NSNumber(value: true)) + } + + func testSanitizeArray_withValidDictionaries_shouldReturnSanitizedDictionaries() throws { + // Arrange + let dict1: [String: Any] = ["key1": "value1", "key2": NSNumber(value: 123)] + let dict2: [String: Any] = ["key3": "value3"] + let array: [Any] = [dict1, dict2] + + // Act + let result = SentryArray.sanitizeArray(array) + + // Assert + XCTAssertEqual(result.count, 2) + let sanitizedDict1 = try XCTUnwrap(result[0] as? [String: Any]) + let sanitizedDict2 = try XCTUnwrap(result[1] as? [String: Any]) + XCTAssertEqual(sanitizedDict1["key1"] as? String, "value1") + XCTAssertEqual(sanitizedDict1["key2"] as? NSNumber, NSNumber(value: 123)) + XCTAssertEqual(sanitizedDict2["key3"] as? String, "value3") + } + + func testSanitizeArray_withInvalidDictionary_shouldSkipNilResult() throws { + // Arrange + // Create a dictionary-like object that will cause sentry_sanitize to return nil + let invalidDict = NotReallyADictionary() + let validDict: [String: Any] = ["key": "value"] + let array: [Any] = [invalidDict, validDict] + + // Act + let result = SentryArray.sanitizeArray(array) + + // Assert + // Should only contain the valid dictionary, invalid one should be skipped + XCTAssertEqual(result.count, 1) + let sanitizedDict = try XCTUnwrap(result[0] as? [String: Any]) + XCTAssertEqual(sanitizedDict["key"] as? String, "value") + } + + func testSanitizeArray_withNestedArrays_shouldRecursivelySanitize() throws { + // Arrange + let nestedArray: [Any] = ["nested1", NSNumber(value: 456)] + let array: [Any] = [nestedArray, "topLevel"] + + // Act + let result = SentryArray.sanitizeArray(array) + + // Assert + XCTAssertEqual(result.count, 2) + + let firstElement = try XCTUnwrap(result[0] as? [Any]) + XCTAssertEqual(firstElement[0] as? String, "nested1") + XCTAssertEqual(firstElement[1] as? NSNumber, NSNumber(value: 456)) + + XCTAssertEqual(result[1] as? String, "topLevel") + } + + func testSanitizeArray_withDates_shouldConvertToISO8601String() throws { + // Arrange + let date1 = Date(timeIntervalSince1970: 1_640_995_200) // 2022-01-01 00:00:00 UTC + let date2 = Date(timeIntervalSince1970: 0) // 1970-01-01 00:00:00 UTC + let array: [Any] = [date1, date2] + + // Act + let result = SentryArray.sanitizeArray(array) + + // Assert + XCTAssertEqual(result.count, 2) + // Verify the dates are converted to strings (ISO8601 format) + let dateString1 = try XCTUnwrap(result[0] as? String) + let dateString2 = try XCTUnwrap(result[1] as? String) + XCTAssertEqual(dateString1, "2022-01-01T00:00:00.000Z") + XCTAssertEqual(dateString2, "1970-01-01T00:00:00.000Z") + } + + func testSanitizeArray_withOtherObjects_shouldUseDescription() throws { + // Arrange + let customObject = CustomObject() + let array: [Any] = [customObject] + + // Act + let result = SentryArray.sanitizeArray(array) + + // Assert + XCTAssertEqual(result.count, 1) + let description = try XCTUnwrap(result[0] as? String) + XCTAssertEqual(description, "CustomObject description") + } + + func testSanitizeArray_withMixedTypes_shouldHandleAllTypes() throws { + // Arrange + let dict: [String: Any] = ["key": "value"] + let nestedArray: [Any] = ["nested"] + let date = Date(timeIntervalSince1970: 1_640_995_200) + let customObject = CustomObject() + let array: [Any] = [ + "string", + NSNumber(value: 42), + dict, + nestedArray, + date, + customObject + ] + + // Act + let result = SentryArray.sanitizeArray(array) + + // Assert + XCTAssertEqual(result.count, 6) + + // Verify each type is handled correctly + XCTAssertEqual(result[0] as? String, "string") + XCTAssertEqual(result[1] as? NSNumber, NSNumber(value: 42)) + XCTAssertNotNil(result[2] as? [String: Any]) + XCTAssertNotNil(result[3] as? [Any]) + + let dateString = try XCTUnwrap(result[4] as? String) + XCTAssertEqual(dateString, "2022-01-01T00:00:00.000Z") + + let objectDescription = try XCTUnwrap(result[5] as? String) + XCTAssertEqual(objectDescription, "CustomObject description") + } +} + +// Helper class that inherits from NSObject but is not a real NSDictionary +// This will cause sentry_sanitize to return nil when it checks isSubclassOfClass +private class NotReallyADictionary: NSObject { + override func isKind(of aClass: AnyClass) -> Bool { + if aClass == NSDictionary.self { + return true // Pretend to be a dictionary + } + return super.isKind(of: aClass) + } +} + +// Helper class for testing description fallback +private class CustomObject: NSObject { + override var description: String { + return "CustomObject description" + } +} diff --git a/Tests/SentryTests/Helper/EnvelopeComparison.swift b/Tests/SentryTests/Helper/EnvelopeComparison.swift new file mode 100644 index 00000000000..a3af852dbad --- /dev/null +++ b/Tests/SentryTests/Helper/EnvelopeComparison.swift @@ -0,0 +1,73 @@ +import XCTest + +extension XCTest { + func compareEnvelopes(_ expectedEnvelope: Data?, _ actualEnvelope: Data?, message: String) throws { + + enum EnvelopeData: Equatable { + case dictionary(NSDictionary) + case string(String) + } + + guard let expectedEnvelope, let actualEnvelope else { + XCTAssertEqual(expectedEnvelope, actualEnvelope, message) + return + } + + guard let unzippedExpected = sentry_unzippedData(expectedEnvelope), let unzippedActual = sentry_unzippedData(actualEnvelope) else { + XCTFail(message) + return + } + + let newline = Data("\n".utf8) + let expectedElements = unzippedExpected.backwardCompatibleSplit(separator: newline) + let actualElements = unzippedActual.backwardCompatibleSplit(separator: newline) + let expectedData = try expectedElements.map { data -> EnvelopeData in + if let json = try? JSONSerialization.jsonObject(with: data) as? NSDictionary { + return .dictionary(json) + } + let dataAsString = try XCTUnwrap(String(data: data, encoding: .utf8)) + return .string(dataAsString) + } + let actualData = try actualElements.map { data -> EnvelopeData in + if let json = try? JSONSerialization.jsonObject(with: data) as? NSDictionary { + return .dictionary(json) + } + let dataAsString = try XCTUnwrap(String(data: data, encoding: .utf8)) + return .string(dataAsString) + } + XCTAssertEqual(expectedData, actualData, message) + } +} + +import Foundation + +extension Data { + // Used to support iOS < 16.0 + func backwardCompatibleSplit(separator: Data) -> [Data] { + // When the `split` function is available all we need to do is call it. + if #available(iOS 16.0, tvOS 16.0, watchOS 16.0, macOS 13.0, *) { + return split(separator: separator) + } + + guard !separator.isEmpty else { return [self] } + + var parts: [Data] = [] + var searchRange: Range = startIndex..= separator.count && + self[self.count - separator.count.. SentryAppStateManager { SentryDependencyContainer.sharedInstance().sysctlWrapper = TestSysctl() return SentryAppStateManager( options: options, - crashWrapper: TestSentryCrashWrapper.sharedInstance(), + crashWrapper: TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo), fileManager: fileManager, dispatchQueueWrapper: TestSentryDispatchQueueWrapper(), notificationCenterWrapper: notificationCenterWrapper @@ -103,7 +108,7 @@ class SentryAppStateManagerTests: XCTestCase { sut.stop(withForce: true) XCTAssertEqual(sut.startCount, 0) - XCTAssertEqual(fixture.notificationCenterWrapper.removeObserverWithNameInvocations.count, 4) + XCTAssertEqual(fixture.notificationCenterWrapper.removeObserverWithNameAndObjectInvocations.count, 4) } func testUpdateAppState() { diff --git a/Tests/SentryTests/Helper/SentryAppStateTests.swift b/Tests/SentryTests/Helper/SentryAppStateTests.swift index 0debb89cc84..129eb30bbd2 100644 --- a/Tests/SentryTests/Helper/SentryAppStateTests.swift +++ b/Tests/SentryTests/Helper/SentryAppStateTests.swift @@ -1,3 +1,4 @@ +@_spi(Private) import Sentry import XCTest class SentryAppStateTests: XCTestCase { diff --git a/Tests/SentryTests/Helper/SentryDependencyContainerTests.swift b/Tests/SentryTests/Helper/SentryDependencyContainerTests.swift index f859adafd50..c310c3cd70b 100644 --- a/Tests/SentryTests/Helper/SentryDependencyContainerTests.swift +++ b/Tests/SentryTests/Helper/SentryDependencyContainerTests.swift @@ -74,7 +74,7 @@ final class SentryDependencyContainerTests: XCTestCase { let options = Options() options.dsn = SentryDependencyContainerTests.dsn - SentrySDK.setStart(options) + SentrySDKInternal.setStart(with: options) let iterations = 100 @@ -108,7 +108,6 @@ final class SentryDependencyContainerTests: XCTestCase { #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) XCTAssertNotNil(SentryDependencyContainer.sharedInstance().uiDeviceWrapper) - XCTAssertNotNil(SentryDependencyContainer.sharedInstance().application) #endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) // Lazy Dependencies @@ -125,15 +124,16 @@ final class SentryDependencyContainerTests: XCTestCase { XCTAssertNotNil(SentryDependencyContainer.sharedInstance().getANRTracker(2.0, isV2Enabled: true)) #endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) +#if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) XCTAssertNotNil(SentryDependencyContainer.sharedInstance().systemWrapper) +#endif // os(iOS) || os(macOS) || targetEnvironment(macCatalyst) XCTAssertNotNil(SentryDependencyContainer.sharedInstance().dispatchFactory) - XCTAssertNotNil(SentryDependencyContainer.sharedInstance().dispatchQueueProvider) XCTAssertNotNil(SentryDependencyContainer.sharedInstance().timerFactory) #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) XCTAssertNotNil(SentryDependencyContainer.sharedInstance().swizzleWrapper) XCTAssertNotNil(SentryDependencyContainer.sharedInstance().framesTracker) - XCTAssertNotNil(SentryDependencyContainer.sharedInstance().screenshot) + XCTAssertNotNil(SentryDependencyContainer.sharedInstance().screenshotSource) XCTAssertNotNil(SentryDependencyContainer.sharedInstance().viewHierarchyProvider) XCTAssertNotNil(SentryDependencyContainer.sharedInstance().uiViewControllerPerformanceTracker) @@ -166,7 +166,7 @@ final class SentryDependencyContainerTests: XCTestCase { // -- Arrange -- let options = Options() options.dsn = SentryDependencyContainerTests.dsn - SentrySDK.setStart(options) + SentrySDKInternal.setStart(with: options) let container = SentryDependencyContainer.sharedInstance() @@ -183,7 +183,7 @@ final class SentryDependencyContainerTests: XCTestCase { // -- Arrange -- let options = Options() options.dsn = SentryDependencyContainerTests.dsn - SentrySDK.setStart(options) + SentrySDKInternal.setStart(with: options) let container = SentryDependencyContainer.sharedInstance() @@ -203,7 +203,7 @@ final class SentryDependencyContainerTests: XCTestCase { // -- Arrange -- let options = Options() options.dsn = SentryDependencyContainerTests.dsn - SentrySDK.setStart(options) + SentrySDKInternal.setStart(with: options) let container = SentryDependencyContainer.sharedInstance() @@ -227,7 +227,7 @@ final class SentryDependencyContainerTests: XCTestCase { // -- Arrange -- let options = Options() options.dsn = SentryDependencyContainerTests.dsn - SentrySDK.setStart(options) + SentrySDKInternal.setStart(with: options) let container = SentryDependencyContainer.sharedInstance() @@ -247,7 +247,7 @@ final class SentryDependencyContainerTests: XCTestCase { // -- Arrange -- let options = Options() options.dsn = SentryDependencyContainerTests.dsn - SentrySDK.setStart(options) + SentrySDKInternal.setStart(with: options) let container = SentryDependencyContainer.sharedInstance() let dispatchFactory = TestDispatchFactory() @@ -276,7 +276,7 @@ final class SentryDependencyContainerTests: XCTestCase { options2.dsn = SentryDependencyContainerTests.dsn options2.sessionTrackingIntervalMillis = 5_000 - SentrySDK.setStart(options1) + SentrySDKInternal.setStart(with: options1) let container = SentryDependencyContainer.sharedInstance() @@ -300,7 +300,7 @@ final class SentryDependencyContainerTests: XCTestCase { options2.sessionTrackingIntervalMillis = 5_000 options2.environment = "test2" - SentrySDK.setStart(options1) + SentrySDKInternal.setStart(with: options1) let container = SentryDependencyContainer.sharedInstance() @@ -322,17 +322,23 @@ final class SentryDependencyContainerTests: XCTestCase { // -- Arrange -- let options = Options() options.dsn = SentryDependencyContainerTests.dsn - SentrySDK.setStart(options) + SentrySDKInternal.setStart(with: options) let container = SentryDependencyContainer.sharedInstance() + #if canImport(UIKit) + container.application = TestSentryUIApplication() + #else + container.application = TestSentryNSApplication() + #endif // -- Act -- let tracker = container.getSessionTracker(with: options) // -- Assert -- // Verify that the tracker uses the dependencies from the container + XCTAssertIdentical(Dynamic(tracker).application.asAnyObject, container.application) XCTAssertIdentical(Dynamic(tracker).dateProvider.asAnyObject, container.dateProvider) XCTAssertIdentical(Dynamic(tracker).notificationCenter.asAnyObject, container.notificationCenterWrapper) - } + } } diff --git a/Tests/SentryTests/Helper/SentryDeviceTests.m b/Tests/SentryTests/Helper/SentryDeviceTests.m index df0dec25558..e71c1528f29 100644 --- a/Tests/SentryTests/Helper/SentryDeviceTests.m +++ b/Tests/SentryTests/Helper/SentryDeviceTests.m @@ -89,13 +89,15 @@ - (void)testOSVersion NSString *osVersion = sentry_getOSVersion(); XCTAssertNotEqual(osVersion.length, 0U); #if TARGET_OS_OSX - SENTRY_ASSERT_PREFIX(osVersion, @"10.", @"11.", @"12.", @"13.", @"14.", @"15."); + SENTRY_ASSERT_PREFIX(osVersion, @"10.", @"11.", @"12.", @"13.", @"14.", @"15.", @"26."); #elif TARGET_OS_IOS || TARGET_OS_MACCATALYST || TARGET_OS_TV - SENTRY_ASSERT_PREFIX( - osVersion, @"9.", @"10.", @"11.", @"12.", @"13.", @"14.", @"15.", @"16.", @"17.", @"18."); + SENTRY_ASSERT_PREFIX(osVersion, @"9.", @"10.", @"11.", @"12.", @"13.", @"14.", @"15.", @"16.", + @"17.", @"18.", @"26."); #elif TARGET_OS_WATCH // TODO: create a watch UI test target to test this branch - SENTRY_ASSERT_PREFIX(osVersion, @"2.", @"3.", @"4.", @"5.", @"6.", @"7.", @"8.", @"9."); + SENTRY_ASSERT_PREFIX(osVersion, @"2.", @"3.", @"4.", @"5.", @"6.", @"7.", @"8.", @"9.", @"26."); +#elif TARGET_OS_VISION + SENTRY_ASSERT_PREFIX(osVersion, @"1.", @"2.", @"26."); #else XCTFail(@"Unexpected OS."); #endif diff --git a/Tests/SentryTests/Helper/SentryEnabledFeaturesBuilderTests.swift b/Tests/SentryTests/Helper/SentryEnabledFeaturesBuilderTests.swift index 193e545fe59..4c5917a1531 100644 --- a/Tests/SentryTests/Helper/SentryEnabledFeaturesBuilderTests.swift +++ b/Tests/SentryTests/Helper/SentryEnabledFeaturesBuilderTests.swift @@ -1,6 +1,7 @@ @_spi(Private) @testable import Sentry import XCTest +@available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") final class SentryEnabledFeaturesBuilderTests: XCTestCase { func testDefaultFeatures() throws { diff --git a/Tests/SentryTests/Helper/SentryExtraContextProviderTests.swift b/Tests/SentryTests/Helper/SentryExtraContextProviderTests.swift index 9ebb1c5f44e..972f632a9a0 100644 --- a/Tests/SentryTests/Helper/SentryExtraContextProviderTests.swift +++ b/Tests/SentryTests/Helper/SentryExtraContextProviderTests.swift @@ -1,14 +1,14 @@ -import SentryTestUtils +@_spi(Private) import SentryTestUtils import XCTest final class SentryExtraContextProviderTests: XCTestCase { private class Fixture { - let crashWrapper = TestSentryCrashWrapper.sharedInstance() + let crashWrapper = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo) #if os(iOS) || targetEnvironment(macCatalyst) let deviceWrapper = TestSentryUIDeviceWrapper() #endif // os(iOS) || targetEnvironment(macCatalyst) - let processWrapper = TestSentryNSProcessInfoWrapper() + let processWrapper = MockSentryProcessInfo() func getSut() -> SentryExtraContextProvider { #if os(iOS) || targetEnvironment(macCatalyst) @@ -74,7 +74,7 @@ final class SentryExtraContextProviderTests: XCTestCase { let actualContext = sut.getExtraContext() let device = try XCTUnwrap(actualContext["device"] as? [String: Any]) - XCTAssertEqual(try XCTUnwrap(device["processor_count"] as? UInt), fixture.processWrapper.overrides.processorCount) + XCTAssertEqual(try XCTUnwrap(device["processor_count"] as? Int), fixture.processWrapper.overrides.processorCount) XCTAssertEqual(try XCTUnwrap(device["thermal_state"] as? String), "critical") } diff --git a/Tests/SentryTests/Helper/SentryFileManagerTestExtension.swift b/Tests/SentryTests/Helper/SentryFileManagerTestExtension.swift index 566e57974b8..e0d1d22af7f 100644 --- a/Tests/SentryTests/Helper/SentryFileManagerTestExtension.swift +++ b/Tests/SentryTests/Helper/SentryFileManagerTestExtension.swift @@ -6,41 +6,34 @@ extension SentryFileManager { /** * Creates a file at the same path as SentryFileManager stores its files. When init on SentryFileManager is called the init is going to throw an error, because it can't create the internal folders. */ - static func prepareInitError() { - deleteInternalPath() - do { - let data = Data("hello".utf8) - try data.write(to: getInternalPath()) - } catch { - XCTFail("Couldn't create file for init error of SentryFileManager.") - } + static func prepareInitError() throws { + try deleteInternalPath() + + let data = Data("hello".utf8) + let sentryPath = try getSentryCachePath() + try data.write(to: sentryPath) } - + /** * Deletes the file created with prepareInitError. */ - static func tearDownInitError() { - deleteInternalPath() + static func tearDownInitError() throws { + try deleteInternalPath() } - private static func deleteInternalPath() { - do { - try FileManager.default.removeItem(at: getInternalPath()) - } catch { - XCTFail("Couldn't delete internal path of SentryFileManager.") + private static func deleteInternalPath() throws { + let cacheSentryPath = try getSentryCachePath() + if FileManager.default.fileExists(atPath: cacheSentryPath.path) { + try FileManager.default.removeItem(at: cacheSentryPath) } } - private static func getInternalPath() -> URL { - let cachePath: String = FileManager.default - .urls(for: .cachesDirectory, in: .userDomainMask) - .map { dir in - dir.absoluteString - } - .first ?? "" - - let sentryPath = URL(fileURLWithPath: cachePath).appendingPathComponent("io.sentry") + private static func getSentryCachePath() throws -> URL { + let cachePath = try XCTUnwrap(FileManager.default + .urls(for: .cachesDirectory, in: .userDomainMask).first) + let sentryPath = cachePath.appendingPathComponent("io.sentry") return sentryPath } + } diff --git a/Tests/SentryTests/Helper/SentryFileManagerTests.swift b/Tests/SentryTests/Helper/SentryFileManagerTests.swift index ba2796bc53d..cd6deb656ba 100644 --- a/Tests/SentryTests/Helper/SentryFileManagerTests.swift +++ b/Tests/SentryTests/Helper/SentryFileManagerTests.swift @@ -30,6 +30,7 @@ class SentryFileManagerTests: XCTestCase { var delegate: TestFileManagerDelegate! // swiftlint:enable weak_delegate + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") init() throws { currentDateProvider = TestCurrentDateProvider() dispatchQueueWrapper = TestSentryDispatchQueueWrapper() @@ -60,14 +61,22 @@ class SentryFileManagerTests: XCTestCase { } func getSut() -> SentryFileManager { - let sut = try! SentryFileManager(options: options, dispatchQueueWrapper: dispatchQueueWrapper) + let sut = try! SentryFileManager( + options: options, + dateProvider: currentDateProvider, + dispatchQueueWrapper: dispatchQueueWrapper + ) sut.setDelegate(delegate) return sut } func getSut(maxCacheItems: UInt) -> SentryFileManager { options.maxCacheItems = maxCacheItems - let sut = try! SentryFileManager(options: options, dispatchQueueWrapper: dispatchQueueWrapper) + let sut = try! SentryFileManager( + options: options, + dateProvider: currentDateProvider, + dispatchQueueWrapper: dispatchQueueWrapper + ) sut.setDelegate(delegate) return sut } @@ -97,6 +106,7 @@ class SentryFileManagerTests: XCTestCase { private var fixture: Fixture! private var sut: SentryFileManager! + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") override func setUpWithError() throws { try super.setUpWithError() fixture = try Fixture() @@ -119,14 +129,23 @@ class SentryFileManagerTests: XCTestCase { sut.deleteAbnormalSession() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testInitDoesNotOverrideDirectories() { sut.store(TestConstants.envelope) sut.storeCurrentSession(SentrySession(releaseName: "1.0.0", distinctId: "some-id")) sut.storeTimestampLast(inForeground: Date()) - _ = try! SentryFileManager(options: fixture.options, dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) - let fileManager = try! SentryFileManager(options: fixture.options, dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) - + _ = try! SentryFileManager( + options: fixture.options, + dateProvider: fixture.currentDateProvider, + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ) + let fileManager = try! SentryFileManager( + options: fixture.options, + dateProvider: fixture.currentDateProvider, + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ) + XCTAssertEqual(1, fileManager.getAllEnvelopes().count) XCTAssertNotNil(fileManager.readCurrentSession()) XCTAssertNotNil(fileManager.readTimestampLastInForeground()) @@ -135,8 +154,12 @@ class SentryFileManagerTests: XCTestCase { func testInitDeletesEventsFolder() { storeEvent() - _ = try! SentryFileManager(options: fixture.options, dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) - + _ = try! SentryFileManager( + options: fixture.options, + dateProvider: fixture.currentDateProvider, + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ) + assertEventFolderDoesntExist() } @@ -144,6 +167,7 @@ class SentryFileManagerTests: XCTestCase { assertEventFolderDoesntExist() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testStoreEnvelope() throws { let envelope = TestConstants.envelope sut.store(envelope) @@ -154,11 +178,11 @@ class SentryFileManagerTests: XCTestCase { XCTAssertEqual(1, envelopes.count) let actualData = try XCTUnwrap(envelopes.first).contents - XCTAssertEqual(expectedData, actualData as Data) + try compareEnvelopes(expectedData, actualData as Data, message: "Envelopes are not equal") } func testStoreInvalidEnvelope_ReturnsNil() { - let sdkInfoWithInvalidJSON = SentrySdkInfo(name: SentryInvalidJSONString() as String, version: "8.0.0", integrations: [], features: [], packages: []) + let sdkInfoWithInvalidJSON = SentrySdkInfo(name: SentryInvalidJSONString() as String, version: "8.0.0", integrations: [], features: [], packages: [], settings: SentrySDKSettings(dict: [:])) let headerWithInvalidJSON = SentryEnvelopeHeader(id: nil, sdkInfo: sdkInfoWithInvalidJSON, traceContext: nil) let envelope = SentryEnvelope(header: headerWithInvalidJSON, items: []) @@ -166,6 +190,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertNil(sut.store(envelope)) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testDeleteOldEnvelopes() throws { try givenOldEnvelopes() @@ -238,6 +263,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertEqual(logMessages.count, 1) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testDeleteOldEnvelopes_WithEmptyDSN() throws { fixture.options.dsn = nil sut = fixture.getSut() @@ -250,6 +276,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertEqual(sut.getAllEnvelopes().count, 0) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testDontDeleteYoungEnvelopes() throws { let envelope = TestConstants.envelope let path = try XCTUnwrap(sut.store(envelope)) @@ -265,6 +292,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertEqual(sut.getAllEnvelopes().count, 1) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testDontDeleteYoungEnvelopesFromOldEnvelopesFolder() throws { let envelope = TestConstants.envelope sut.store(envelope) @@ -280,6 +308,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertEqual(sut.getAllEnvelopes().count, 1) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testFileManagerDeallocated_OldEnvelopesNotDeleted() throws { try givenOldEnvelopes() @@ -307,6 +336,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertFalse(logOutput.loggedMessages.contains(where: { $0.contains("[error]") })) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testDefaultMaxEnvelopes() { for _ in 0...(fixture.maxCacheItems + 1) { sut.store(TestConstants.envelope) @@ -316,6 +346,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertEqual(fixture.maxCacheItems, events.count) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testDefaultMaxEnvelopes_CallsEnvelopeItemDeleted() { let event = Event() let envelope = SentryEnvelope(id: event.eventId, items: [ @@ -333,6 +364,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertEqual(expected, fixture.delegate.envelopeItemsDeleted.invocations) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testDefaultMaxEnvelopesConcurrent() { let maxCacheItems = 1 let sut = fixture.getSut(maxCacheItems: UInt(maxCacheItems)) @@ -358,6 +390,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertEqual(maxCacheItems, events.count) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testMaxEnvelopesSet() { let maxCacheItems: UInt = 15 sut = fixture.getSut(maxCacheItems: maxCacheItems) @@ -368,6 +401,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertEqual(maxCacheItems, UInt(events.count)) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testMigrateSessionInit_SessionUpdateIsLast() throws { sut.store(fixture.sessionEnvelope) // just some other session @@ -381,6 +415,7 @@ class SentryFileManagerTests: XCTestCase { assertSessionEnvelopesStored(count: 2) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testMigrateSessionInit_SessionUpdateIsSecond() throws { sut.store(fixture.sessionEnvelope) sut.store(fixture.sessionUpdateEnvelope) @@ -392,6 +427,7 @@ class SentryFileManagerTests: XCTestCase { assertSessionEnvelopesStored(count: 1) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testMigrateSessionInit_IsInMiddle() throws { sut.store(fixture.sessionEnvelope) for _ in 0...10 { @@ -406,6 +442,7 @@ class SentryFileManagerTests: XCTestCase { assertSessionEnvelopesStored(count: 1) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testMigrateSessionInit_MovesInitFlagOnlyToFirstSessionUpdate() throws { sut.store(fixture.sessionEnvelope) for _ in 0...10 { @@ -424,6 +461,7 @@ class SentryFileManagerTests: XCTestCase { assertSessionEnvelopesStored(count: 3) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testMigrateSessionInit_NoOtherSessionUpdate() { sut.store(fixture.sessionEnvelope) sut.store(fixture.sessionUpdateEnvelope) @@ -434,6 +472,7 @@ class SentryFileManagerTests: XCTestCase { assertSessionEnvelopesStored(count: 0) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testMigrateSessionInit_FailToLoadEnvelope() throws { sut.store(fixture.sessionEnvelope) @@ -452,6 +491,7 @@ class SentryFileManagerTests: XCTestCase { try assertSessionInitMoved(sut.getAllEnvelopes().last!) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testMigrateSessionInit_DoesNotCallEnvelopeItemDeleted() { sut.store(fixture.sessionEnvelope) sut.store(fixture.sessionUpdateEnvelope) @@ -462,6 +502,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertEqual(0, fixture.delegate.envelopeItemsDeleted.count) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testGetAllEnvelopesAreSortedByDateAscending() { givenMaximumEnvelopes() @@ -478,6 +519,7 @@ class SentryFileManagerTests: XCTestCase { } } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testGetOldestEnvelope() { givenMaximumEnvelopes() @@ -561,7 +603,7 @@ class SentryFileManagerTests: XCTestCase { sut.deleteAbnormalSession() } - func testReadAbnormalSession_NoSessionStored () throws { + func testReadAbnormalSession_NoSessionStored() throws { XCTAssertNil(sut.readAbnormalSession()) } @@ -613,6 +655,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertNil(actualTimestamp) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testGetAllStoredEventsAndEnvelopes() { sut.store(TestConstants.envelope) sut.store(TestConstants.envelope) @@ -620,6 +663,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertEqual(2, sut.getAllEnvelopes().count) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testDeleteAllFolders() { storeEvent() sut.store(TestConstants.envelope) @@ -632,6 +676,7 @@ class SentryFileManagerTests: XCTestCase { assertEventFolderDoesntExist() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testDeleteAllStoredEnvelopes() { sut.store(TestConstants.envelope) @@ -1167,7 +1212,7 @@ extension SentryFileManagerTests { profilesSampleRate: expectedProfilesSampleRate, profilesSampleRand: expectedProfilesSampleRand ) - let config = sentry_appLaunchProfileConfiguration() + let config = sentry_persistedLaunchProfileConfigurationOptions() // -- Assert -- let actualTracesSampleRate = try XCTUnwrap(config?[kSentryLaunchProfileConfigKeyTracesSampleRate]).doubleValue @@ -1183,7 +1228,7 @@ extension SentryFileManagerTests { // if a file isn't present when we expect it to be, like if there was an issue when we went to write it to disk func testsentry_appLaunchProfileConfiguration_noConfigurationExists() throws { try ensureAppLaunchProfileConfig(exists: false) - XCTAssertNil(sentry_appLaunchProfileConfiguration()) + XCTAssertNil(sentry_persistedLaunchProfileConfigurationOptions()) } func testWriteAppLaunchProfilingConfigFile_noCurrentFileExists() throws { @@ -1200,9 +1245,10 @@ extension SentryFileManagerTests { kSentryLaunchProfileConfigKeyProfilesSampleRate: expectedProfilesSampleRate, kSentryLaunchProfileConfigKeyProfilesSampleRand: expectedProfilesSampleRand ]) - - let config = NSDictionary(contentsOf: launchProfileConfigFileURL()) - + + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + let config = NSDictionary(contentsOf: configURL) + let actualTracesSampleRate = try XCTUnwrap(config?[kSentryLaunchProfileConfigKeyTracesSampleRate] as? NSNumber).doubleValue let actualTracesSampleRand = try XCTUnwrap(config?[kSentryLaunchProfileConfigKeyTracesSampleRand] as? NSNumber).doubleValue let actualProfilesSampleRate = try XCTUnwrap(config?[kSentryLaunchProfileConfigKeyProfilesSampleRate] as? NSNumber).doubleValue @@ -1232,8 +1278,9 @@ extension SentryFileManagerTests { ]) // -- Assert -- - let config = NSDictionary(contentsOf: launchProfileConfigFileURL()) - + let configURL = try XCTUnwrap(launchProfileConfigFileURL()) + let config = NSDictionary(contentsOf: configURL) + let actualTracesSampleRate = try XCTUnwrap(config?[kSentryLaunchProfileConfigKeyTracesSampleRate] as? NSNumber).doubleValue let actualTracesSampleRand = try XCTUnwrap(config?[kSentryLaunchProfileConfigKeyTracesSampleRand] as? NSNumber).doubleValue let actualProfilesSampleRate = try XCTUnwrap(config?[kSentryLaunchProfileConfigKeyProfilesSampleRate] as? NSNumber).doubleValue @@ -1246,17 +1293,17 @@ extension SentryFileManagerTests { func testRemoveAppLaunchProfilingConfigFile() throws { try ensureAppLaunchProfileConfig(exists: true) - XCTAssertNotNil(NSDictionary(contentsOf: launchProfileConfigFileURL())) + XCTAssertNotNil(NSDictionary(contentsOf: try XCTUnwrap(launchProfileConfigFileURL()))) removeAppLaunchProfilingConfigFile() - XCTAssertNil(NSDictionary(contentsOf: launchProfileConfigFileURL())) + XCTAssertNil(NSDictionary(contentsOf: try XCTUnwrap(launchProfileConfigFileURL()))) } // if there's not a file when we expect one, just make sure we don't crash func testRemoveAppLaunchProfilingConfigFile_noFileExists() throws { try ensureAppLaunchProfileConfig(exists: false) - XCTAssertNil(NSDictionary(contentsOf: launchProfileConfigFileURL())) + XCTAssertNil(NSDictionary(contentsOf: try XCTUnwrap(launchProfileConfigFileURL()))) removeAppLaunchProfilingConfigFile() - XCTAssertNil(NSDictionary(contentsOf: launchProfileConfigFileURL())) + XCTAssertNil(NSDictionary(contentsOf: try XCTUnwrap(launchProfileConfigFileURL()))) } func testCheckForLaunchProfilingConfigFile_URLDoesNotExist() { @@ -1270,7 +1317,7 @@ extension SentryFileManagerTests { XCTAssertFalse(appLaunchProfileConfigFileExists()) // set the original value back so other tests don't crash - sentryLaunchConfigFileURL = (originalURL as NSURL) + sentryLaunchConfigFileURL = (originalURL as? NSURL) } func testSentryGetScopedCachesDirectory_targetIsNotMacOS_shouldReturnSamePath() throws { @@ -1383,7 +1430,7 @@ extension SentryFileManagerTests { // MARK: Private profiling tests private extension SentryFileManagerTests { func ensureAppLaunchProfileConfig(exists: Bool = true, tracesSampleRate: Double = 1, tracesSampleRand: Double = 1.0, profilesSampleRate: Double = 1, profilesSampleRand: Double = 1.0) throws { - let url = launchProfileConfigFileURL() + let url = try XCTUnwrap(launchProfileConfigFileURL()) if exists { let dict = [ @@ -1405,6 +1452,7 @@ private extension SentryFileManagerTests { // MARK: Private private extension SentryFileManagerTests { + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func givenMaximumEnvelopes() { fixture.eventIds.forEach { id in let envelope = SentryEnvelope(id: id, singleItem: SentryEnvelopeItem(event: Event())) @@ -1422,6 +1470,7 @@ private extension SentryFileManagerTests { } } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func givenOldEnvelopes() throws { let envelope = TestConstants.envelope let path = try XCTUnwrap(sut.store(envelope)) @@ -1482,7 +1531,7 @@ private extension SentryFileManagerTests { let actualSessionEnvelope = SentrySerialization.envelope(with: actualSessionFileContents.contents) XCTAssertEqual(2, actualSessionEnvelope?.items.count) - let actualSession = SentrySerialization.session(with: try XCTUnwrap(actualSessionEnvelope?.items.element(at: 1)).data) + let actualSession = SentrySerialization.session(with: try XCTUnwrap(XCTUnwrap(actualSessionEnvelope?.items.element(at: 1)).data)) XCTAssertNotNil(actualSession) XCTAssertEqual(fixture.expectedSessionUpdate, actualSession) @@ -1492,7 +1541,7 @@ private extension SentryFileManagerTests { let actualSessionEnvelope = SentrySerialization.envelope(with: actualSessionFileContents.contents) XCTAssertEqual(2, actualSessionEnvelope?.items.count) - let actualSession = SentrySerialization.session(with: try XCTUnwrap(actualSessionEnvelope?.items.first).data) + let actualSession = SentrySerialization.session(with: try XCTUnwrap(XCTUnwrap(actualSessionEnvelope?.items.first).data)) XCTAssertNotNil(actualSession) XCTAssertEqual(fixture.sessionUpdate, actualSession) @@ -1501,7 +1550,7 @@ private extension SentryFileManagerTests { func assertSessionEnvelopesStored(count: Int) { let fileContentsWithSession = sut.getAllEnvelopes().filter { envelopeFileContents in let envelope = SentrySerialization.envelope(with: envelopeFileContents.contents) - return !(envelope?.items.filter { item in item.header.type == SentryEnvelopeItemTypeSession }.isEmpty ?? false) + return !(envelope?.items.filter { item in item.header.type == SentryEnvelopeItemTypes.session }.isEmpty ?? false) } XCTAssertEqual(count, fileContentsWithSession.count) diff --git a/Tests/SentryTests/Helper/SentryLevelMapperTests.swift b/Tests/SentryTests/Helper/SentryLevelMapperTests.swift new file mode 100644 index 00000000000..69e683786f6 --- /dev/null +++ b/Tests/SentryTests/Helper/SentryLevelMapperTests.swift @@ -0,0 +1,25 @@ +@testable import Sentry +import XCTest + +class SentryLevelMapperTests: XCTestCase { + func testSentryLevelForString_nilParameter_shouldReturnDefault() { + XCTAssertEqual(sentryLevelForString(nil), .error) + } + + func testSentryLevelForString_emptyString_shouldReturnDefault() { + XCTAssertEqual(sentryLevelForString(""), .error) + } + + func testSentryLevelForString_invalidString_shouldReturnDefault() { + XCTAssertEqual(sentryLevelForString("invalid"), .error) + } + + func testSentryLevelForString_validString_shouldReturnCorrectLevel() { + XCTAssertEqual(sentryLevelForString("none"), .none) + XCTAssertEqual(sentryLevelForString("debug"), .debug) + XCTAssertEqual(sentryLevelForString("info"), .info) + XCTAssertEqual(sentryLevelForString("warning"), .warning) + XCTAssertEqual(sentryLevelForString("error"), .error) + XCTAssertEqual(sentryLevelForString("fatal"), .fatal) + } +} diff --git a/Tests/SentryTests/Helper/SentryMobileProvisionParserTests.swift b/Tests/SentryTests/Helper/SentryMobileProvisionParserTests.swift new file mode 100644 index 00000000000..b400b04e95d --- /dev/null +++ b/Tests/SentryTests/Helper/SentryMobileProvisionParserTests.swift @@ -0,0 +1,204 @@ +@_spi(Private) @testable import Sentry +@_spi(Private) import SentryTestUtils +import XCTest + +class SentryMobileProvisionParserTests: XCTestCase { + // MARK: - Valid Content Tests + + func testInitWithValidEnterpriseContent() throws { + let content = """ + + + + + ProvisionsAllDevices + + AppIDName + Enterprise App + + + """ + try createFileAndAssert(content) { path in + let parser = SentryMobileProvisionParser(path) + XCTAssertTrue(parser.mobileProvisionProfileProvisionsAllDevices) + } + } + + func testInitWithValidAdhocContent() throws { + let content = """ + + + + + ProvisionsAllDevices + + AppIDName + Adhoc App + + + + + """ + + try createFileAndAssert(content) { path in + let parser = SentryMobileProvisionParser(path) + XCTAssertFalse(parser.mobileProvisionProfileProvisionsAllDevices) + } + } + + func testInitWithContentWithoutProvisionsAllDevicesKey() throws { + let content = """ + + + + + AppIDName + No Provisions All Devices Key + + + + + """ + + try createFileAndAssert(content) { path in + let parser = SentryMobileProvisionParser(path) + XCTAssertFalse(parser.mobileProvisionProfileProvisionsAllDevices) + } + } + + func testInitWithExtraDataInMobileprovisionfile() throws { + let content = """ + This is not a valid plist content + + + ProvisionsAllDevices + + + + This isn't valid content either + """ + + // The parser scans for the plist inside the profile, so it should find it + try createFileAndAssert(content) { path in + let parser = SentryMobileProvisionParser(path) + XCTAssertTrue(parser.mobileProvisionProfileProvisionsAllDevices) + } + } + + // MARK: - Invalid Content Tests + + func testInitWithEmptyContent() throws { + try createFileAndAssert("") { path in + let parser = SentryMobileProvisionParser(path) + XCTAssertFalse(parser.mobileProvisionProfileProvisionsAllDevices) // Should default to false when parsing fails + } + } + + func testInitWithMalformedPlistContent() throws { + let content = """ + + + ProvisionsAllDevices + + + """ + + try createFileAndAssert(content) { path in + let parser = SentryMobileProvisionParser(path) + XCTAssertFalse(parser.mobileProvisionProfileProvisionsAllDevices) // Should default to false when parsing fails + } + } + + func testInitWithMissingPlistTags() throws { + let content = """ + + ProvisionsAllDevices + + + """ + + try createFileAndAssert(content) { path in + let parser = SentryMobileProvisionParser(path) + XCTAssertFalse(parser.mobileProvisionProfileProvisionsAllDevices) // Should default to false when parsing fails + } + } + + // MARK: - Edge Cases + + func testProvisionsAllDevicesWithNonBooleanValue() throws { + let content = """ + + + + + ProvisionsAllDevices + true + + + """ + + try createFileAndAssert(content) { path in + let parser = SentryMobileProvisionParser(path) + XCTAssertFalse(parser.mobileProvisionProfileProvisionsAllDevices) // Should default to false when value is not boolean + } + } + + func testProvisionsAllDevicesWithArrayValue() throws { + let content = """ + + + + + ProvisionsAllDevices + + true + + + + """ + + try createFileAndAssert(content) { path in + let parser = SentryMobileProvisionParser(path) + XCTAssertFalse(parser.mobileProvisionProfileProvisionsAllDevices) // Should default to false when value is not boolean + } + } + + func testPathDoesNotExist() throws { + let parser = SentryMobileProvisionParser("/randomPath.xml") + XCTAssertFalse(parser.mobileProvisionProfileProvisionsAllDevices) + } + + func testContentWithEmojiAndJapaneseCharacters() throws { + // Create content with UTF-8 characters that cannot be represented in Latin-1 + // These include emojis, Chinese characters, and other Unicode characters + let content = """ + + + + + ProvisionsAllDevices + + AppIDName + Test App with 中文 characters and 🚀 emojis + + + """ + + try createFileAndAssert(content) { path in + let parser = SentryMobileProvisionParser(path) + // Should default to false when Latin-1 conversion fails and plist cannot be extracted + XCTAssertTrue(parser.mobileProvisionProfileProvisionsAllDevices) + } + } + + // MARK: - Utils + private func createFileAndAssert(_ content: String, at fileName: String = #function, assertBlock: ((String) throws -> Void)) throws { + let tmpPath = FileManager.default.temporaryDirectory.path + let path = "\(tmpPath)\(fileName).tmp" + try content.write(toFile: path, atomically: true, encoding: .utf8) + + try assertBlock(path) + + try FileManager.default.removeItem(atPath: path) + } +} diff --git a/Tests/SentryTests/Helper/SentryNSNotificationCenterWrapperTests.swift b/Tests/SentryTests/Helper/SentryNSNotificationCenterWrapperTests.swift deleted file mode 100644 index ce6c46fd221..00000000000 --- a/Tests/SentryTests/Helper/SentryNSNotificationCenterWrapperTests.swift +++ /dev/null @@ -1,97 +0,0 @@ -import SentryTestUtils -import XCTest - -class SentryNSNotificationCenterWrapperTests: XCTestCase { - - private var sut: SentryNSNotificationCenterWrapper! - - private var didBecomeActiveExpectation: XCTestExpectation! - private var willResignActiveExpectation: XCTestExpectation! - - private let didBecomeActiveNotification = CrossPlatformApplication.didBecomeActiveNotification - private let willResignActiveNotification = CrossPlatformApplication.willResignActiveNotification - - override func setUp() { - super.setUp() - - sut = SentryNSNotificationCenterWrapper() - } - - override func tearDown() { - sut.removeObserver(self) - - super.tearDown() - } - - func testAddObserver() { - addDefaultExpectations() - sut.addObserver(self, selector: #selector(didBecomeActive), name: didBecomeActiveNotification) - - NotificationCenter.default.post(Notification(name: didBecomeActiveNotification)) - - wait(for: [didBecomeActiveExpectation, willResignActiveExpectation], timeout: 0.5) - } - - func testAddObserverWithBlock() { - let exp = expectation(description: "received notification block callback") - var observer: NSObject? - observer = sut.addObserver(forName: didBecomeActiveNotification, object: nil, queue: nil) { _ in - do { - self.sut.removeObserver(try XCTUnwrap(observer)) - } catch { - XCTFail("notification observer was not correctly retained") - } - exp.fulfill() - } as? NSObject - NotificationCenter.default.post(.init(name: didBecomeActiveNotification)) - wait(for: [exp], timeout: 0.5) - } - - func testRemoveSpecificObserver() { - addDefaultExpectations() - sut.addObserver(self, selector: #selector(didBecomeActive), name: didBecomeActiveNotification) - sut.addObserver(self, selector: #selector(willResignActive), name: willResignActiveNotification) - - sut.removeObserver(self, name: willResignActiveNotification) - NotificationCenter.default.post(Notification(name: didBecomeActiveNotification)) - - wait(for: [didBecomeActiveExpectation, willResignActiveExpectation], timeout: 0.5) - } - - func testRemoveObserver() { - addDefaultExpectations() - didBecomeActiveExpectation.isInverted = true - - sut.addObserver(self, selector: #selector(didBecomeActive), name: didBecomeActiveNotification) - sut.addObserver(self, selector: #selector(willResignActive), name: willResignActiveNotification) - - sut.removeObserver(self) - NotificationCenter.default.post(Notification(name: didBecomeActiveNotification)) - - wait(for: [didBecomeActiveExpectation, willResignActiveExpectation], timeout: 0.5) - } - - func testPostNotificationsOnMock() { - addDefaultExpectations() - let sut = TestNSNotificationCenterWrapper() - sut.addObserver(self, selector: #selector(didBecomeActive), name: didBecomeActiveNotification) - sut.post(Notification(name: didBecomeActiveNotification)) - wait(for: [didBecomeActiveExpectation, willResignActiveExpectation], timeout: 0.5) - } -} - -@objc private extension SentryNSNotificationCenterWrapperTests { - func didBecomeActive() { - didBecomeActiveExpectation.fulfill() - } - - func willResignActive() { - willResignActiveExpectation.fulfill() - } - - func addDefaultExpectations() { - didBecomeActiveExpectation = expectation(description: "didBecomeActive") - willResignActiveExpectation = expectation(description: "willResignActive") - willResignActiveExpectation.isInverted = true - } -} diff --git a/Tests/SentryTests/Helper/SentrySerializationNilTests.m b/Tests/SentryTests/Helper/SentrySerializationNilTests.m index b59f3b524da..ea00d4257db 100644 --- a/Tests/SentryTests/Helper/SentrySerializationNilTests.m +++ b/Tests/SentryTests/Helper/SentrySerializationNilTests.m @@ -1,4 +1,3 @@ -#import "SentryEnvelope.h" #import "SentrySerialization.h" #import diff --git a/Tests/SentryTests/Helper/SentrySerializationTests.swift b/Tests/SentryTests/Helper/SentrySerializationTests.swift index 9043ee51409..ddc9b6bedfd 100644 --- a/Tests/SentryTests/Helper/SentrySerializationTests.swift +++ b/Tests/SentryTests/Helper/SentrySerializationTests.swift @@ -46,7 +46,7 @@ class SentrySerializationTests: XCTestCase { } func testEnvelopeWithData_InvalidEnvelopeHeaderJSON_ReturnsNil() { - let sdkInfoWithInvalidJSON = SentrySdkInfo(name: SentryInvalidJSONString() as String, version: "8.0.0", integrations: [], features: [], packages: []) + let sdkInfoWithInvalidJSON = SentrySdkInfo(name: SentryInvalidJSONString() as String, version: "8.0.0", integrations: [], features: [], packages: [], settings: SentrySDKSettings(dict: [:])) let headerWithInvalidJSON = SentryEnvelopeHeader(id: nil, sdkInfo: sdkInfoWithInvalidJSON, traceContext: nil) let envelope = SentryEnvelope(header: headerWithInvalidJSON, items: []) @@ -54,6 +54,7 @@ class SentrySerializationTests: XCTestCase { XCTAssertNil(SentrySerialization.data(with: envelope)) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testEnvelopeWithData_InvalidEnvelopeItemHeaderJSON_ReturnsNil() throws { let envelopeItemHeader = SentryEnvelopeItemHeader(type: SentryInvalidJSONString() as String, length: 0) let envelopeItem = SentryEnvelopeItem(header: envelopeItemHeader, data: Data()) @@ -63,6 +64,7 @@ class SentrySerializationTests: XCTestCase { XCTAssertNil(SentrySerialization.data(with: envelope)) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testEnvelopeWithData_WithSingleEvent() throws { // Arrange let event = Event() @@ -87,6 +89,7 @@ class SentrySerializationTests: XCTestCase { XCTAssertEqual(Date(timeIntervalSince1970: 9_001), deserializedEnvelope.header.sentAt) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testEnvelopeWithData_WithManyItems() throws { // Arrange let itemsCount = 15 @@ -125,6 +128,7 @@ class SentrySerializationTests: XCTestCase { } } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testEnvelopeWithData_EmptyAttachment_ReturnsEnvelope() throws { // Arrange let itemData = Data() @@ -142,12 +146,12 @@ class SentrySerializationTests: XCTestCase { XCTAssertEqual(1, deserializedEnvelope.items.count) XCTAssertEqual("attachment", try XCTUnwrap(deserializedEnvelope.items.first).header.type) XCTAssertEqual(0, try XCTUnwrap(deserializedEnvelope.items.first).header.length) - XCTAssertEqual(0, try XCTUnwrap(deserializedEnvelope.items.first).data.count) + XCTAssertEqual(0, try XCTUnwrap(XCTUnwrap(deserializedEnvelope.items.first).data).count) assertDefaultSdkInfoSet(deserializedEnvelope: deserializedEnvelope) } func testEnvelopeWithData_WithSdkInfo_ReturnsSDKInfo() throws { - let sdkInfo = SentrySdkInfo(name: "sentry.cocoa", version: "5.0.1", integrations: [], features: [], packages: []) + let sdkInfo = SentrySdkInfo(name: "sentry.cocoa", version: "5.0.1", integrations: [], features: [], packages: [], settings: SentrySDKSettings(dict: [:])) let envelopeHeader = SentryEnvelopeHeader(id: nil, sdkInfo: sdkInfo, traceContext: nil) let envelope = SentryEnvelope(header: envelopeHeader, singleItem: createItemWithEmptyAttachment()) @@ -155,6 +159,7 @@ class SentrySerializationTests: XCTestCase { XCTAssertEqual(sdkInfo, deserializedEnvelope.header.sdkInfo) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testEnvelopeWithData_WithTraceContext_ReturnsTraceContext() throws { let envelopeHeader = SentryEnvelopeHeader(id: nil, traceContext: Fixture.traceContext) let envelope = SentryEnvelope(header: envelopeHeader, singleItem: createItemWithEmptyAttachment()) @@ -166,6 +171,7 @@ class SentrySerializationTests: XCTestCase { assertTraceState(firstTrace: Fixture.traceContext, secondTrace: traceContext) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testEnvelopeWithData_TraceContextWithoutUser_ReturnsTraceContext() throws { let trace = TraceContext(trace: SentryId(), publicKey: "PUBLIC_KEY", releaseName: "RELEASE_NAME", environment: "TEST", transaction: "transaction", userSegment: nil, sampleRate: nil, sampled: nil, replayId: nil) @@ -179,6 +185,7 @@ class SentrySerializationTests: XCTestCase { assertTraceState(firstTrace: trace, secondTrace: traceContext) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testEnvelopeWithDataWithSampleRand_TraceContextWithoutUser_ReturnsTraceContext() throws { // -- Arrange -- let trace = TraceContext( @@ -291,7 +298,7 @@ class SentrySerializationTests: XCTestCase { let secondItem = try XCTUnwrap(envelope.items[1]) XCTAssertEqual(0, secondItem.header.length) XCTAssertEqual("attachment", secondItem.header.type) - XCTAssertTrue(secondItem.data.isEmpty) + try XCTAssertTrue(XCTUnwrap(secondItem.data).isEmpty) } func testEnvelopeWithData_EmptyAttachmentFollowedByNormal() throws { @@ -314,7 +321,7 @@ class SentrySerializationTests: XCTestCase { XCTAssertEqual(0, firstItem.header.length) XCTAssertEqual("attachment", firstItem.header.type) XCTAssertNil(firstItem.header.contentType) - XCTAssertTrue(firstItem.data.isEmpty) + try XCTAssertTrue(XCTUnwrap(firstItem.data).isEmpty) let secondItem = try XCTUnwrap(envelope.items[1]) XCTAssertEqual(10, secondItem.header.length) @@ -337,7 +344,7 @@ class SentrySerializationTests: XCTestCase { XCTAssertEqual(0, item.header.length) XCTAssertEqual("attachment", item.header.type) XCTAssertNil(item.header.contentType) - XCTAssertTrue(item.data.isEmpty) + try XCTAssertTrue(XCTUnwrap(item.data).isEmpty) } func testEnvelopeWithData_WithAttachmentWithFileName() throws { @@ -539,7 +546,7 @@ class SentrySerializationTests: XCTestCase { XCTAssertNil(SentrySerialization.session(with: data)) } - func testSerializeReplayRecording() { + func testSerializeReplayRecording() throws { class MockReplayRecording: SentryReplayRecording { override func serialize() -> [[String: Any]] { return [["KEY": "VALUE"]] @@ -548,17 +555,53 @@ class SentrySerializationTests: XCTestCase { let date = Date(timeIntervalSince1970: 2) let recording = MockReplayRecording(segmentId: 5, size: 5_000, start: date, duration: 5_000, frameCount: 5, frameRate: 1, height: 320, width: 950, extraEvents: []) - let data = SentrySerialization.data(with: recording) - + let data = try XCTUnwrap(recording.data()) + let serialized = String(data: data, encoding: .utf8) XCTAssertEqual(serialized, "{\"segment_id\":5}\n[{\"KEY\":\"VALUE\"}]") } - - func testLevelFromEventData() { + + func testDataWithReplayRecording_whenHeaderCanNotBeSerialized_shouldReturnNil() throws { + // -- Arrange -- + class MockReplayRecording: SentryReplayRecording { + override func headerForReplayRecording() -> [String: Any] { + // This will cause serialization to fail, because NSObject cannot be serialized to JSON + return ["KEY": NSObject()] + } + } + + let recording = MockReplayRecording(segmentId: 5, size: 5_000, start: Date(timeIntervalSince1970: 2), duration: 5_000, frameCount: 5, frameRate: 1, height: 320, width: 950, extraEvents: []) + + // -- Act -- + let result = recording.data() + + // -- Assert -- + XCTAssertNil(result, "Data serialization should return nil when the header cannot be serialized.") + } + + func testDataWithReplayRecording_whenRecordingCanNotBeSerialized_shouldReturnNil() throws { + // -- Arrange -- + class MockReplayRecording: SentryReplayRecording { + override func serialize() -> [[String: Any]] { + // This will cause serialization to fail, because NSObject cannot be serialized to JSON + return [["KEY": NSObject()]] + } + } + + let recording = MockReplayRecording(segmentId: 5, size: 5_000, start: Date(timeIntervalSince1970: 2), duration: 5_000, frameCount: 5, frameRate: 1, height: 320, width: 950, extraEvents: []) + + // -- Act -- + let result = recording.data() + + // -- Assert -- + XCTAssertNil(result, "Data serialization should return nil when the header cannot be serialized.") + } + + func testLevelFromEventData() throws { let envelopeItem = SentryEnvelopeItem(event: TestData.event) - let level = SentrySerialization.level(from: envelopeItem.data) + let level = try SentrySerialization.level(from: XCTUnwrap(envelopeItem.data)) XCTAssertEqual(TestData.event.level, level) } @@ -582,6 +625,7 @@ class SentrySerializationTests: XCTestCase { XCTAssertNil(actual) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testReturnNilForCorruptedEnvelope() throws { let envelope = SentryEnvelope(event: Event(error: NSError(domain: "test", code: -1, userInfo: nil))) let data = try XCTUnwrap(SentrySerialization.data(with: envelope)) @@ -647,7 +691,7 @@ class SentrySerializationTests: XCTestCase { } private func assertDefaultSdkInfoSet(deserializedEnvelope: SentryEnvelope, file: StaticString = #file, line: UInt = #line) { - let sdkInfo = SentrySdkInfo(name: SentryMeta.sdkName, version: SentryMeta.versionString, integrations: [], features: [], packages: []) + let sdkInfo = SentrySdkInfo(name: SentryMeta.sdkName, version: SentryMeta.versionString, integrations: [], features: [], packages: [], settings: SentrySDKSettings(dict: [:])) XCTAssertEqual(sdkInfo, deserializedEnvelope.header.sdkInfo, file: file, line: line) } diff --git a/Tests/SentryTests/Helper/SentryTestObjCRuntimeWrapper.h b/Tests/SentryTests/Helper/SentryTestObjCRuntimeWrapper.h index 4f79d9e360b..37777713349 100644 --- a/Tests/SentryTests/Helper/SentryTestObjCRuntimeWrapper.h +++ b/Tests/SentryTests/Helper/SentryTestObjCRuntimeWrapper.h @@ -1,5 +1,5 @@ #import "SentryDefines.h" -#import "SentryObjCRuntimeWrapper.h" +@import Sentry; /** * Written in ObjC, because dealing with the pointers in Swift is super complicated. diff --git a/Tests/SentryTests/Helper/SentryTestObjCRuntimeWrapper.m b/Tests/SentryTests/Helper/SentryTestObjCRuntimeWrapper.m index a301c532ab0..5fc96849b67 100644 --- a/Tests/SentryTests/Helper/SentryTestObjCRuntimeWrapper.m +++ b/Tests/SentryTests/Helper/SentryTestObjCRuntimeWrapper.m @@ -1,10 +1,14 @@ #import "SentryTestObjCRuntimeWrapper.h" -#import "SentryDefaultObjCRuntimeWrapper.h" +#import "SentryDependencyContainer.h" +#import "SentryInternalDefines.h" +#import "SentrySwift.h" #import +@protocol SentryObjCRuntimeWrapper; + @interface SentryTestObjCRuntimeWrapper () -@property (nonatomic, strong) SentryDefaultObjCRuntimeWrapper *objcRuntimeWrapper; +@property (nonatomic, strong) id objcRuntimeWrapper; @end @@ -13,7 +17,7 @@ @implementation SentryTestObjCRuntimeWrapper - (instancetype)init { if (self = [super init]) { - self.objcRuntimeWrapper = [SentryDefaultObjCRuntimeWrapper sharedInstance]; + self.objcRuntimeWrapper = [[SentryDependencyContainer sharedInstance] objcRuntimeWrapper]; } return self; @@ -24,7 +28,14 @@ - (const char **)copyClassNamesForImage:(const char *)image amount:(unsigned int if (self.beforeGetClassList != nil) { self.beforeGetClassList(); } - const char **result = [self.objcRuntimeWrapper copyClassNamesForImage:image amount:outCount]; + + if (image == nil) { + return nil; + } + + const char **result = + [self.objcRuntimeWrapper copyClassNamesForImage:SENTRY_UNWRAP_NULLABLE(const char, image) + amount:outCount]; if (self.classesNames != nil) { NSMutableArray *names = [NSMutableArray new]; diff --git a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1IntegrationTests.swift b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1IntegrationTests.swift index 3c7430e37e9..a4a63780a64 100644 --- a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1IntegrationTests.swift +++ b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1IntegrationTests.swift @@ -14,7 +14,7 @@ final class SentryANRTrackerV1IntegrationTests: XCTestCase { let anrTracker: SentryANRTracker = SentryANRTrackerV1( timeoutInterval: 0.01, - crashWrapper: TestSentryCrashWrapper.sharedInstance(), + crashWrapper: TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo), dispatchQueueWrapper: SentryDispatchQueueWrapper(), threadWrapper: SentryThreadWrapper()) as! SentryANRTracker diff --git a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1Tests.swift b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1Tests.swift index 4d15d71eefe..164caeaa2f8 100644 --- a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1Tests.swift +++ b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1Tests.swift @@ -9,7 +9,7 @@ class SentryANRTrackerV1Tests: XCTestCase, SentryANRTrackerDelegate { private var fixture: Fixture! private var anrDetectedExpectation: XCTestExpectation! private var anrStoppedExpectation: XCTestExpectation! - private let waitTimeout: TimeInterval = 2.0 + private let waitTimeout: TimeInterval = 5.0 private var lastANRStoppedResult: SentryANRStoppedResult? private class Fixture { @@ -20,7 +20,7 @@ class SentryANRTrackerV1Tests: XCTestCase, SentryANRTrackerDelegate { let threadWrapper = SentryTestThreadWrapper() init() { - crashWrapper = TestSentryCrashWrapper.sharedInstance() + crashWrapper = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo) SentryDependencyContainer.sharedInstance().dateProvider = currentDate } } diff --git a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV2Tests.swift b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV2Tests.swift index 00027165c63..0cf2c86d790 100644 --- a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV2Tests.swift +++ b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV2Tests.swift @@ -5,14 +5,14 @@ import XCTest #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) class SentryANRTrackerV2Tests: XCTestCase { - private let waitTimeout: TimeInterval = 5.0 + private let waitTimeout: TimeInterval = 10.0 private var timeoutInterval: TimeInterval = 2 private func getSut() throws -> (SentryANRTracker, TestCurrentDateProvider, TestDisplayLinkWrapper, TestSentryCrashWrapper, SentryTestThreadWrapper, SentryFramesTracker) { let currentDate = TestCurrentDateProvider() - let crashWrapper = TestSentryCrashWrapper.sharedInstance() + let crashWrapper = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo) let dispatchQueue = TestSentryDispatchQueueWrapper() let threadWrapper = SentryTestThreadWrapper() diff --git a/Tests/SentryTests/Integrations/ANR/SentryANRTrackingIntegrationTests.swift b/Tests/SentryTests/Integrations/ANR/SentryANRTrackingIntegrationTests.swift index 500ae6af3b5..c4c51c59a6a 100644 --- a/Tests/SentryTests/Integrations/ANR/SentryANRTrackingIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/ANR/SentryANRTrackingIntegrationTests.swift @@ -324,13 +324,11 @@ class SentryANRTrackingIntegrationTests: SentrySDKIntegrationTestsBase { #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) func testANRDetected_ButBackground_EventNotCaptured() { - class BackgroundSentryUIApplication: SentryUIApplication { - override var applicationState: UIApplication.State { .background } - } - givenInitializedTracker() setUpThreadInspector() - SentryDependencyContainer.sharedInstance().application = BackgroundSentryUIApplication(notificationCenterWrapper: TestNSNotificationCenterWrapper(), dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) + let backgroundUIApplication = TestSentryUIApplication() + backgroundUIApplication.unsafeApplicationState = .background + SentryDependencyContainer.sharedInstance().application = backgroundUIApplication Dynamic(sut).anrDetectedWithType(SentryANRType.unknown) @@ -495,7 +493,7 @@ class SentryANRTrackingIntegrationTests: SentrySDKIntegrationTestsBase { setUpThreadInspector() Dynamic(sut).anrDetectedWithType(SentryANRType.fullyBlocking) - SentrySDK.currentHub().client()?.fileManager.storeAppHang(Event()) + SentrySDKInternal.currentHub().client()?.fileManager.storeAppHang(Event()) // Act let result = SentryANRStoppedResult(minDuration: 1.851, maxDuration: 2.249) @@ -593,13 +591,13 @@ class SentryANRTrackingIntegrationTests: SentrySDKIntegrationTestsBase { let abnormalSession = SentrySession(releaseName: "release", distinctId: "distinct") abnormalSession.endAbnormal(withTimestamp: fixture.currentDate.date()) - SentrySDK.currentHub().client()?.fileManager.storeAbnormalSession(abnormalSession) + SentrySDKInternal.currentHub().client()?.fileManager.storeAbnormalSession(abnormalSession) // Act givenInitializedTracker(enableV2: true) // Assert - let client = try XCTUnwrap(SentrySDK.currentHub().getClient() as? TestClient) + let client = try XCTUnwrap(SentrySDKInternal.currentHub().getClient() as? TestClient) XCTAssertEqual(1, client.captureFatalEventWithSessionInvocations.count, "Wrong number of `Crashs` captured.") let capture = try XCTUnwrap(client.captureFatalEventWithSessionInvocations.first) @@ -656,7 +654,7 @@ class SentryANRTrackingIntegrationTests: SentrySDKIntegrationTestsBase { // Arrange givenInitializedTracker(enableV2: true) let event = Event() - SentrySDK.currentHub().client()?.fileManager.storeAppHang(event) + SentrySDKInternal.currentHub().client()?.fileManager.storeAppHang(event) // Act givenInitializedTracker(enableV2: true) @@ -688,7 +686,7 @@ class SentryANRTrackingIntegrationTests: SentrySDKIntegrationTestsBase { givenInitializedTracker(enableV2: true) setUpThreadInspector() Dynamic(sut).anrDetectedWithType(SentryANRType.nonFullyBlocking) - SentrySDK.currentHub().client()?.fileManager.deleteAppHangEvent() + SentrySDKInternal.currentHub().client()?.fileManager.deleteAppHangEvent() // Act let result = SentryANRStoppedResult(minDuration: 1.8, maxDuration: 2.2) @@ -776,6 +774,6 @@ class SentryANRTrackingIntegrationTests: SentrySDKIntegrationTestsBase { threadInspector.allThreads = [] } - SentrySDK.currentHub().getClient()?.threadInspector = threadInspector + SentrySDKInternal.currentHub().getClient()?.threadInspector = threadInspector } } diff --git a/Tests/SentryTests/Integrations/Breadcrumbs/SentryAutoBreadcrumbTrackingIntegrationTests.swift b/Tests/SentryTests/Integrations/Breadcrumbs/SentryAutoBreadcrumbTrackingIntegrationTests.swift index 43e211bb744..4adaff68240 100644 --- a/Tests/SentryTests/Integrations/Breadcrumbs/SentryAutoBreadcrumbTrackingIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Breadcrumbs/SentryAutoBreadcrumbTrackingIntegrationTests.swift @@ -1,26 +1,42 @@ -import Sentry -import SentryTestUtils +@testable import Sentry +@_spi(Private) import SentryTestUtils import XCTest class SentryAutoBreadcrumbTrackingIntegrationTests: XCTestCase { private class Fixture { + private let dateProvider = TestCurrentDateProvider() + private let dispatchQueueWrapper = TestSentryDispatchQueueWrapper() + + let fileManager: TestFileManager + let breadcrumbTracker = SentryTestBreadcrumbTracker() #if os(iOS) var systemEventBreadcrumbTracker: SentryTestSystemEventBreadcrumbs? #endif // os(iOS) - + + init() throws { + let options = Options() + options.dsn = TestConstants.dsnForTestCase(type: SentryAutoBreadcrumbTrackingIntegrationTests.self) + + fileManager = try TestFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: dispatchQueueWrapper + ) + } + var sut: SentryAutoBreadcrumbTrackingIntegration { return SentryAutoBreadcrumbTrackingIntegration() } } private var fixture: Fixture! - - override func setUp() { - super.setUp() - fixture = Fixture() + + override func setUpWithError() throws { + try super.setUpWithError() + fixture = try Fixture() } override func tearDown() { @@ -70,7 +86,7 @@ class SentryAutoBreadcrumbTrackingIntegrationTests: XCTestCase { let scope = Scope() let hub = SentryHub(client: TestClient(options: Options()), andScope: scope) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) let crumb = TestData.crumb fixture.systemEventBreadcrumbTracker?.startWithDelegateInvocations.first?.add(crumb) @@ -92,7 +108,7 @@ class SentryAutoBreadcrumbTrackingIntegrationTests: XCTestCase { private func install(sut: SentryAutoBreadcrumbTrackingIntegration, options: Options = Options()) throws { #if os(iOS) - fixture.systemEventBreadcrumbTracker = SentryTestSystemEventBreadcrumbs(fileManager: try TestFileManager(options: options), andNotificationCenterWrapper: TestNSNotificationCenterWrapper()) + fixture.systemEventBreadcrumbTracker = SentryTestSystemEventBreadcrumbs(fileManager: fixture.fileManager, andNotificationCenterWrapper: TestNSNotificationCenterWrapper()) sut.install(with: options, breadcrumbTracker: fixture.breadcrumbTracker, systemEventBreadcrumbs: fixture.systemEventBreadcrumbTracker!) #else sut.install(with: options, breadcrumbTracker: fixture.breadcrumbTracker) diff --git a/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift b/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift index bdf346985fd..a1f6285b654 100644 --- a/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift @@ -100,7 +100,7 @@ class SentryBreadcrumbTrackerTests: XCTestCase { let scope = Scope() let client = TestClient(options: Options()) let hub = TestHub(client: client, andScope: scope) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) let sut = SentryBreadcrumbTracker() sut.start(with: delegate) @@ -167,7 +167,7 @@ class SentryBreadcrumbTrackerTests: XCTestCase { let scope = Scope() let client = TestClient(options: Options()) let hub = TestHub(client: client, andScope: scope) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) let tracker = SentryBreadcrumbTracker() tracker.start(with: delegate) @@ -211,7 +211,7 @@ class SentryBreadcrumbTrackerTests: XCTestCase { let scope = Scope() let client = TestClient(options: Options()) let hub = TestHub(client: client, andScope: scope) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) let swizzlingWrapper = TestSentrySwizzleWrapper() SentryDependencyContainer.sharedInstance().swizzleWrapper = swizzlingWrapper @@ -240,7 +240,7 @@ class SentryBreadcrumbTrackerTests: XCTestCase { let scope = Scope() let client = TestClient(options: Options()) let hub = TestHub(client: client, andScope: scope) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) let swizzlingWrapper = TestSentrySwizzleWrapper() SentryDependencyContainer.sharedInstance().swizzleWrapper = swizzlingWrapper @@ -268,7 +268,7 @@ class SentryBreadcrumbTrackerTests: XCTestCase { let scope = Scope() let client = TestClient(options: Options()) let hub = TestHub(client: client, andScope: scope) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) let swizzlingWrapper = TestSentrySwizzleWrapper() SentryDependencyContainer.sharedInstance().swizzleWrapper = swizzlingWrapper @@ -295,7 +295,7 @@ class SentryBreadcrumbTrackerTests: XCTestCase { let scope = Scope() let client = TestClient(options: Options()) let hub = TestHub(client: client, andScope: scope) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) let sut = SentryBreadcrumbTracker() sut.start(with: delegate) diff --git a/Tests/SentryTests/Integrations/Breadcrumbs/SentrySystemEventBreadcrumbsTest.swift b/Tests/SentryTests/Integrations/Breadcrumbs/SentrySystemEventBreadcrumbsTest.swift index 08c2ac208ee..0c9125619dc 100644 --- a/Tests/SentryTests/Integrations/Breadcrumbs/SentrySystemEventBreadcrumbsTest.swift +++ b/Tests/SentryTests/Integrations/Breadcrumbs/SentrySystemEventBreadcrumbsTest.swift @@ -14,7 +14,7 @@ class SentrySystemEventBreadcrumbsTest: XCTestCase { var currentDateProvider = TestCurrentDateProvider() let notificationCenterWrapper = TestNSNotificationCenterWrapper() - init() { + init() throws { options = Options() options.dsn = TestConstants.dsnAsString(username: "SentrySystemEventBreadcrumbsTest") options.releaseName = "SentrySessionTrackerIntegrationTests" @@ -22,7 +22,11 @@ class SentrySystemEventBreadcrumbsTest: XCTestCase { options.environment = "debug" SentryDependencyContainer.sharedInstance().dateProvider = currentDateProvider - fileManager = try! TestFileManager(options: options) + fileManager = try TestFileManager( + options: options, + dateProvider: currentDateProvider, + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ) } func getSut(currentDevice: UIDevice? = UIDevice.current) -> SentrySystemEventBreadcrumbs { @@ -61,9 +65,9 @@ class SentrySystemEventBreadcrumbsTest: XCTestCase { private var fixture: Fixture! private var sut: SentrySystemEventBreadcrumbs! - override func setUp() { - super.setUp() - fixture = Fixture() + override func setUpWithError() throws { + try super.setUpWithError() + fixture = try Fixture() } override func tearDown() { @@ -324,10 +328,37 @@ class SentrySystemEventBreadcrumbsTest: XCTestCase { } } + func testSignificantTimeChangeNotificationBreadcrumb() throws { + sut = fixture.getSut(currentDevice: nil) + + fixture.notificationCenterWrapper.post(Notification(name: UIApplication.significantTimeChangeNotification, object: nil)) + + XCTAssertEqual(1, fixture.delegate.addCrumbInvocations.count) + + let crumb = try XCTUnwrap(fixture.delegate.addCrumbInvocations.first) + + XCTAssertEqual("device.event", crumb.category) + XCTAssertEqual("system", crumb.type) + XCTAssertEqual(SentryLevel.info, crumb.level) + + let data = try XCTUnwrap(crumb.data, "no breadcrumb.data") + XCTAssertEqual("SIGNIFICANT_TIME_CHANGE", data["action"] as? String) + } + + func testSignificantTimeChangeNotificationBreadcrumb_UnsubscribeOnStop() { + sut = fixture.getSut(currentDevice: nil) + + sut.stop() + + let didCallRemoveObserver = fixture.notificationCenterWrapper.removeObserverWithNameAndObjectInvocations.invocations.filter { $0.name == UIApplication.significantTimeChangeNotification }.count == 1 + + XCTAssertTrue(didCallRemoveObserver, "Stop didn't call remove observer for UIApplicationSignificantTimeChangeNotification") + } + func testStopCallsSpecificRemoveObserverMethods() { sut = fixture.getSut(currentDevice: nil) sut.stop() - XCTAssertEqual(fixture.notificationCenterWrapper.removeObserverWithNameInvocations.count, 7) + XCTAssertEqual(fixture.notificationCenterWrapper.removeObserverWithNameAndObjectInvocations.count, 7) } private func postBatteryLevelNotification(uiDevice: UIDevice?) { diff --git a/Tests/SentryTests/Integrations/Feedback/SentryFeedbackTests.swift b/Tests/SentryTests/Integrations/Feedback/SentryFeedbackTests.swift index b0df12c258b..92bdb321d0a 100644 --- a/Tests/SentryTests/Integrations/Feedback/SentryFeedbackTests.swift +++ b/Tests/SentryTests/Integrations/Feedback/SentryFeedbackTests.swift @@ -190,6 +190,141 @@ class SentryFeedbackTests: XCTestCase { } } + + func testFeedbackNotSubjectToSampling() throws { + let options = Options() + options.dsn = TestConstants.dsnAsString(username: "SentryFeedbackTests") + options.sampleRate = 0.0 // Sample rate that would normally filter out all events + + let transport = TestTransport() + let transportAdapter = TestTransportAdapter(transports: [transport], options: options) + + let client = SentryClient( + options: options, + transportAdapter: transportAdapter, + fileManager: try XCTUnwrap(SentryFileManager( + options: options, + dateProvider: TestCurrentDateProvider(), + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + )), + deleteOldEnvelopeItems: false, + threadInspector: TestThreadInspector.instance, + debugImageProvider: TestDebugImageProvider(), + random: TestRandom(value: 1.0), + locale: Locale(identifier: "en_US"), + timezone: try XCTUnwrap(TimeZone(identifier: "Europe/Vienna")) + ) + let hub = TestHub(client: client, andScope: nil) + + SentrySDKInternal.setCurrentHub(hub) + + let feedback = SentryFeedback( + message: "Test feedback message", + name: "Test User", + email: "test@example.com", + source: .widget + ) + + SentrySDK.capture(feedback: feedback) + + // Verify that the feedback was captured and sent despite the 0.0 sample rate + let lastSentEventArguments = try XCTUnwrap(transportAdapter.sendEventWithTraceStateInvocations.last) + let capturedFeedback = try XCTUnwrap(lastSentEventArguments.event) + + XCTAssertEqual(capturedFeedback.type, SentryEnvelopeItemTypes.feedback) + } + + func testFeedbackNotSubjectToBeforeSendFiltering() throws { + let options = Options() + options.dsn = TestConstants.dsnAsString(username: "SentryFeedbackTests") + options.beforeSend = { _ in return nil } // beforeSend that filters out all events + + let transport = TestTransport() + let transportAdapter = TestTransportAdapter(transports: [transport], options: options) + + let client = SentryClient( + options: options, + transportAdapter: transportAdapter, + fileManager: try XCTUnwrap(SentryFileManager( + options: options, + dateProvider: TestCurrentDateProvider(), + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + )), + deleteOldEnvelopeItems: false, + threadInspector: TestThreadInspector.instance, + debugImageProvider: TestDebugImageProvider(), + random: TestRandom(value: 1.0), + locale: Locale(identifier: "en_US"), + timezone: try XCTUnwrap(TimeZone(identifier: "Europe/Vienna")) + ) + let hub = TestHub(client: client, andScope: nil) + SentrySDKInternal.setCurrentHub(hub) + + let feedback = SentryFeedback( + message: "Test feedback message", + name: "Test User", + email: "test@example.com", + source: .widget + ) + + SentrySDK.capture(feedback: feedback) + + // Verify that the feedback was captured and sent despite beforeSend returning nil + let lastSentEventArguments = try XCTUnwrap(transportAdapter.sendEventWithTraceStateInvocations.last) + let capturedFeedback = try XCTUnwrap(lastSentEventArguments.event) + + XCTAssertEqual(capturedFeedback.type, SentryEnvelopeItemTypes.feedback) + } + + func testFeedbackWithSamplingAndBeforeSendFilteringCombined() throws { + let options = Options() + options.dsn = TestConstants.dsnAsString(username: "SentryFeedbackTests") + options.sampleRate = 0.5 // Partial sampling + options.beforeSend = { _ in return nil } // beforeSend that filters out all events + + let transport = TestTransport() + let transportAdapter = TestTransportAdapter(transports: [transport], options: options) + + let client = SentryClient( + options: options, + transportAdapter: transportAdapter, + fileManager: try XCTUnwrap(SentryFileManager( + options: options, + dateProvider: TestCurrentDateProvider(), + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + )), + deleteOldEnvelopeItems: false, + threadInspector: TestThreadInspector.instance, + debugImageProvider: TestDebugImageProvider(), + random: TestRandom(value: 1.0), + locale: Locale(identifier: "en_US"), + timezone: try XCTUnwrap(TimeZone(identifier: "Europe/Vienna")) + ) + let hub = TestHub(client: client, andScope: nil) + SentrySDKInternal.setCurrentHub(hub) + + struct UserInfo { + var email: String? + } + + let userInfo = UserInfo(email: nil) + let emailString = String(userInfo.email ?? "newanonymous@example.com") + + let feedback = SentryFeedback( + message: "messageString", + name: "nameString", + email: emailString, + source: .widget + ) + + SentrySDK.capture(feedback: feedback) + + // Verify that the feedback was captured and sent despite both sampling and beforeSend filtering + let lastSentEventArguments = try XCTUnwrap(transportAdapter.sendEventWithTraceStateInvocations.last) + let capturedFeedback = try XCTUnwrap(lastSentEventArguments.event) + + XCTAssertEqual(capturedFeedback.type, SentryEnvelopeItemTypes.feedback) + } } #endif // os(iOS) && !SENTRY_NO_UIKIT diff --git a/Tests/SentryTests/Integrations/MetricKit/SentryMetricKitIntegrationTests.swift b/Tests/SentryTests/Integrations/MetricKit/SentryMetricKitIntegrationTests.swift index 7e654524ad4..94c145768ba 100644 --- a/Tests/SentryTests/Integrations/MetricKit/SentryMetricKitIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/MetricKit/SentryMetricKitIntegrationTests.swift @@ -1,5 +1,5 @@ @_spi(Private) @testable import Sentry -import SentryTestUtils +@_spi(Private) import SentryTestUtils import XCTest #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) @@ -185,7 +185,7 @@ final class SentryMetricKitIntegrationTests: SentrySDKIntegrationTestsBase { let mxDelegate = sut as! SentryMXManagerDelegate mxDelegate.didReceiveCpuExceptionDiagnostic(TestMXCPUExceptionDiagnostic(), callStackTree: callStackTree, timeStampBegin: timeStampBegin, timeStampEnd: timeStampEnd) - guard let client = SentrySDK.currentHub().getClient() as? TestClient else { + guard let client = SentrySDKInternal.currentHub().getClient() as? TestClient else { XCTFail("Hub Client is not a `TestClient`") return } @@ -270,7 +270,7 @@ final class SentryMetricKitIntegrationTests: SentrySDKIntegrationTestsBase { } private func assertNothingCaptured() { - guard let client = SentrySDK.currentHub().getClient() as? TestClient else { + guard let client = SentrySDKInternal.currentHub().getClient() as? TestClient else { XCTFail("Hub Client is not a `TestClient`") return } @@ -279,7 +279,7 @@ final class SentryMetricKitIntegrationTests: SentrySDKIntegrationTestsBase { } private func assertNotPerThread(exceptionType: String, exceptionValue: String, exceptionMechanism: String) throws { - guard let client = SentrySDK.currentHub().getClient() as? TestClient else { + guard let client = SentrySDKInternal.currentHub().getClient() as? TestClient else { XCTFail("Hub Client is not a `TestClient`") return } diff --git a/Tests/SentryTests/Integrations/Performance/AppStartTracking/SentryAppStartTrackerTests.swift b/Tests/SentryTests/Integrations/Performance/AppStartTracking/SentryAppStartTrackerTests.swift index b1387d24c0e..3b50ba25efb 100644 --- a/Tests/SentryTests/Integrations/Performance/AppStartTracking/SentryAppStartTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Performance/AppStartTracking/SentryAppStartTrackerTests.swift @@ -13,7 +13,7 @@ class SentryAppStartTrackerTests: NotificationCenterTestCase { let currentDate = TestCurrentDateProvider() let sysctl = TestSysctl() let fileManager: SentryFileManager - let crashWrapper = TestSentryCrashWrapper.sharedInstance() + let crashWrapper = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo) let appStateManager: SentryAppStateManager var displayLinkWrapper = TestDisplayLinkWrapper() private let framesTracker: SentryFramesTracker @@ -34,7 +34,11 @@ class SentryAppStartTrackerTests: NotificationCenterTestCase { SentryDependencyContainer.sharedInstance().dateProvider = currentDate - fileManager = try! SentryFileManager(options: options, dispatchQueueWrapper: dispatchQueue) + fileManager = try! SentryFileManager( + options: options, + dateProvider: currentDate, + dispatchQueueWrapper: dispatchQueue + ) SentryDependencyContainer.sharedInstance().sysctlWrapper = sysctl @@ -43,7 +47,7 @@ class SentryAppStartTrackerTests: NotificationCenterTestCase { crashWrapper: crashWrapper, fileManager: fileManager, dispatchQueueWrapper: dispatchQueue, - notificationCenterWrapper: SentryNSNotificationCenterWrapper() + notificationCenterWrapper: NotificationCenter.default ) framesTracker = SentryFramesTracker(displayLinkWrapper: displayLinkWrapper, dateProvider: currentDate, dispatchQueueWrapper: TestSentryDispatchQueueWrapper(), @@ -53,7 +57,7 @@ class SentryAppStartTrackerTests: NotificationCenterTestCase { runtimeInitTimestamp = SentryDependencyContainer.sharedInstance().dateProvider.date().addingTimeInterval(0.2) moduleInitializationTimestamp = SentryDependencyContainer.sharedInstance().dateProvider.date().addingTimeInterval(0.1) sdkStartTimestamp = SentryDependencyContainer.sharedInstance().dateProvider.date().addingTimeInterval(0.1) - SentrySDK.startTimestamp = sdkStartTimestamp + SentrySDKInternal.startTimestamp = sdkStartTimestamp didFinishLaunchingTimestamp = SentryDependencyContainer.sharedInstance().dateProvider.date().addingTimeInterval(0.2) } @@ -424,11 +428,11 @@ class SentryAppStartTrackerTests: NotificationCenterTestCase { * We assume a class reads the app measurement, sends it with a transaction to Sentry and sets it to nil. */ private func sendAppMeasurement() { - SentrySDK.setAppStartMeasurement(nil) + SentrySDKInternal.setAppStartMeasurement(nil) } private func assertValidStart(type: SentryAppStartType, expectedDuration: TimeInterval? = nil, preWarmed: Bool = false) { - guard let appStartMeasurement = SentrySDK.getAppStartMeasurement() else { + guard let appStartMeasurement = SentrySDKInternal.getAppStartMeasurement() else { XCTFail("AppStartMeasurement must not be nil") return } @@ -454,7 +458,7 @@ class SentryAppStartTrackerTests: NotificationCenterTestCase { } private func assertValidHybridStart(type: SentryAppStartType) { - guard let appStartMeasurement = SentrySDK.getAppStartMeasurement() else { + guard let appStartMeasurement = SentrySDKInternal.getAppStartMeasurement() else { XCTFail("AppStartMeasurement must not be nil") return } @@ -470,7 +474,7 @@ class SentryAppStartTrackerTests: NotificationCenterTestCase { } private func assertNoAppStartUp() { - XCTAssertNil(SentrySDK.getAppStartMeasurement()) + XCTAssertNil(SentrySDKInternal.getAppStartMeasurement()) } private func advanceTime(bySeconds: TimeInterval) { diff --git a/Tests/SentryTests/Integrations/Performance/AppStartTracking/SentryAppStartTrackingIntegrationTests.swift b/Tests/SentryTests/Integrations/Performance/AppStartTracking/SentryAppStartTrackingIntegrationTests.swift index 3b82d3e5562..270574fe582 100644 --- a/Tests/SentryTests/Integrations/Performance/AppStartTracking/SentryAppStartTrackingIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Performance/AppStartTracking/SentryAppStartTrackingIntegrationTests.swift @@ -7,15 +7,22 @@ import XCTest class SentryAppStartTrackingIntegrationTests: NotificationCenterTestCase { private class Fixture { + private let dateProvider = TestCurrentDateProvider() + private let dispatchQueueWrapper = TestSentryDispatchQueueWrapper() + let options = Options() let fileManager: SentryFileManager - init() { + init() throws { options.tracesSampleRate = 0.1 options.tracesSampler = { _ in return 0 } options.dsn = TestConstants.dsnAsString(username: "SentryAppStartTrackingIntegrationTests") - fileManager = try! TestFileManager(options: options) + fileManager = try TestFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: dispatchQueueWrapper + ) } } @@ -28,10 +35,10 @@ class SentryAppStartTrackingIntegrationTests: NotificationCenterTestCase { clearTestState() } - override func setUp() { - super.setUp() - fixture = Fixture() - SentrySDK.setAppStartMeasurement(nil) + override func setUpWithError() throws { + try super.setUpWithError() + fixture = try Fixture() + SentrySDKInternal.setAppStartMeasurement(nil) sut = SentryAppStartTrackingIntegration() } @@ -39,7 +46,7 @@ class SentryAppStartTrackingIntegrationTests: NotificationCenterTestCase { super.tearDown() fixture.fileManager.deleteAppState() PrivateSentrySDKOnly.appStartMeasurementHybridSDKMode = false - SentrySDK.setAppStartMeasurement(nil) + SentrySDKInternal.setAppStartMeasurement(nil) sut.stop() clearTestState() } diff --git a/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackerTest.swift b/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackerTest.swift index a1d0dd4a49d..5ffbbea329b 100644 --- a/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackerTest.swift +++ b/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackerTest.swift @@ -1,6 +1,6 @@ import CoreData @testable import Sentry -import SentryTestUtils +@_spi(Private) import SentryTestUtils import XCTest class SentryCoreDataTrackerTests: XCTestCase { @@ -24,7 +24,7 @@ class SentryCoreDataTrackerTests: XCTestCase { SentryDependencyContainer.sharedInstance().debugImageProvider = imageProvider threadInspector.allThreads = [TestData.thread2] - let processInfoWrapper = TestSentryNSProcessInfoWrapper() + let processInfoWrapper = MockSentryProcessInfo() processInfoWrapper.overrides.processDirectoryPath = "sentrytest" return SentryCoreDataTracker(threadInspector: threadInspector, processInfoWrapper: processInfoWrapper) diff --git a/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackingIntegrationTest.swift b/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackingIntegrationTest.swift index 8653ae43438..d422b02dcf4 100644 --- a/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackingIntegrationTest.swift +++ b/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackingIntegrationTest.swift @@ -9,6 +9,7 @@ class SentryCoreDataTrackingIntegrationTests: XCTestCase { let options: Options let coreDataStack: TestCoreDataStack + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") init(testName: String) { coreDataStack = TestCoreDataStack(databaseFilename: "db-\(testName.hashValue).sqlite") options = Options() @@ -24,6 +25,7 @@ class SentryCoreDataTrackingIntegrationTests: XCTestCase { private var fixture: Fixture! + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") override func setUp() { super.setUp() fixture = Fixture(testName: self.name) diff --git a/Tests/SentryTests/Integrations/Performance/CoreData/TestCoreDataStack.swift b/Tests/SentryTests/Integrations/Performance/CoreData/TestCoreDataStack.swift index 18b1895cdac..07f5a4a3bf6 100644 --- a/Tests/SentryTests/Integrations/Performance/CoreData/TestCoreDataStack.swift +++ b/Tests/SentryTests/Integrations/Performance/CoreData/TestCoreDataStack.swift @@ -98,14 +98,14 @@ class TestCoreDataStack { return obj } - func saveContext () { + func saveContext() { if managedObjectContext.hasChanges { try? managedObjectContext.save() } } } -class TestNSManagedObjectContext: NSManagedObjectContext { +class TestNSManagedObjectContext: NSManagedObjectContext, @unchecked Sendable { var inserted: Set? var updated: Set? diff --git a/Tests/SentryTests/Integrations/Performance/CoreData/TestModel.xcdatamodeld/TestModel.xcdatamodel/contents b/Tests/SentryTests/Integrations/Performance/CoreData/TestModel.xcdatamodeld/TestModel.xcdatamodel/contents index a5218622e8d..896a919d7bf 100644 --- a/Tests/SentryTests/Integrations/Performance/CoreData/TestModel.xcdatamodeld/TestModel.xcdatamodel/contents +++ b/Tests/SentryTests/Integrations/Performance/CoreData/TestModel.xcdatamodeld/TestModel.xcdatamodel/contents @@ -7,4 +7,4 @@ - \ No newline at end of file + diff --git a/Tests/SentryTests/Integrations/Performance/FramesTracking/SentryFramesTrackerTests.swift b/Tests/SentryTests/Integrations/Performance/FramesTracking/SentryFramesTrackerTests.swift index 89409568d97..448c5623cc0 100644 --- a/Tests/SentryTests/Integrations/Performance/FramesTracking/SentryFramesTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Performance/FramesTracking/SentryFramesTrackerTests.swift @@ -9,7 +9,6 @@ class SentryFramesTrackerTests: XCTestCase { private class Fixture { var displayLinkWrapper: TestDisplayLinkWrapper - var queue: DispatchQueue var dateProvider = TestCurrentDateProvider() var notificationCenter = TestNSNotificationCenterWrapper() let keepDelayedFramesDuration = 10.0 @@ -18,8 +17,7 @@ class SentryFramesTrackerTests: XCTestCase { init() { displayLinkWrapper = TestDisplayLinkWrapper(dateProvider: dateProvider) - queue = DispatchQueue(label: "SentryFramesTrackerTests", qos: .background, attributes: [.concurrent]) - + slowestSlowFrameDelay = (displayLinkWrapper.slowestSlowFrameDuration - slowFrameThreshold(displayLinkWrapper.currentFrameRate.rawValue)) } @@ -62,7 +60,7 @@ class SentryFramesTrackerTests: XCTestCase { sut.start() sut.start() - XCTAssertEqual(self.fixture.notificationCenter.addObserverInvocations.invocations.count, 2) + XCTAssertEqual(self.fixture.notificationCenter.addObserverWithObjectInvocations.invocations.count, 2) } func testIsNotRunning_WhenStopped() { @@ -79,7 +77,7 @@ class SentryFramesTrackerTests: XCTestCase { sut.stop() sut.stop() - XCTAssertEqual(self.fixture.notificationCenter.removeObserverWithNameInvocations.invocations.count, 2) + XCTAssertEqual(self.fixture.notificationCenter.removeObserverWithNameAndObjectInvocations.invocations.count, 2) } func testKeepFrames_WhenStopped() throws { @@ -710,6 +708,132 @@ class SentryFramesTrackerTests: XCTestCase { XCTAssertEqual(sut.isRunning, true) } + func testUnpause_ResetsPreviousFrameTimestamp_ToAvoidWrongMetrics() throws { + let sut = fixture.sut + sut.start() + + // Simulate some frames to establish a previous frame timestamp + fixture.displayLinkWrapper.call() + fixture.displayLinkWrapper.normalFrame() + fixture.displayLinkWrapper.normalFrame() + + // Pause the tracker + fixture.notificationCenter.post(Notification(name: CrossPlatformApplication.willResignActiveNotification)) + + // Verify it's paused + XCTAssertFalse(sut.isRunning) + + // Unpause and verify the previous frame timestamp is reset + fixture.notificationCenter.post(Notification(name: CrossPlatformApplication.didBecomeActiveNotification)) + XCTAssertTrue(sut.isRunning) + + // The next frame should be treated as the first frame (previousFrameTimestamp == SentryPreviousFrameInitialValue) + // This means it won't be classified as slow/frozen even if there was a long pause + fixture.displayLinkWrapper.call() + + // Should not detect any slow or frozen frames after unpausing + try assert(slow: 0, frozen: 0, total: 2) + } + + func testUnpause_WhenAlreadyRunning_DoesNotResetTimestamp() throws { + let sut = fixture.sut + sut.start() + + // Simulate some frames + fixture.displayLinkWrapper.call() + fixture.displayLinkWrapper.normalFrame() + + // Try to unpause when already running + fixture.notificationCenter.post(Notification(name: CrossPlatformApplication.didBecomeActiveNotification)) + + // Should still be running + XCTAssertTrue(sut.isRunning) + + // Continue with normal frames + fixture.displayLinkWrapper.normalFrame() + + // Should have normal frame counting behavior + try assert(slow: 0, frozen: 0, total: 2) + } + + func testUnpause_AfterBackgroundForegroundTransition_ResetsTimestamp() throws { + let sut = fixture.sut + sut.start() + + // Simulate some frames + fixture.displayLinkWrapper.call() + fixture.displayLinkWrapper.normalFrame() + + // Simulate app going to background + fixture.notificationCenter.post(Notification(name: CrossPlatformApplication.willResignActiveNotification)) + XCTAssertFalse(sut.isRunning) + + // Simulate a long time in background + fixture.dateProvider.advance(by: 10.0) + + // Simulate app coming to foreground + fixture.notificationCenter.post(Notification(name: CrossPlatformApplication.didBecomeActiveNotification)) + XCTAssertTrue(sut.isRunning) + + // The next frame should not be classified as slow/frozen due to the long background time + fixture.displayLinkWrapper.call() + + // Should not detect any slow or frozen frames + try assert(slow: 0, frozen: 0, total: 1) + } + + func testUnpause_MultipleTimes_AlwaysResetsTimestamp() throws { + let sut = fixture.sut + sut.start() + + // Simulate some frames + fixture.displayLinkWrapper.call() + fixture.displayLinkWrapper.normalFrame() + + // Pause and unpause multiple times + for _ in 0..<3 { + fixture.notificationCenter.post(Notification(name: CrossPlatformApplication.willResignActiveNotification)) + fixture.dateProvider.advance(by: 2.0) // Long pause each time + fixture.notificationCenter.post(Notification(name: CrossPlatformApplication.didBecomeActiveNotification)) + + // Each unpause should reset the timestamp + fixture.displayLinkWrapper.call() + fixture.displayLinkWrapper.normalFrame() + } + + // Should not detect any slow or frozen frames from the pauses + try assert(slow: 0, frozen: 0, total: 4) + } + + func testUnpause_WithDelayedFramesTracker_ResetsPreviousFrameSystemTimestamp() { + let sut = fixture.sut + sut.start() + + // Simulate some frames to establish system timestamps + fixture.displayLinkWrapper.call() + fixture.displayLinkWrapper.normalFrame() + + // Pause the tracker + fixture.notificationCenter.post(Notification(name: CrossPlatformApplication.willResignActiveNotification)) + + // Advance time significantly + fixture.dateProvider.advance(by: 5.0) + + // Unpause the tracker + fixture.notificationCenter.post(Notification(name: CrossPlatformApplication.didBecomeActiveNotification)) + + // The delayed frames tracker should also have its previous frame system timestamp reset + // This prevents false delay calculations after unpausing + let startSystemTime = fixture.dateProvider.systemTime() + fixture.dateProvider.advance(by: 0.001) + let endSystemTime = fixture.dateProvider.systemTime() + + let frameDelay = sut.getFramesDelay(startSystemTime, endSystemTimestamp: endSystemTime) + + // Should not report any delay from the pause period + XCTAssertEqual(frameDelay.delayDuration, 0.001, accuracy: 0.0001) + } + #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) func testResetProfilingTimestamps_FromBackgroundThread() { let sut = fixture.sut diff --git a/Tests/SentryTests/Integrations/Performance/IO/DataSentryTracingIntegrationTests.swift b/Tests/SentryTests/Integrations/Performance/IO/DataSentryTracingIntegrationTests.swift index 2113c552bac..c12ca2568db 100644 --- a/Tests/SentryTests/Integrations/Performance/IO/DataSentryTracingIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Performance/IO/DataSentryTracingIntegrationTests.swift @@ -20,6 +20,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { init() {} + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func getSut(testName: String, isSDKEnabled: Bool = true, isEnabled: Bool = true) throws -> Data { let fileManager = FileManager.default let tempDirUrl = URL(fileURLWithPath: NSTemporaryDirectory()) @@ -59,7 +60,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { } // Get the working directory of the SDK, as these files are ignored by default - guard let sentryPath = SentrySDK.currentHub().getClient()?.fileManager.sentryPath else { + guard let sentryPath = SentrySDKInternal.currentHub().getClient()?.fileManager.sentryPath else { preconditionFailure("Sentry path is nil, but should be configured for test cases.") } let sentryPathUrl = URL(fileURLWithPath: sentryPath) @@ -92,8 +93,10 @@ class DataSentryTracingIntegrationTests: XCTestCase { } var nonFileUrl: URL { - // URL to a file that is not a file but should exist at all times - URL(string: "https://raw.githubusercontent.com/getsentry/sentry-cocoa/refs/heads/main/.gitignore")! + // Use a non-file scheme that doesn't hit the network. + // We use a data: URL to reliably return bytes without external dependencies, + // ensuring this test verifies "non-file URL should not trace" deterministically. + URL(string: "data:text/plain;base64,SGVsbG8=")! } func tearDown() throws { @@ -130,6 +133,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { // MARK: - Data.init(contentsOfWithSentryTracing:) + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testInitContentsOfWithSentryTracing_shouldTraceManually() throws { // -- Arrange -- let expectedData = try fixture.getSut(testName: self.name) @@ -159,6 +163,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertGreaterThan(endTimestamp.timeIntervalSince1970, startTimestamp.timeIntervalSince1970) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testInitContentsOfWithSentryTracingWithOptions_shouldPassOptionsToSystemImplementation() throws { // -- Arrange -- let expectedData = try fixture.getSut(testName: self.name) @@ -186,6 +191,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertEqual(mappedSentryData, expectedData) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testInitContentsOfWithSentryTracing_throwsError_shouldTraceManuallyWithErrorRethrow() throws { // -- Arrange -- let _ = try fixture.getSut(testName: self.name) @@ -212,6 +218,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertGreaterThan(endTimestamp.timeIntervalSince1970, startTimestamp.timeIntervalSince1970) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testInitContentsOfWithSentryTracing_nonFileUrl_shouldNotTraceManually() throws { // -- Arrange -- let _ = try fixture.getSut(testName: self.name) @@ -225,6 +232,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertEqual(parentTransaction.children.count, 0) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testInitContentsOfWithSentryTracing_trackerIsNotEnabled_shouldNotTraceManually() throws { // -- Arrange -- let _ = try fixture.getSut(testName: self.name, isEnabled: false) @@ -238,6 +246,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertEqual(parentTransaction.children.count, 0) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testInitContentsOfWithSentryTracing_fileIsIgnored_shouldNotTraceManually() throws { // -- Arrange -- let _ = try fixture.getSut(testName: self.name) @@ -251,6 +260,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertEqual(parentTransaction.children.count, 0) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testInitContentsOfWithSentryTracing_SDKIsNotStarted_shouldReadData() throws { // -- Arrange -- let _ = try fixture.getSut(testName: self.name, isSDKEnabled: false) @@ -263,6 +273,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertEqual(data, fixture.data) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testInitContentsOfWithSentryTracing_SDKIsClosed_shouldReadData() throws { // -- Arrange -- let _ = try fixture.getSut(testName: self.name) @@ -278,6 +289,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { // MARK: - Data.writeWithSentryTracing(to:) + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testWriteWithSentryTracing_shouldTraceManuallyWithErrorRethrow() throws { // -- Arrange -- let sut: Data = try fixture.getSut(testName: self.name) @@ -313,6 +325,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertGreaterThan(endTimestamp.timeIntervalSince1970, startTimestamp.timeIntervalSince1970) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testWriteWithSentryTracingWithOptions_shouldPassOptionsToSystemImplementation() throws { // -- Arrange -- let sut: Data = try fixture.getSut(testName: self.name) @@ -344,6 +357,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertEqual(writtenData, sut) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testWriteWithSentryTracing_throwsError_shouldTraceManuallyWithErrorRethrow() throws { // -- Arrange -- let sut: Data = try fixture.getSut(testName: self.name) @@ -370,6 +384,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertGreaterThan(endTimestamp.timeIntervalSince1970, startTimestamp.timeIntervalSince1970) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testWriteWithSentryTracing_nonFileUrl_shouldNotTraceManually() throws { // -- Arrange -- let sut: Data = try fixture.getSut(testName: self.name) @@ -382,6 +397,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertEqual(parentTransaction.children.count, 0) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testWriteWithSentryTracing_trackerIsNotEnabled_shouldNotTraceManually() throws { // -- Arrange -- let sut: Data = try fixture.getSut(testName: self.name, isEnabled: false) @@ -394,6 +410,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertEqual(parentTransaction.children.count, 0) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testWriteWithSentryTracing_fileIsIgnored_shouldNotTraceManually() throws { // -- Arrange -- let sut: Data = try fixture.getSut(testName: self.name) @@ -413,6 +430,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertEqual(parentTransaction.children.count, 0) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testWriteWithSentryTracing_SDKIsNotStarted_shouldWriteFile() throws { // -- Arrange -- let sut: Data = try fixture.getSut(testName: self.name, isSDKEnabled: false) @@ -431,6 +449,7 @@ class DataSentryTracingIntegrationTests: XCTestCase { XCTAssertEqual(writtenData, fixture.data) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testWriteWithSentryTracing_SDKIsClosed_shouldWriteFile() throws { // -- Arrange -- let sut: Data = try fixture.getSut(testName: self.name) diff --git a/Tests/SentryTests/Integrations/Performance/IO/FileManagerTracingIntegrationTests.swift b/Tests/SentryTests/Integrations/Performance/IO/FileManagerTracingIntegrationTests.swift index d469fe1596f..497b54a8da0 100644 --- a/Tests/SentryTests/Integrations/Performance/IO/FileManagerTracingIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Performance/IO/FileManagerTracingIntegrationTests.swift @@ -3,6 +3,7 @@ @_spi(Private) import SentryTestUtils import XCTest +@available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") class FileManagerSentryTracingIntegrationTests: XCTestCase { private class Fixture { let mockDateProvider: TestCurrentDateProvider = { @@ -53,7 +54,7 @@ class FileManagerSentryTracingIntegrationTests: XCTestCase { } // Get the working directory of the SDK, as the path is using the DSN hash to avoid conflicts - let sentryBasePath = try XCTUnwrap(SentrySDK.currentHub().getClient()?.fileManager.basePath, "Sentry base path is nil, but should be configured for test cases.") + let sentryBasePath = try XCTUnwrap(SentrySDKInternal.currentHub().getClient()?.fileManager.basePath, "Sentry base path is nil, but should be configured for test cases.") let sentryBasePathUrl = URL(fileURLWithPath: sentryBasePath) // The base path is not unique for the DSN, therefore we need to make it unique @@ -66,7 +67,7 @@ class FileManagerSentryTracingIntegrationTests: XCTestCase { } // Get the working directory of the SDK, as these files are ignored by default - let sentryPath = try XCTUnwrap(SentrySDK.currentHub().getClient()?.fileManager.sentryPath, "Sentry path is nil, but should be configured for test cases.") + let sentryPath = try XCTUnwrap(SentrySDKInternal.currentHub().getClient()?.fileManager.sentryPath, "Sentry path is nil, but should be configured for test cases.") let sentryPathUrl = URL(fileURLWithPath: sentryPath) ignoredFileToCreateUrl = sentryPathUrl.appendingPathComponent("test--ignored-file-to-create") @@ -120,8 +121,10 @@ class FileManagerSentryTracingIntegrationTests: XCTestCase { var invalidPathToCreate: String { invalidDestPath } var nonFileUrl: URL { - // URL to a file that is not a file but should exist at all times - URL(string: "https://raw.githubusercontent.com/getsentry/sentry-cocoa/refs/heads/main/.gitignore")! + // Use a non-file scheme that doesn't hit the network. + // We use a data: URL to reliably return bytes without external dependencies, + // ensuring this test verifies "non-file URL should not trace" deterministically. + URL(string: "data:text/plain;base64,SGVsbG8=")! } var ignoredFileToCreatePath: String { diff --git a/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackerSwiftHelpersTests.swift b/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackerSwiftHelpersTests.swift index e2963933fc1..1ee6361a80b 100644 --- a/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackerSwiftHelpersTests.swift +++ b/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackerSwiftHelpersTests.swift @@ -20,16 +20,17 @@ class SentryFileIOTrackerSwiftHelpersTests: XCTestCase { private let destPath = "/path/to/dest" private let testError = NSError(domain: "Test", code: 1, userInfo: nil) + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") override func setUp() { mockedDateProvider = TestCurrentDateProvider() SentryDependencyContainer.sharedInstance().dateProvider = mockedDateProvider hub = SentryHub(client: nil, andScope: nil) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) tracker = SentryFileIOTracker( threadInspector: TestThreadInspector(options: .noIntegrations()), - processInfoWrapper: TestSentryNSProcessInfoWrapper() + processInfoWrapper: MockSentryProcessInfo() ) } diff --git a/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackerTests.swift b/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackerTests.swift index a8322b00ef7..b2193faf8d7 100644 --- a/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackerTests.swift @@ -8,34 +8,49 @@ class SentryFileIOTrackerTests: XCTestCase { let filePath = "Some Path" let fileURL = URL(fileURLWithPath: "Some Path") - let sentryPath = try! TestFileManager(options: Options()).sentryPath - let sentryUrl = URL(fileURLWithPath: try! TestFileManager(options: Options()).sentryPath) + + let sentryPath: String + let sentryUrl: URL + let dateProvider = TestCurrentDateProvider() + let dispatchQueueWrapper = TestSentryDispatchQueueWrapper() + let data = Data("SOME DATA".utf8) let threadInspector = TestThreadInspector.instance let imageProvider = TestDebugImageProvider() - func getSut() -> SentryFileIOTracker { + init() throws { + let options = Options() + options.dsn = TestConstants.dsnForTestCase(type: SentryFileIOTrackerTests.self) + let fileManager = try TestFileManager(options: options, dateProvider: dateProvider, dispatchQueueWrapper: dispatchQueueWrapper) + sentryPath = fileManager.sentryPath + sentryUrl = URL(fileURLWithPath: sentryPath) + imageProvider.debugImages = [TestData.debugImage] SentryDependencyContainer.sharedInstance().debugImageProvider = imageProvider + SentryDependencyContainer.sharedInstance().dateProvider = dateProvider + } + + func getSut() -> SentryFileIOTracker { threadInspector.allThreads = [TestData.thread2] - let processInfoWrapper = TestSentryNSProcessInfoWrapper() + let processInfoWrapper = MockSentryProcessInfo() processInfoWrapper.overrides.processDirectoryPath = "sentrytest" let result = SentryFileIOTracker(threadInspector: threadInspector, processInfoWrapper: processInfoWrapper) - SentryDependencyContainer.sharedInstance().dateProvider = dateProvider result.enable() + return result } } private var fixture: Fixture! - override func setUp() { - super.setUp() - fixture = Fixture() + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + override func setUpWithError() throws { + try super.setUpWithError() + fixture = try Fixture() fixture.getSut().enable() SentrySDK.start { $0.removeAllIntegrations() diff --git a/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationObjCTests.m b/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationObjCTests.m index 3514d21af68..ae60c88a652 100644 --- a/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationObjCTests.m +++ b/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationObjCTests.m @@ -1,7 +1,6 @@ #import "SentryByteCountFormatter.h" #import "SentryFileIOTracker.h" #import "SentryOptions.h" -#import "SentrySDK.h" #import "SentrySpan.h" #import "SentrySpanOperation.h" #import "SentrySwizzle.h" @@ -205,13 +204,14 @@ - (void)assertDataWritten - (void)assertTransactionForOperation:(NSString *)operation block:(void (^)(void))block { - SentryTracer *parentTransaction = [SentrySDK startTransactionWithName:@"Transaction" - operation:@"Test" - bindToScope:YES]; + SentryTracer *parentTransaction + = (SentryTracer *)[SentrySDK startTransactionWithName:@"Transaction" + operation:@"Test" + bindToScope:YES]; block(); - SentrySpan *ioSpan = parentTransaction.children.firstObject; + SentrySpan *ioSpan = (SentrySpan *)parentTransaction.children.firstObject; XCTAssertEqual(parentTransaction.children.count, 1); XCTAssertEqual([ioSpan.data[@"file.size"] unsignedIntValue], someData.length); diff --git a/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationTests.swift b/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationTests.swift index 4aea168ee45..913a7230f21 100644 --- a/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationTests.swift @@ -11,6 +11,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { let fileURL: URL! let fileDirectory: URL! + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func getOptions(enableAutoPerformanceTracing: Bool = true, enableFileIOTracing: Bool = true, enableSwizzling: Bool = true, enableDataSwizzling: Bool = true, enableFileManagerSwizzling: Bool = true, tracesSampleRate: NSNumber = 1) -> Options { let result = Options() result.enableAutoPerformanceTracing = enableAutoPerformanceTracing @@ -68,6 +69,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { SentrySDK.close() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_WritingTrackingDisabled_forIOOption() { // -- Act -- SentrySDK.start(options: fixture.getOptions(enableFileIOTracing: false)) @@ -76,6 +78,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { assertWriteWithNoSpans() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_WritingTrackingDisabled_forSwizzlingOption() { // -- Act -- SentrySDK.start(options: fixture.getOptions(enableSwizzling: false)) @@ -84,6 +87,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { assertWriteWithNoSpans() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_WritingTrackingDisabled_forAutoPerformanceTrackingOption() { // -- Act -- SentrySDK.start(options: fixture.getOptions(enableAutoPerformanceTracing: false)) @@ -92,6 +96,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { assertWriteWithNoSpans() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_WritingTrackingDisabled_TracingDisabled() { // -- Act -- SentrySDK.start(options: fixture.getOptions(tracesSampleRate: 0)) @@ -100,6 +105,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { assertWriteWithNoSpans() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testData_Writing_Tracking() { // -- Arrange -- let expectedSpanCount: Int @@ -121,6 +127,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { } } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testData_WritingWithOption_Tracking() { // -- Arrange -- let expectedSpanCount: Int @@ -142,6 +149,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { } } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_ReadingTrackingDisabled_forIOOption() { // -- Act -- SentrySDK.start(options: fixture.getOptions(enableFileIOTracing: false)) @@ -150,6 +158,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { assertWriteWithNoSpans() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_ReadingTrackingDisabled_forSwizzlingOption() { // -- Act -- SentrySDK.start(options: fixture.getOptions(enableSwizzling: false)) @@ -158,6 +167,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { assertWriteWithNoSpans() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_ReadingTrackingDisabled_forAutoPerformanceTrackingOption() { // -- Act -- SentrySDK.start(options: fixture.getOptions(enableAutoPerformanceTracing: false)) @@ -166,6 +176,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { assertWriteWithNoSpans() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_ReadingTrackingDisabled_TracingDisabled() { // -- Act -- SentrySDK.start(options: fixture.getOptions(tracesSampleRate: 0)) @@ -174,6 +185,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { assertWriteWithNoSpans() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testData_ReadingURL_Tracking() { // -- Arrange -- let expectedSpanCount: Int @@ -193,6 +205,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { } } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testData_ReadingURLWithOption_Tracking() throws { // -- Arrange -- let expectedSpanCount: Int @@ -213,6 +226,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { XCTAssertEqual(data?.count, fixture.data.count) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_ReadingFile_Tracking() { // -- Arrange -- SentrySDK.start(options: fixture.getOptions()) @@ -224,6 +238,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { XCTAssertEqual(data?.count, fixture.data.count) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_ReadingFileWithOptions_Tracking() { // -- Arrange -- SentrySDK.start(options: fixture.getOptions()) @@ -235,6 +250,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { XCTAssertEqual(data?.count, fixture.data.count) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_ReadingBigFile() { // -- Arrange -- SentrySDK.start(options: fixture.getOptions()) @@ -249,6 +265,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { XCTAssertEqual(data?.count, 295_760) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_WritingBigFile() { // -- Arrange -- guard let jsonFile = getBigFilePath() else { @@ -278,6 +295,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { ?? bundle.path(forResource: "fatal-error-binary-images-message2", ofType: "json") } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_DataConsistency_readUrl() { SentrySDK.start(options: fixture.getOptions()) @@ -292,6 +310,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { XCTAssertEqual(randomValue, readValue) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_DataConsistency_readPath() { SentrySDK.start(options: fixture.getOptions()) @@ -305,6 +324,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { XCTAssertEqual(randomValue, readValue) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testEnableDataSwizzling_isNotEnabled_shouldNotSwizzleNSDataMethods() { // -- Arrange -- let options = fixture.getOptions(enableDataSwizzling: false) @@ -314,6 +334,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { assertWriteWithNoSpans() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testDisableFileManagerSwizzling_isNotEnabledAndDataSwizzlingIsEnabled_shouldTrackWithSpan() throws { // -- Arrange -- if #available(iOS 18, macOS 15, tvOS 18, *) { @@ -329,6 +350,7 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { } } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testDisableFileManagerSwizzling_isNotEnabled_shouldNotTrackWithSpan() throws { // -- Arrange -- if #available(iOS 18, macOS 15, tvOS 18, *) { diff --git a/Tests/SentryTests/Integrations/Performance/IO/SentryNSFileManagerSwizzlingTests.m b/Tests/SentryTests/Integrations/Performance/IO/SentryNSFileManagerSwizzlingTests.m index 57091e3d981..eb61d729b4d 100644 --- a/Tests/SentryTests/Integrations/Performance/IO/SentryNSFileManagerSwizzlingTests.m +++ b/Tests/SentryTests/Integrations/Performance/IO/SentryNSFileManagerSwizzlingTests.m @@ -2,7 +2,6 @@ #import "SentryFileIOTracker.h" #import "SentryNSFileManagerSwizzling.h" #import "SentryOptions.h" -#import "SentrySDK.h" #import "SentrySpan.h" #import "SentrySpanOperation.h" #import "SentrySwizzle.h" @@ -58,7 +57,7 @@ - (void)setUpNSFileManagerSwizzlingWithEnabledFlag:(bool)enableFileManagerSwizzl SentryThreadInspector *threadInspector = [[SentryThreadInspector alloc] initWithOptions:options]; - SentryNSProcessInfoWrapper *processInfoWrapper = + id processInfoWrapper = [SentryDependencyContainer.sharedInstance processInfoWrapper]; self->tracker = [[SentryFileIOTracker alloc] initWithThreadInspector:threadInspector processInfoWrapper:processInfoWrapper]; @@ -163,15 +162,16 @@ - (void)assertTransactionForOperation:(NSString *)operation spanCount:(NSUInteger)spanCount block:(void (^)(void))block { - SentryTracer *parentTransaction = [SentrySDK startTransactionWithName:@"Transaction" - operation:@"Test" - bindToScope:YES]; + SentryTracer *parentTransaction + = (SentryTracer *)[SentrySDK startTransactionWithName:@"Transaction" + operation:@"Test" + bindToScope:YES]; block(); XCTAssertEqual(parentTransaction.children.count, spanCount); - SentrySpan *ioSpan = parentTransaction.children.firstObject; + SentrySpan *ioSpan = (SentrySpan *)parentTransaction.children.firstObject; if (spanCount > 0) { XCTAssertEqual([ioSpan.data[@"file.size"] unsignedIntValue], someData.length); XCTAssertEqualObjects(ioSpan.data[@"file.path"], filePath); diff --git a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift index 84cc1df11c6..fbe2f9e42bc 100644 --- a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift @@ -16,6 +16,7 @@ class SentryNetworkTrackerIntegrationTests: XCTestCase { let dateProvider = TestCurrentDateProvider() let options: Options + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") init() { options = Options() options.dsn = SentryNetworkTrackerIntegrationTests.dsnAsString @@ -26,6 +27,7 @@ class SentryNetworkTrackerIntegrationTests: XCTestCase { private var fixture: Fixture! + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") override func setUp() { super.setUp() fixture = Fixture() @@ -149,7 +151,7 @@ class SentryNetworkTrackerIntegrationTests: XCTestCase { wait(for: [expect], timeout: 5) - let scope = SentrySDK.currentHub().scope + let scope = SentrySDKInternal.currentHub().scope let breadcrumbs = Dynamic(scope).breadcrumbArray as [Breadcrumb]? XCTAssertEqual(1, breadcrumbs?.count) } diff --git a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift index 5462bf6b8f6..c9d4a67dc21 100644 --- a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift @@ -61,8 +61,8 @@ class SentryNetworkTrackerTests: XCTestCase { super.setUp() fixture = Fixture() - SentrySDK.setCurrentHub(fixture.hub) - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setCurrentHub(fixture.hub) + SentrySDKInternal.setStart(with: fixture.options) SentryDependencyContainer.sharedInstance().dateProvider = fixture.dateProvider } @@ -148,7 +148,7 @@ class SentryNetworkTrackerTests: XCTestCase { } func testSDKOptionsNil() { - SentrySDK.setCurrentHub(nil) + SentrySDKInternal.setCurrentHub(nil) let task = fixture.sentryTask let span = spanForTask(task: task) @@ -806,19 +806,25 @@ class SentryNetworkTrackerTests: XCTestCase { let transaction = startTransaction() let queue = DispatchQueue(label: "SentryNetworkTrackerTests", qos: .userInteractive, attributes: [.concurrent, .initiallyInactive]) - let group = DispatchGroup() - for _ in 0...100_000 { - group.enter() + let loopCount = 1_000 + + let expectation = XCTestExpectation(description: "Resume called multiple times concurrently") + expectation.expectedFulfillmentCount = loopCount + expectation.assertForOverFulfill = true + + for _ in 0.. SentryTimeToDisplayTracker { @@ -26,19 +29,26 @@ class SentryTimeToDisplayTrackerTest: XCTestCase { func getTracer() throws -> SentryTracer { let options = Options() - let hub = TestHub(client: SentryClient(options: options, fileManager: try TestFileManager(options: options), deleteOldEnvelopeItems: false), andScope: nil) + options.dsn = TestConstants.dsnForTestCase(type: SentryTimeToDisplayTrackerTest.self) + + let fileManager = try TestFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: dispatchQueue + ) + + let hub = TestHub(client: SentryClient(options: options, fileManager: fileManager, deleteOldEnvelopeItems: false), andScope: nil) return SentryTracer(transactionContext: TransactionContext(operation: "ui.load"), hub: hub, configuration: SentryTracerConfiguration(block: { $0.waitForChildren = true })) } } - private lazy var fixture = Fixture() + private var fixture: Fixture! - override func setUp() { - super.setUp() - SentryDependencyContainer.sharedInstance().dateProvider = fixture.dateProvider - SentryDependencyContainer.sharedInstance().dispatchQueueWrapper = fixture.dispatchQueue + override func setUpWithError() throws { + try super.setUpWithError() + fixture = try Fixture() } override func tearDown() { @@ -345,7 +355,7 @@ class SentryTimeToDisplayTrackerTest: XCTestCase { func testTracerWithAppStartData_notWaitingForFullDisplay() throws { let appStartMeasurement = TestData.getAppStartMeasurement(type: .cold, appStartTimestamp: Date(timeIntervalSince1970: 6), runtimeInitSystemTimestamp: 6_000_000_000) - SentrySDK.setAppStartMeasurement(appStartMeasurement) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) fixture.dateProvider.setDate(date: Date(timeIntervalSince1970: 7)) @@ -378,7 +388,7 @@ class SentryTimeToDisplayTrackerTest: XCTestCase { func testTracerWithAppStartData_waitingForFullDisplay() throws { let appStartMeasurement = TestData.getAppStartMeasurement(type: .cold, appStartTimestamp: Date(timeIntervalSince1970: 6), runtimeInitSystemTimestamp: 6_000_000_000) - SentrySDK.setAppStartMeasurement(appStartMeasurement) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) fixture.dateProvider.setDate(date: Date(timeIntervalSince1970: 7)) diff --git a/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerPerformanceTrackerTests.swift b/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerPerformanceTrackerTests.swift index ae3976ded1f..bb025e4f016 100644 --- a/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerPerformanceTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerPerformanceTrackerTests.swift @@ -41,6 +41,7 @@ class SentryUIViewControllerPerformanceTrackerTests: XCTestCase { return SentryInAppLogic(inAppIncludes: options.inAppIncludes, inAppExcludes: []) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") init() { options = Options.noIntegrations() let imageName = String( @@ -67,6 +68,7 @@ class SentryUIViewControllerPerformanceTrackerTests: XCTestCase { private var fixture: Fixture! + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") override func setUp() { super.setUp() fixture = Fixture() diff --git a/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerSwizzlingTests.swift b/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerSwizzlingTests.swift index 8564802702c..434e98ec698 100644 --- a/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerSwizzlingTests.swift +++ b/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerSwizzlingTests.swift @@ -11,10 +11,11 @@ class SentryUIViewControllerSwizzlingTests: XCTestCase { let dispatchQueue = TestSentryDispatchQueueWrapper() let objcRuntimeWrapper = SentryTestObjCRuntimeWrapper() let subClassFinder: TestSubClassFinder - let processInfoWrapper = SentryNSProcessInfoWrapper() + let processInfoWrapper = MockSentryProcessInfo() let binaryImageCache: SentryBinaryImageCache var options: Options + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") init() { subClassFinder = TestSubClassFinder(dispatchQueue: dispatchQueue, objcRuntimeWrapper: objcRuntimeWrapper, swizzleClassNameExcludes: []) binaryImageCache = SentryDependencyContainer.sharedInstance().binaryImageCache @@ -32,7 +33,7 @@ class SentryUIViewControllerSwizzlingTests: XCTestCase { } var sutWithDefaultObjCRuntimeWrapper: SentryUIViewControllerSwizzling { - return SentryUIViewControllerSwizzling(options: options, dispatchQueue: dispatchQueue, objcRuntimeWrapper: SentryDefaultObjCRuntimeWrapper.sharedInstance(), subClassFinder: subClassFinder, processInfoWrapper: processInfoWrapper, binaryImageCache: binaryImageCache) + return SentryUIViewControllerSwizzling(options: options, dispatchQueue: dispatchQueue, objcRuntimeWrapper: SentryDependencyContainerSwiftHelper.objcRuntimeWrapper(), subClassFinder: subClassFinder, processInfoWrapper: processInfoWrapper, binaryImageCache: binaryImageCache) } var testableSut: TestSentryUIViewControllerSwizzling { @@ -48,6 +49,7 @@ class SentryUIViewControllerSwizzlingTests: XCTestCase { private var fixture: Fixture! + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") override func setUp() { super.setUp() fixture = Fixture() @@ -128,7 +130,7 @@ class SentryUIViewControllerSwizzlingTests: XCTestCase { func testViewControllerWithLoadView_TransactionBoundToScope() { let d = class_getImageName(type(of: self))! - fixture.processInfoWrapper.setProcessPath(String(cString: d)) + fixture.processInfoWrapper.overrides.processPath = String(cString: d) fixture.sut.start() let controller = ViewWithLoadViewController() @@ -202,9 +204,13 @@ class SentryUIViewControllerSwizzlingTests: XCTestCase { let debugDylib = "\(imageName).debug.dylib" - var image = createCrashBinaryImage(0, name: debugDylib) - SentryDependencyContainer.sharedInstance().binaryImageCache.start() - SentryDependencyContainer.sharedInstance().binaryImageCache.binaryImageAdded(&image) + let image = createCrashBinaryImage(0, name: debugDylib) + SentryDependencyContainer.sharedInstance().binaryImageCache.start(false) + SentryDependencyContainer.sharedInstance().binaryImageCache.binaryImageAdded(imageName: image.name, + vmAddress: image.vmAddress, + address: image.address, + size: image.size, + uuid: image.uuid) let sut = fixture.sut sut.start() @@ -320,7 +326,7 @@ class SentryUIViewControllerSwizzlingTests: XCTestCase { } } -class MockApplication: NSObject, SentryUIApplicationProtocol { +class MockApplication: NSObject, SentryUIApplication { class MockApplicationDelegate: NSObject, UIApplicationDelegate { var window: UIWindow? diff --git a/Tests/SentryTests/Integrations/Screenshot/SentryScreenshotIntegrationTests.swift b/Tests/SentryTests/Integrations/Screenshot/SentryScreenshotIntegrationTests.swift index d10ac25c69e..9e1f0602df6 100644 --- a/Tests/SentryTests/Integrations/Screenshot/SentryScreenshotIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Screenshot/SentryScreenshotIntegrationTests.swift @@ -1,23 +1,31 @@ #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) -import Sentry -import SentryTestUtils +@_spi(Private) @testable import Sentry +@_spi(Private) @testable import SentryTestUtils import XCTest class SentryScreenshotIntegrationTests: XCTestCase { private class Fixture { - let screenshot: TestSentryScreenshot - + let screenshotSource: TestSentryScreenshotSource + init() { - let testScreenShot = TestSentryScreenshot() - testScreenShot.result = [Data(count: 10)] - screenshot = testScreenShot + let redactOptions = SentryViewScreenshotOptions() + let renderer = TestSentryViewRenderer() + let photographer = TestSentryViewPhotographer( + renderer: renderer, + redactOptions: redactOptions + ) + let source = TestSentryScreenshotSource(photographer: photographer) + source.result = [Data(count: 10)] + screenshotSource = source + SentryDependencyContainer.sharedInstance().screenshotSource = source } - func getSut() -> SentryScreenshotIntegration { - let result = SentryScreenshotIntegration() - return result + func getSut(options: Options = Options()) -> SentryScreenshotIntegration { + let sut = SentryScreenshotIntegration() + sut.install(with: options) + return sut } } @@ -26,8 +34,6 @@ class SentryScreenshotIntegrationTests: XCTestCase { override func setUp() { super.setUp() fixture = Fixture() - - SentryDependencyContainer.sharedInstance().screenshot = fixture.screenshot } override func tearDown() { @@ -35,24 +41,27 @@ class SentryScreenshotIntegrationTests: XCTestCase { clearTestState() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_attachScreenshot_disabled() { SentrySDK.start { $0.attachScreenshot = false $0.setIntegrations([SentryScreenshotIntegration.self]) } - XCTAssertEqual(SentrySDK.currentHub().getClient()?.attachmentProcessors.count, 0) + XCTAssertEqual(SentrySDKInternal.currentHub().getClient()?.attachmentProcessors.count, 0) XCTAssertFalse(sentrycrash_hasSaveScreenshotCallback()) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_attachScreenshot_enabled() { SentrySDK.start { $0.attachScreenshot = true $0.setIntegrations([SentryScreenshotIntegration.self]) } - XCTAssertEqual(SentrySDK.currentHub().getClient()?.attachmentProcessors.count, 1) + XCTAssertEqual(SentrySDKInternal.currentHub().getClient()?.attachmentProcessors.count, 1) XCTAssertTrue(sentrycrash_hasSaveScreenshotCallback()) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_uninstall() { SentrySDK.start { $0.attachScreenshot = true @@ -60,12 +69,13 @@ class SentryScreenshotIntegrationTests: XCTestCase { } SentrySDK.close() - XCTAssertNil(SentrySDK.currentHub().getClient()?.attachmentProcessors) + XCTAssertNil(SentrySDKInternal.currentHub().getClient()?.attachmentProcessors) XCTAssertFalse(sentrycrash_hasSaveScreenshotCallback()) } func test_attachScreenShot_withError() { let sut = fixture.getSut() + let event = Event(error: NSError(domain: "", code: -1)) let newAttachmentList = sut.processAttachments([], for: event) @@ -138,8 +148,6 @@ class SentryScreenshotIntegrationTests: XCTestCase { #endif // os(iOS) || targetEnvironment(macCatalyst) func test_NoScreenShot_WhenDiscardedInCallback() { - let sut = fixture.getSut() - let expectation = expectation(description: "BeforeCaptureScreenshot must be called.") let options = Options() @@ -148,8 +156,8 @@ class SentryScreenshotIntegrationTests: XCTestCase { return false } - sut.install(with: options) - + let sut = fixture.getSut(options: options) + let newAttachmentList = sut.processAttachments([], for: Event(error: NSError(domain: "", code: -1))) wait(for: [expectation], timeout: 1.0) @@ -171,8 +179,9 @@ class SentryScreenshotIntegrationTests: XCTestCase { func test_Attachments_Info() { let sut = fixture.getSut() + let event = Event(error: NSError(domain: "", code: -1)) - fixture.screenshot.result = [Data(repeating: 0, count: 1), Data(repeating: 0, count: 2), Data(repeating: 0, count: 3)] + fixture.screenshotSource.result = [Data(repeating: 0, count: 1), Data(repeating: 0, count: 2), Data(repeating: 0, count: 3)] let newAttachmentList = sut.processAttachments([], for: event) @@ -193,15 +202,13 @@ class SentryScreenshotIntegrationTests: XCTestCase { func test_backgroundForAppHangs() { let sut = fixture.getSut() - let testVH = TestSentryScreenshot() - SentryDependencyContainer.sharedInstance().screenshot = testVH let event = Event() event.exceptions = [Sentry.Exception(value: "test", type: "App Hanging")] let ex = expectation(description: "Attachment Added") - testVH.processScreenshotsCallback = { + fixture.screenshotSource.processScreenshotsCallback = { XCTFail("Should not add screenshots to App Hanging events") } diff --git a/Tests/SentryTests/Integrations/Screenshot/SentryScreenshotOptionsTests.swift b/Tests/SentryTests/Integrations/Screenshot/SentryScreenshotOptionsTests.swift new file mode 100644 index 00000000000..b1eb2a34d0c --- /dev/null +++ b/Tests/SentryTests/Integrations/Screenshot/SentryScreenshotOptionsTests.swift @@ -0,0 +1,506 @@ +import Foundation +@testable import Sentry +import XCTest + +class SentryViewScreenshotOptionsTests: XCTestCase { + // MARK: - Initializer + + func testInit_withoutArguments_shouldUseDefaults() { + // -- Act -- + let options = SentryViewScreenshotOptions() + + // -- Assert -- + XCTAssertTrue(options.enableViewRendererV2) + XCTAssertFalse(options.enableFastViewRendering) + XCTAssertTrue(options.maskAllText) + XCTAssertTrue(options.maskAllImages) + XCTAssertEqual(options.maskedViewClasses.count, 0) + XCTAssertEqual(options.unmaskedViewClasses.count, 0) + } + + func testInit_withAllArguments_shouldSetValues() { + // -- Act -- + // Use the opposite of the default values to check if they are set correctly + let options = SentryViewScreenshotOptions( + enableViewRendererV2: false, + enableFastViewRendering: true, + maskAllText: false, + maskAllImages: false, + maskedViewClasses: [NSString.self], + unmaskedViewClasses: [NSNumber.self] + ) + + // -- Assert -- + XCTAssertFalse(options.enableViewRendererV2) + XCTAssertTrue(options.enableFastViewRendering) + XCTAssertFalse(options.maskAllText) + XCTAssertFalse(options.maskAllImages) + XCTAssertEqual(options.maskedViewClasses.count, 1) + XCTAssertEqual(ObjectIdentifier(options.maskedViewClasses[0]), ObjectIdentifier(NSString.self)) + XCTAssertEqual(options.unmaskedViewClasses.count, 1) + XCTAssertEqual(ObjectIdentifier(options.unmaskedViewClasses[0]), ObjectIdentifier(NSNumber.self)) + } + + func testInit_enableViewRendererV2Omitted_shouldUseDefaultValues() { + // -- Act -- + let options = SentryViewScreenshotOptions( + enableFastViewRendering: true, + maskAllText: false, + maskAllImages: false + ) + + // -- Assert -- + XCTAssertTrue(options.enableViewRendererV2) + } + + func testInit_enableFastViewRenderingOmitted_shouldUseDefaultValues() { + // -- Act -- + let options = SentryViewScreenshotOptions( + enableViewRendererV2: false, + maskAllText: false, + maskAllImages: false + ) + + // -- Assert -- + XCTAssertFalse(options.enableFastViewRendering) + } + + func testInit_maskAllTextOmitted_shouldUseDefaultValues() { + // -- Act -- + let options = SentryViewScreenshotOptions( + enableViewRendererV2: false, + enableFastViewRendering: true, + maskAllImages: false + ) + + // -- Assert -- + XCTAssertTrue(options.maskAllText) + } + + func testInit_maskAllImagesOmitted_shouldUseDefaultValues() { + // -- Act -- + let options = SentryViewScreenshotOptions( + enableViewRendererV2: false, + enableFastViewRendering: true, + maskAllText: false + ) + + // -- Assert -- + XCTAssertTrue(options.maskAllImages) + } + + func testInit_maskedViewClassesOmitted_shouldUseDefaultValues() { + // -- Act -- + let options = SentryViewScreenshotOptions( + enableViewRendererV2: false, + enableFastViewRendering: true, + maskAllText: false, + maskAllImages: false, + unmaskedViewClasses: [NSString.self] + ) + + // -- Assert -- + XCTAssertEqual(options.maskedViewClasses.count, 0) + } + + func testInit_unmaskedViewClassesOmitted_shouldUseDefaultValues() { + // -- Act -- + let options = SentryViewScreenshotOptions( + enableViewRendererV2: false, + enableFastViewRendering: true, + maskAllText: false, + maskAllImages: false, + maskedViewClasses: [NSString.self] + ) + + // -- Assert -- + XCTAssertEqual(options.unmaskedViewClasses.count, 0) + } + + // MARK: - Dictionary Initialization + + func testInitFromDict_emptyDictionary_shouldUseDefaultValues() { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [:]) + + // -- Assert -- + XCTAssertTrue(options.enableViewRendererV2) + XCTAssertFalse(options.enableFastViewRendering) + XCTAssertTrue(options.maskAllText) + XCTAssertTrue(options.maskAllImages) + XCTAssertEqual(options.maskedViewClasses.count, 0) + XCTAssertEqual(options.unmaskedViewClasses.count, 0) + } + + func testInitFromDict_allValues_shouldSetValues() throws { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "enableViewRendererV2": false, + "enableFastViewRendering": true, + "maskAllText": false, + "maskAllImages": false, + "maskedViewClasses": ["NSString"], + "unmaskedViewClasses": ["NSNumber"] + ]) + + // -- Assert -- + XCTAssertFalse(options.enableViewRendererV2) + XCTAssertTrue(options.enableFastViewRendering) + XCTAssertFalse(options.maskAllText) + XCTAssertFalse(options.maskAllImages) + + XCTAssertEqual(options.maskedViewClasses.count, 1) + let maskedViewClass: AnyClass = try XCTUnwrap(options.maskedViewClasses.first) + XCTAssertEqual(ObjectIdentifier(maskedViewClass), ObjectIdentifier(NSString.self)) + + XCTAssertEqual(options.unmaskedViewClasses.count, 1) + let unmaskedViewClass: AnyClass = try XCTUnwrap(options.unmaskedViewClasses.first) + XCTAssertEqual(ObjectIdentifier(unmaskedViewClass), ObjectIdentifier(NSNumber.self)) + } + + // MARK: - enableViewRendererV2 + + func testInitFromDict_enableViewRendererV2_whenValidValue_shouldSetValue() { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "enableViewRendererV2": true + ]) + + // -- Assert -- + XCTAssertTrue(options.enableViewRendererV2) + + let options2 = SentryViewScreenshotOptions(dictionary: [ + "enableViewRendererV2": false + ]) + + // -- Assert -- + XCTAssertFalse(options2.enableViewRendererV2) + } + + func testInitFromDict_enableViewRendererV2_whenInvalidValue_shouldUseDefaultValue() { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "enableViewRendererV2": "invalid_value" + ]) + + // -- Assert -- + XCTAssertTrue(options.enableViewRendererV2) + } + + func testInitFromDict_enableViewRendererV2_whenNotSpecified_shouldUseDefaultValue() { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [:]) + + // -- Assert -- + XCTAssertTrue(options.enableViewRendererV2) + } + + // MARK: - enableFastViewRendering + + func testInitFromDict_enableFastViewRendering_whenValidValue_shouldSetValue() { + let options = SentryViewScreenshotOptions(dictionary: [ + "enableFastViewRendering": true + ]) + XCTAssertTrue(options.enableFastViewRendering) + + let options2 = SentryViewScreenshotOptions(dictionary: [ + "enableFastViewRendering": false + ]) + XCTAssertFalse(options2.enableFastViewRendering) + } + + func testInitFromDict_enableFastViewRendering_whenInvalidValue_shouldUseDefaultValue() { + let options = SentryViewScreenshotOptions(dictionary: [ + "enableFastViewRendering": "invalid_value" + ]) + XCTAssertFalse(options.enableFastViewRendering) + } + + // MARK: - maskAllText + + func testInitFromDict_maskAllText_whenValidValue_shouldSetValue() { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "maskAllText": true + ]) + + // -- Assert -- + XCTAssertTrue(options.maskAllText) + + let options2 = SentryViewScreenshotOptions(dictionary: [ + "maskAllText": false + ]) + + // -- Assert -- + XCTAssertFalse(options2.maskAllText) + } + + func testInitFromDict_maskAllText_whenNotValidValue_shouldUseDefaultValue() { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "maskAllText": "invalid_value" + ]) + + // -- Assert -- + XCTAssertTrue(options.maskAllText) + } + + // MARK: - maskAllImages + + func testInitFromDict_maskAllImages_whenValidValue_shouldSetValue() { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "maskAllImages": true + ]) + + // -- Assert -- + XCTAssertTrue(options.maskAllImages) + + let options2 = SentryViewScreenshotOptions(dictionary: [ + "maskAllImages": false + ]) + + // -- Assert -- + XCTAssertFalse(options2.maskAllImages) + } + + func testInitFromDict_maskAllImages_whenNotValidValue_shouldUseDefaultValue() { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "maskAllImages": "invalid_value" + ]) + + // -- Assert -- + XCTAssertTrue(options.maskAllImages) + } + + // MARK: - maskedViewClasses + + func testInitFromDict_maskedViewClasses_whenValidValue_shouldSetValue() throws { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "maskedViewClasses": ["NSString"] + ]) + + // -- Assert -- + XCTAssertEqual(options.maskedViewClasses.count, 1) + let maskedClass: AnyClass = try XCTUnwrap(options.maskedViewClasses.first) + XCTAssertEqual(ObjectIdentifier(maskedClass), ObjectIdentifier(NSString.self)) + } + + func testInitFromDict_maskedViewClasses_whenMultipleValidValue_shouldKeepAll() throws { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "maskedViewClasses": ["NSString", "NSNumber"] + ]) + + // -- Assert -- + XCTAssertEqual(options.maskedViewClasses.count, 2) + guard options.maskedViewClasses.count == 2 else { + return XCTFail("Expected two masked view classes, can not proceed.") + } + XCTAssertEqual(ObjectIdentifier(options.maskedViewClasses[0]), ObjectIdentifier(NSString.self)) + XCTAssertEqual(ObjectIdentifier(options.maskedViewClasses[1]), ObjectIdentifier(NSNumber.self)) + } + + func testInitFromDict_maskedViewClasses_whenInvalidValue_shouldExcludedClass() { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "maskedViewClasses": "invalid_value" + ]) + + // -- Assert -- + XCTAssertEqual(options.maskedViewClasses.count, 0) + } + + func testInitFromDict_maskedViewClasses_whenInvalidArrayValue_shouldFilterInvalidValues() throws { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "maskedViewClasses": [ + "NSString", // Valid class + "some.class", // Invalid class name + 123, // Invalid type (number) + true, // Invalid type (boolean) + ["nested": "array"], // Invalid type (dictionary) + NSNull(), // Invalid type (NSNull) + "" // Empty string + ] as [Any] + ]) + + // -- Assert -- + XCTAssertEqual(options.maskedViewClasses.count, 1) + let maskedViewClass: AnyClass = try XCTUnwrap(options.maskedViewClasses.first) + XCTAssertEqual(ObjectIdentifier(maskedViewClass), ObjectIdentifier(NSString.self)) + } + + func testInitFromDict_maskedViewClasses_whenMixedValidAndInvalidValues_shouldKeepOnlyValidValues() throws { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "maskedViewClasses": [ + "NSString", // Valid class + "NSNumber", // Valid class + "not.a.class", // Invalid class name + 123 // Invalid type (number) + ] as [Any] + ]) + + // -- Assert -- + XCTAssertEqual(options.maskedViewClasses.count, 2) + guard options.maskedViewClasses.count == 2 else { + return XCTFail("Expected two masked view classes, can not proceed.") + } + XCTAssertEqual(ObjectIdentifier(options.maskedViewClasses[0]), ObjectIdentifier(NSString.self)) + XCTAssertEqual(ObjectIdentifier(options.maskedViewClasses[1]), ObjectIdentifier(NSNumber.self)) + } + + func testInitFromDict_maskedViewClasses_whenKeyOmitted_shouldUseDefaultValue() { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [:]) + + // -- Assert -- + XCTAssertEqual(options.maskedViewClasses.count, 0) + } + + // MARK: - unmaskedViewClasses + + func testInitFromDict_unmaskedViewClasses_whenValidValue_shouldSetValue() throws { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "unmaskedViewClasses": ["NSString"] + ]) + + // -- Assert -- + XCTAssertEqual(options.unmaskedViewClasses.count, 1) + let unmaskedClass: AnyClass = try XCTUnwrap(options.unmaskedViewClasses.first) + XCTAssertEqual(ObjectIdentifier(unmaskedClass), ObjectIdentifier(NSString.self)) + } + + func testInitFromDict_unmaskedViewClasses_whenMultipleValidValue_shouldKeepAll() throws { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "unmaskedViewClasses": ["NSString", "NSNumber"] + ]) + + // -- Assert -- + XCTAssertEqual(options.unmaskedViewClasses.count, 2) + guard options.unmaskedViewClasses.count == 2 else { + return XCTFail("Expected two unmasked view classes, can not proceed.") + } + XCTAssertEqual(ObjectIdentifier(options.unmaskedViewClasses[0]), ObjectIdentifier(NSString.self)) + XCTAssertEqual(ObjectIdentifier(options.unmaskedViewClasses[1]), ObjectIdentifier(NSNumber.self)) + } + + func testInitFromDict_unmaskedViewClasses_whenNotValidValue_shouldUseDefaultValue() { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "unmaskedViewClasses": "invalid_value" + ]) + + // -- Assert -- + XCTAssertEqual(options.unmaskedViewClasses.count, 0) + } + + func testInitFromDict_unmaskedViewClasses_whenInvalidArrayValues_shouldUseDefaultValue() throws { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "unmaskedViewClasses": [ + "not.a.class", // Invalid class name + 123, // Invalid type (number) + true, // Invalid type (boolean) + ["nested": "array"], // Invalid type (dictionary) + NSNull(), // Invalid type (NSNull) + "" // Empty string + ] as [Any] + ]) + + // -- Assert -- + XCTAssertEqual(options.unmaskedViewClasses.count, 0) + } + + func testInitFromDict_unmaskedViewClasses_whenMixedValidAndInvalidValues_shouldKeepOnlyValidValues() throws { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [ + "unmaskedViewClasses": [ + "NSString", // Valid class + "NSNumber", // Valid class + "not.a.class", // Invalid class name + 123 // Invalid type (number) + ] as [Any] + ]) + + // -- Assert -- + XCTAssertEqual(options.unmaskedViewClasses.count, 2) + guard options.unmaskedViewClasses.count == 2 else { + return XCTFail("Expected two unmasked view classes, can not proceed.") + } + XCTAssertEqual(ObjectIdentifier(options.unmaskedViewClasses[0]), ObjectIdentifier(NSString.self)) + XCTAssertEqual(ObjectIdentifier(options.unmaskedViewClasses[1]), ObjectIdentifier(NSNumber.self)) + } + + func testInitFromDict_unmaskedViewClasses_whenKeyOmitted_shouldUseDefaultValue() { + // -- Act -- + let options = SentryViewScreenshotOptions(dictionary: [:]) + + // -- Assert -- + XCTAssertEqual(options.unmaskedViewClasses.count, 0) + } + + // MARK: - Mixed Dictionary Options + + func testInitFromDict_withMultipleOptions_shouldSetAllValues() { + let options = SentryViewScreenshotOptions(dictionary: [ + "enableViewRendererV2": false, + "enableFastViewRendering": true, + "maskAllText": false, + "maskAllImages": false, + "maskedViewClasses": ["NSString", "not.a.class", 123] as [Any], + "unmaskedViewClasses": ["NSNumber", "invalid", true] as [Any] + ]) + + XCTAssertFalse(options.enableViewRendererV2) + XCTAssertTrue(options.enableFastViewRendering) + XCTAssertFalse(options.maskAllText) + XCTAssertFalse(options.maskAllImages) + XCTAssertEqual(options.maskedViewClasses.count, 1) + XCTAssertEqual(ObjectIdentifier(options.maskedViewClasses.first!), ObjectIdentifier(NSString.self)) + XCTAssertEqual(options.unmaskedViewClasses.count, 1) + XCTAssertEqual(ObjectIdentifier(options.unmaskedViewClasses.first!), ObjectIdentifier(NSNumber.self)) + } + + // MARK: - Description + + func testDescription_shouldContainAllProperties() { + // -- Arrange -- + let options = SentryViewScreenshotOptions( + enableViewRendererV2: false, + enableFastViewRendering: true, + maskAllText: false, + maskAllImages: false, + maskedViewClasses: [NSString.self], + unmaskedViewClasses: [NSNumber.self] + ) + + // -- Act -- + let description = options.description + + // -- Assert -- + XCTAssertTrue(description.contains("SentryViewScreenshotOptions")) + XCTAssertTrue(description.contains("enableViewRendererV2: false")) + XCTAssertTrue(description.contains("enableFastViewRendering: true")) + XCTAssertTrue(description.contains("maskAllText: false")) + XCTAssertTrue(description.contains("maskAllImages: false")) + XCTAssertTrue(description.contains("maskedViewClasses")) + XCTAssertTrue(description.contains("unmaskedViewClasses")) + } + + // MARK: - Default Values + + func testDefaultValues_shouldMatchExpectedValues() { + XCTAssertTrue(SentryViewScreenshotOptions.DefaultValues.enableViewRendererV2) + XCTAssertFalse(SentryViewScreenshotOptions.DefaultValues.enableFastViewRendering) + XCTAssertTrue(SentryViewScreenshotOptions.DefaultValues.maskAllText) + XCTAssertTrue(SentryViewScreenshotOptions.DefaultValues.maskAllImages) + XCTAssertEqual(SentryViewScreenshotOptions.DefaultValues.maskedViewClasses.count, 0) + XCTAssertEqual(SentryViewScreenshotOptions.DefaultValues.unmaskedViewClasses.count, 0) + } +} diff --git a/Tests/SentryTests/Integrations/Screenshot/TestSentryScreenShot.swift b/Tests/SentryTests/Integrations/Screenshot/TestSentryScreenshotProvider.swift similarity index 88% rename from Tests/SentryTests/Integrations/Screenshot/TestSentryScreenShot.swift rename to Tests/SentryTests/Integrations/Screenshot/TestSentryScreenshotProvider.swift index cdb98a485b3..a36c7ebfeea 100644 --- a/Tests/SentryTests/Integrations/Screenshot/TestSentryScreenShot.swift +++ b/Tests/SentryTests/Integrations/Screenshot/TestSentryScreenshotProvider.swift @@ -2,12 +2,12 @@ @_spi(Private) @testable import Sentry -class TestSentryScreenshot: SentryScreenshot { - +class TestSentryScreenshotSource: SentryScreenshotSource { + var result: [Data] = [] var images: [UIImage] = [] var processScreenshotsCallback: (() -> Void)? - + override func appScreenshotsData() -> [Data] { processScreenshotsCallback?() return result diff --git a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift index 7f19c170cbc..3421495abd8 100644 --- a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift @@ -7,15 +7,17 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { private static let dsnAsString = TestConstants.dsnAsString(username: "SentryCrashIntegrationTests") private class Fixture { + let dateProvider = TestCurrentDateProvider() let dispatchQueueWrapper = TestSentryDispatchQueueWrapper() let hub: SentryHub let client: TestClient! let options: Options let sentryCrash: TestSentryCrashWrapper - - init() { + let fileManager: TestFileManager + + init() throws { SentryDependencyContainer.sharedInstance().sysctlWrapper = TestSysctl() - sentryCrash = TestSentryCrashWrapper.sharedInstance() + sentryCrash = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo) sentryCrash.internalActiveDurationSinceLastCrash = 5.0 sentryCrash.internalCrashedLastLaunch = true @@ -24,8 +26,20 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { options.releaseName = TestData.appState.releaseName options.tracesSampleRate = 1.0 - client = TestClient(options: options, fileManager: try! SentryFileManager(options: options, dispatchQueueWrapper: dispatchQueueWrapper), deleteOldEnvelopeItems: false) + client = TestClient(options: options, fileManager: try! SentryFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: dispatchQueueWrapper + ), deleteOldEnvelopeItems: false) hub = TestHub(client: client, andScope: nil) + + fileManager = try TestFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: dispatchQueueWrapper + ) + + SentryDependencyContainer.sharedInstance().dateProvider = dateProvider } var session: SentrySession { @@ -49,12 +63,12 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { return SentryCrashIntegration(crashAdapter: crash, andDispatchQueueWrapper: dispatchQueueWrapper) } } + + private var fixture: Fixture! - private lazy var fixture = Fixture() - - override func setUp() { - super.setUp() - SentryDependencyContainer.sharedInstance().dateProvider = TestCurrentDateProvider() + override func setUpWithError() throws { + try super.setUpWithError() + fixture = try Fixture() fixture.client.fileManager.deleteCurrentSession() fixture.client.fileManager.deleteCrashedSession() @@ -62,7 +76,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { fixture.client.fileManager.deleteAppState() fixture.client.fileManager.deleteAppHangEvent() - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setStart(with: fixture.options) } override func tearDown() { @@ -77,6 +91,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { } // Test for GH-581 + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testReleaseNamePassedToSentryCrash() throws { let releaseName = "1.0.0" let dist = "14G60" @@ -95,6 +110,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { assertUserInfoField(userInfo: userInfo, key: "dist", expected: dist) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testContext_IsPassedToSentryCrash() throws { SentrySDK.start { options in options.dsn = SentryCrashIntegrationTests.dsnAsString @@ -109,7 +125,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { func testEndSessionAsCrashed_WithCurrentSession() throws { let expectedCrashedSession = givenCrashedSession() - SentrySDK.setCurrentHub(fixture.hub) + SentrySDKInternal.setCurrentHub(fixture.hub) try advanceTime(bySeconds: 10) @@ -122,11 +138,11 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) func testEndSessionAsCrashed_WhenOOM_WithCurrentSession() throws { givenOOMAppState() - SentrySDK.startInvocations = 1 + SentrySDKInternal.startInvocations = 1 let expectedCrashedSession = givenCrashedSession() - SentrySDK.setCurrentHub(fixture.hub) + SentrySDKInternal.setCurrentHub(fixture.hub) try advanceTime(bySeconds: 10) let sut = fixture.sutWithoutCrash @@ -210,7 +226,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { func testEndSessionAsAbnormal_NoCurrentSession() { // Arrange - SentrySDK.setCurrentHub(fixture.hub) + SentrySDKInternal.setCurrentHub(fixture.hub) let sentryCrash = fixture.sentryCrash sentryCrash.internalCrashedLastLaunch = false let sut = SentryCrashIntegration(crashAdapter: sentryCrash, andDispatchQueueWrapper: fixture.dispatchQueueWrapper) @@ -227,7 +243,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { func testEndSessionAsAbnormal_NoAppHangEvent() { // Arrange - SentrySDK.setCurrentHub(fixture.hub) + SentrySDKInternal.setCurrentHub(fixture.hub) let sentryCrash = fixture.sentryCrash sentryCrash.internalCrashedLastLaunch = false let sut = SentryCrashIntegration(crashAdapter: sentryCrash, andDispatchQueueWrapper: fixture.dispatchQueueWrapper) @@ -246,10 +262,14 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { func testEndSessionAsAbnormal_AppHangEventDeletedInBetween() throws { // Arrange - let fileManager = try DeleteAppHangWhenCheckingExistenceFileManager(options: fixture.options) + let fileManager = try DeleteAppHangWhenCheckingExistenceFileManager( + options: fixture.options, + dateProvider: TestCurrentDateProvider(), + dispatchQueueWrapper: fixture.dispatchQueueWrapper + ) fixture.client.fileManager = fileManager - SentrySDK.setCurrentHub(fixture.hub) + SentrySDKInternal.setCurrentHub(fixture.hub) let sentryCrash = fixture.sentryCrash sentryCrash.internalCrashedLastLaunch = false let sut = SentryCrashIntegration(crashAdapter: sentryCrash, andDispatchQueueWrapper: fixture.dispatchQueueWrapper) @@ -269,7 +289,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { func testEndSessionAsAbnormal_AppHangEvent_EndsSessionAsAbnormal() throws { // Arrange - SentrySDK.setCurrentHub(fixture.hub) + SentrySDKInternal.setCurrentHub(fixture.hub) let sentryCrash = fixture.sentryCrash sentryCrash.internalCrashedLastLaunch = false let sut = SentryCrashIntegration(crashAdapter: sentryCrash, andDispatchQueueWrapper: fixture.dispatchQueueWrapper) @@ -300,7 +320,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { func testEndSessionAsAbnormal_AppHangEventAndCrash_EndsSessionAsCrashed() throws { // Arrange let expectedCrashedSession = givenCrashedSession() - SentrySDK.setCurrentHub(fixture.hub) + SentrySDKInternal.setCurrentHub(fixture.hub) let fileManager = fixture.client.fileManager let appHangEvent = Event() fileManager.storeAppHang(appHangEvent) @@ -378,7 +398,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { api?.pointee.setEnabled(true) let transport = TestTransport() - let client = SentryClient(options: fixture.options, fileManager: try TestFileManager(options: fixture.options), deleteOldEnvelopeItems: false) + let client = SentryClient(options: fixture.options, fileManager: fixture.fileManager, deleteOldEnvelopeItems: false) Dynamic(client).transportAdapter = TestTransportAdapter(transports: [transport], options: fixture.options) hub.bindClient(client) @@ -540,9 +560,9 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { let client = SentryClient(options: options) defer { client?.fileManager.deleteAllEnvelopes() } let hub = SentryHub(client: client, andScope: nil) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) - let sut = fixture.getSut(crashWrapper: SentryCrashWrapper.sharedInstance()) + let sut = fixture.getSut(crashWrapper: SentryDependencyContainer.sharedInstance().crashWrapper) sut.install(with: options) let transaction = SentrySDK.startTransaction(name: "Crashing", operation: "Operation", bindToScope: true) @@ -565,13 +585,13 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { let client = SentryClient(options: options) defer { client?.fileManager.deleteAllEnvelopes() } let hub = SentryHub(client: client, andScope: nil) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) - let sut = fixture.getSut(crashWrapper: SentryCrashWrapper.sharedInstance()) + let sut = fixture.getSut(crashWrapper: SentryDependencyContainer.sharedInstance().crashWrapper) sut.install(with: options) let transaction = SentrySDK.startTransaction(name: "name", operation: "operation", bindToScope: true) - SentrySDK.currentHub().scope.span = nil + SentrySDKInternal.currentHub().scope.span = nil sentrycrash_invokeSaveTransaction() @@ -586,14 +606,14 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { let client = SentryClient(options: options) defer { client?.fileManager.deleteAllEnvelopes() } let hub = SentryHub(client: client, andScope: nil) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) - let sut = fixture.getSut(crashWrapper: SentryCrashWrapper.sharedInstance()) + let sut = fixture.getSut(crashWrapper: SentryDependencyContainer.sharedInstance().crashWrapper) sut.install(with: options) let transaction = SentrySDK.startTransaction(name: "name", operation: "operation", bindToScope: true) let span = transaction.startChild(operation: "child") - SentrySDK.currentHub().scope.span = span + SentrySDKInternal.currentHub().scope.span = span sentrycrash_invokeSaveTransaction() @@ -630,7 +650,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { private func givenSutWithGlobalHub() -> (SentryCrashIntegration, SentryHub) { let sut = fixture.getSut() let hub = fixture.hub - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) return (sut, hub) } @@ -639,9 +659,9 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) SentryDependencyContainer.sharedInstance().uiDeviceWrapper.start() #endif - let sut = fixture.getSut(crashWrapper: SentryCrashWrapper.sharedInstance()) + let sut = fixture.getSut(crashWrapper: SentryDependencyContainer.sharedInstance().crashWrapper) let hub = fixture.hub - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) return (sut, hub) } diff --git a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift index 867cbc695bb..5cdaa46782e 100644 --- a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift +++ b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashReportTests.swift @@ -173,12 +173,29 @@ class SentryCrashReportTests: XCTestCase { } #if os(iOS) && !targetEnvironment(macCatalyst) - // We can't really test writing the crash_info_message unless there is an actual crash. - // We noticed that the libsystem_sim_platform.dylib is a simulator library that has a crash info message even when there is no crash. - // This is simply a smoke test to ensure we can write the crash_info_message key to the report. - // This only works on iOS and also not macCatalyst. - // Actual testing must be done manually with a fatalError in Swift. + // We can't really test reading the crash_info_message from the crash_info section unless there is an + // actual crash. To correctly test this, you must use an fatalError and let an app crash. + // + // While building this feature, we noticed that the libsystem_sim_platform.dylib, a simulator library, + // puts information about the simulator into the crash info section, for example: + // CoreSimulator 1047 - Device: iPhone 16 Pro iOS 26.0 (6EDB2433-B0C8-4501-924A-16B5D13F7435) - Runtime: iOS 26.0 (23A5326a) - DeviceType: iPhone 16 Pro + // + // On iOS 26.0, we identified that the crash info suddenly uses version 7, but sadly, we didn't identify + // the root cause or find any evidence in the Swift or Xcode release notes. We could change reading the + // crash info also with version 7, which would fix this unit test, but we decided against this approach + // because the fatal error using the crash info section still works correctly with version 5, and using + // version 7 brings an unknown risk with it. Neither KSCrash or Firebase Crashlytics read above version 5. + // Furthermore, we experienced crashes when accessing the crashInfo message when ignoring the safety checks + // in getCrashInfo. It seems incorrect to adapt the getCrashInfo to make a unit test work that doesn’t + // actually test the functionality. It seems like libsystem_sim_platform.dylib simply uses the crash info + // section to store device information. + // + // Therefore, we keep this test as is and skip it on iOS 26.0 and above. func testWriteCrashReport_ContainsCrashInfoMessage() throws { + if #available(iOS 26.0, *) { + throw XCTSkip("This test is only works on iOS versions before 26.0") + } + writeCrashReport() let crashReportContents = FileManager.default.contents(atPath: fixture.reportPath) ?? Data() diff --git a/Tests/SentryTests/Integrations/Session/SentrySessionGeneratorTests.swift b/Tests/SentryTests/Integrations/Session/SentrySessionGeneratorTests.swift index f1af1a3b103..98c9f905cb0 100644 --- a/Tests/SentryTests/Integrations/Session/SentrySessionGeneratorTests.swift +++ b/Tests/SentryTests/Integrations/Session/SentrySessionGeneratorTests.swift @@ -22,6 +22,7 @@ class SentrySessionGeneratorTests: NotificationCenterTestCase { private var options: Options! private var fileManager: SentryFileManager! + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") override func setUp() { super.setUp() @@ -38,8 +39,12 @@ class SentrySessionGeneratorTests: NotificationCenterTestCase { return name != "SentryAutoSessionTrackingIntegration" } - fileManager = try! SentryFileManager(options: options, dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) - + fileManager = try! SentryFileManager( + options: options, + dateProvider: TestCurrentDateProvider(), + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ) + fileManager.deleteCurrentSession() fileManager.deleteCrashedSession() fileManager.deleteTimestampLastInForeground() @@ -101,7 +106,7 @@ class SentrySessionGeneratorTests: NotificationCenterTestCase { let fatalEvent = Event() fatalEvent.level = SentryLevel.fatal fatalEvent.message = SentryMessage(formatted: "Crash for SentrySessionGeneratorTests") - SentrySDK.captureFatalEvent(fatalEvent) + SentrySDKInternal.captureFatalEvent(fatalEvent) } sentryCrash.internalCrashedLastLaunch = false @@ -118,7 +123,7 @@ class SentrySessionGeneratorTests: NotificationCenterTestCase { autoSessionTrackingIntegration.install(with: options) goToForeground() - SentrySDK.captureFatalEvent(TestData.oomEvent) + SentrySDKInternal.captureFatalEvent(TestData.oomEvent) } fileManager.deleteAppState() #endif @@ -140,10 +145,10 @@ class SentrySessionGeneratorTests: NotificationCenterTestCase { SentrySDK.start(options: options) - sentryCrash = TestSentryCrashWrapper.sharedInstance() - let client = SentrySDK.currentHub().getClient() + sentryCrash = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo) + let client = SentrySDKInternal.currentHub().getClient() let hub = SentryHub(client: client, andScope: nil, andCrashWrapper: self.sentryCrash, andDispatchQueue: SentryDispatchQueueWrapper()) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) crashIntegration = SentryCrashIntegration(crashAdapter: sentryCrash, andDispatchQueueWrapper: TestSentryDispatchQueueWrapper()) crashIntegration.install(with: options) diff --git a/Tests/SentryTests/Integrations/Session/SentrySessionTrackerTests.swift b/Tests/SentryTests/Integrations/Session/SentrySessionTrackerTests.swift index 4bb0a6d85c4..fd6b4777da0 100644 --- a/Tests/SentryTests/Integrations/Session/SentrySessionTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Session/SentrySessionTrackerTests.swift @@ -20,7 +20,7 @@ class SentrySessionTrackerTests: XCTestCase { #endif let notificationCenter = TestNSNotificationCenterWrapper() let dispatchQueue = TestSentryDispatchQueueWrapper() - lazy var fileManager = try! SentryFileManager(options: options, dispatchQueueWrapper: dispatchQueue) + lazy var fileManager = try! SentryFileManager(options: options, dateProvider: currentDateProvider, dispatchQueueWrapper: dispatchQueue) init() { options = Options() @@ -31,11 +31,11 @@ class SentrySessionTrackerTests: XCTestCase { client = TestClient(options: options) - sentryCrash = TestSentryCrashWrapper.sharedInstance() + sentryCrash = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo) #if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) application = TestSentryUIApplication() - application.applicationState = .inactive + application.unsafeApplicationState = .inactive SentryDependencyContainer.sharedInstance().application = application #else application = TestSentryNSApplication() @@ -55,7 +55,7 @@ class SentrySessionTrackerTests: XCTestCase { func setNewHubToSDK() { let hub = SentryHub(client: client, andScope: nil, andCrashWrapper: self.sentryCrash, andDispatchQueue: SentryDispatchQueueWrapper()) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) } } @@ -428,24 +428,24 @@ class SentrySessionTrackerTests: XCTestCase { assertSessionsSent(count: 2) } - func testStart_AddsObservers() { + func testStart_AddsObservers() throws { // -- Act -- startSutInAppDelegate() // -- Assert -- - let invocations = fixture.notificationCenter.addObserverInvocations - let notificationNames = invocations.invocations.map { $0.name } + let invocations = fixture.notificationCenter.addObserverWithObjectInvocations + let notificationNames = try invocations.invocations.map { try XCTUnwrap($0.name) } assertNotificationNames(notificationNames) } - func testStop_RemovesObservers() { + func testStop_RemovesObservers() throws { // -- Act -- stopSut() // -- Assert -- - let invocations = fixture.notificationCenter.removeObserverWithNameInvocations - let notificationNames = invocations.invocations.map { $0 } + let invocations = fixture.notificationCenter.removeObserverWithNameAndObjectInvocations + let notificationNames = try invocations.invocations.map { try XCTUnwrap($0.name) } assertNotificationNames(notificationNames) } @@ -539,7 +539,7 @@ class SentrySessionTrackerTests: XCTestCase { // become the active app yet. // // This can be observed by viewing the application state in `UIAppDelegate.didFinishLaunchingWithOptions`. - fixture.application.applicationState = .inactive + fixture.application.unsafeApplicationState = .inactive #else // The Sentry SDK should be initialized in the `NSApplicationDelegate.applicationDidFinishLaunching` // At this point the app is not active yet. @@ -564,7 +564,7 @@ class SentrySessionTrackerTests: XCTestCase { #if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) // When the app stops, the app state is `inactive`. // This can be observed by viewing the application state in `UIAppDelegate.applicationDidEnterBackground`. - fixture.application.applicationState = .inactive + fixture.application.unsafeApplicationState = .inactive #else // When the app crashes, the app state is `inactive`. // @@ -580,7 +580,7 @@ class SentrySessionTrackerTests: XCTestCase { // When the app stops, the app state is `inactive`. // // This can be observed by viewing the application state in `UIAppDelegate.applicationDidEnterBackground`. - fixture.application.applicationState = .inactive + fixture.application.unsafeApplicationState = .inactive #else // When the app crashes, the app state is `inactive`. // @@ -599,7 +599,7 @@ class SentrySessionTrackerTests: XCTestCase { #if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) // When the app becomes active, the app state is `active`. // This can be observed by viewing the application state in `UIAppDelegate.applicationDidBecomeActive`. - fixture.application.applicationState = .active + fixture.application.unsafeApplicationState = .active #else // When the app becomes active, the app state is `active`. // This can be observed by viewing the application state in `NSApplicationDelegate.applicationDidBecomeActive`. @@ -620,7 +620,7 @@ class SentrySessionTrackerTests: XCTestCase { willResignActive() #if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) // It is expected that the app state is background when the didEnterBackground is called - fixture.application.applicationState = .background + fixture.application.unsafeApplicationState = .background fixture.notificationCenter .post( Notification( @@ -642,7 +642,7 @@ class SentrySessionTrackerTests: XCTestCase { // When the app is about to resign being active, it is still active. // // This can be observed by viewing the application state in `UIAppDelegate.applicationWillResignActive`. - fixture.application.applicationState = .active + fixture.application.unsafeApplicationState = .active #else // When the app becomes active, the app state is `active`. // @@ -662,7 +662,7 @@ class SentrySessionTrackerTests: XCTestCase { private func hybridSdkDidBecomeActive() { // When an app did become active, it is in the active state. #if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) - fixture.application.applicationState = .active + fixture.application.unsafeApplicationState = .active #else fixture.application.setIsActive(true) #endif @@ -687,7 +687,7 @@ class SentrySessionTrackerTests: XCTestCase { // When terminating an app, it will first move to the background and then terminate. // // This can be observed by viewing the application state in `UIAppDelegate.applicationWillTerminate`. - fixture.application.applicationState = .background + fixture.application.unsafeApplicationState = .background #else // When terminating an app, it will first move to the background and then terminate. // @@ -858,7 +858,7 @@ class SentrySessionTrackerTests: XCTestCase { fixture.fileManager.storeCrashedSession(crashedSession) startSutInAppDelegate() - SentrySDK.captureFatalEvent(Event()) + SentrySDKInternal.captureFatalEvent(Event()) let session = try XCTUnwrap(fixture.client.captureFatalEventWithSessionInvocations.last?.session) assertSession(session: session, started: sessionStartTime, status: SentrySessionStatus.crashed, duration: 5) @@ -878,7 +878,7 @@ class SentrySessionTrackerTests: XCTestCase { private func postHybridSdkDidBecomeActiveNotification() { // When the hybrid SDK posts this notification, the app should be in active state #if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) - fixture.application.applicationState = .active + fixture.application.unsafeApplicationState = .active #else fixture.application.setIsActive(true) #endif @@ -891,32 +891,4 @@ class SentrySessionTrackerTests: XCTestCase { ) ) } - -#if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) - private class TestSentryUIApplication: SentryUIApplication { - init() { - super.init(notificationCenterWrapper: TestNSNotificationCenterWrapper(), dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) - } - - private var _underlyingAppState: UIApplication.State = .active - override var applicationState: UIApplication.State { - get { _underlyingAppState } - set { _underlyingAppState = newValue } - } - - override func isActive() -> Bool { - return applicationState == .active - } - } -#else - private class TestSentryNSApplication: SentryNSApplication { - private var _underlyingIsActive = true - func setIsActive(_ isActive: Bool) { - _underlyingIsActive = isActive - } - override func isActive() -> Bool { - return _underlyingIsActive - } - } -#endif } diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentryOnDemandReplayTests.swift b/Tests/SentryTests/Integrations/SessionReplay/SentryOnDemandReplayTests.swift index fc6c7b06e55..63cd9bd793f 100644 --- a/Tests/SentryTests/Integrations/SessionReplay/SentryOnDemandReplayTests.swift +++ b/Tests/SentryTests/Integrations/SessionReplay/SentryOnDemandReplayTests.swift @@ -122,20 +122,28 @@ class SentryOnDemandReplayTests: XCTestCase { processingQueue: processingQueue, assetWorkerQueue: workerQueue ) - let group = DispatchGroup() + + let loopCount = 10 + let expectation = XCTestExpectation(description: "AddFrameIsThreadSafe") + expectation.expectedFulfillmentCount = loopCount + expectation.assertForOverFulfill = true let start = Date(timeIntervalSinceReferenceDate: 0) - for i in 0..<10 { - group.enter() + for i in 0.. [String]? { - guard let screenName = screenName else { return nil } - return [screenName] - } - } - private class TestCrashWrapper: SentryCrashWrapper { let traced: Bool init(traced: Bool = true) { self.traced = traced - // not calling super.init() here as we don't actually want to install crash reporter machinery + super.init(processInfoWrapper: ProcessInfo.processInfo, systemInfo: [:]) // Call the test designated initializer } - override func isBeingTraced() -> Bool { + override public var isBeingTraced: Bool { traced } } @@ -48,6 +31,7 @@ class SentrySessionReplayIntegrationTests: XCTestCase { private var globalEventProcessor = SentryGlobalEventProcessor() override func setUp() { + uiApplication.windows = [UIWindow()] SentryDependencyContainer.sharedInstance().application = uiApplication SentryDependencyContainer.sharedInstance().reachability = TestSentryReachability() SentryDependencyContainer.sharedInstance().globalEventProcessor = globalEventProcessor @@ -59,7 +43,7 @@ class SentrySessionReplayIntegrationTests: XCTestCase { } private func getSut() throws -> SentrySessionReplayIntegration { - return try XCTUnwrap(SentrySDK.currentHub().installedIntegrations().first as? SentrySessionReplayIntegration) + return try XCTUnwrap(SentrySDKInternal.currentHub().installedIntegrations().first as? SentrySessionReplayIntegration) } private func startSDK(sessionSampleRate: Float, errorSampleRate: Float, enableSwizzling: Bool = true, noIntegrations: Bool = false, configure: ((Options) -> Void)? = nil) { @@ -71,26 +55,26 @@ class SentrySessionReplayIntegrationTests: XCTestCase { $0.cacheDirectoryPath = FileManager.default.temporaryDirectory.path configure?($0) } - SentrySDK.currentHub().startSession() + SentrySDKInternal.currentHub().startSession() } func testNoInstall() { startSDK(sessionSampleRate: 0, errorSampleRate: 0) - XCTAssertEqual(SentrySDK.currentHub().trimmedInstalledIntegrationNames().count, 0) + XCTAssertEqual(SentrySDKInternal.currentHub().trimmedInstalledIntegrationNames().count, 0) XCTAssertEqual(globalEventProcessor.processors.count, 0) } func testInstallFullSessionReplay() { startSDK(sessionSampleRate: 1, errorSampleRate: 0) - XCTAssertEqual(SentrySDK.currentHub().trimmedInstalledIntegrationNames().count, 1) + XCTAssertEqual(SentrySDKInternal.currentHub().trimmedInstalledIntegrationNames().count, 1) XCTAssertEqual(globalEventProcessor.processors.count, 1) } func testInstallNoSwizzlingNoTouchTracker() { startSDK(sessionSampleRate: 1, errorSampleRate: 0, enableSwizzling: false) - guard let integration = SentrySDK.currentHub().installedIntegrations().first as? SentrySessionReplayIntegration + guard let integration = SentrySDKInternal.currentHub().installedIntegrations().first as? SentrySessionReplayIntegration else { XCTFail("Could not find session replay integration") return @@ -107,7 +91,7 @@ class SentrySessionReplayIntegrationTests: XCTestCase { func testInstallFullSessionReplayButDontRunBecauseOfRandom() throws { SentryDependencyContainer.sharedInstance().random = TestRandom(value: 0.3) startSDK(sessionSampleRate: 0.2, errorSampleRate: 0) - XCTAssertEqual(SentrySDK.currentHub().trimmedInstalledIntegrationNames().count, 1) + XCTAssertEqual(SentrySDKInternal.currentHub().trimmedInstalledIntegrationNames().count, 1) XCTAssertEqual(globalEventProcessor.processors.count, 1) let sut = try getSut() XCTAssertNil(sut.sessionReplay) @@ -118,7 +102,7 @@ class SentrySessionReplayIntegrationTests: XCTestCase { startSDK(sessionSampleRate: 0.3, errorSampleRate: 0) - XCTAssertEqual(SentrySDK.currentHub().trimmedInstalledIntegrationNames().count, 1) + XCTAssertEqual(SentrySDKInternal.currentHub().trimmedInstalledIntegrationNames().count, 1) XCTAssertEqual(globalEventProcessor.processors.count, 1) let sut = try getSut() XCTAssertNotNil(sut.sessionReplay) @@ -127,18 +111,18 @@ class SentrySessionReplayIntegrationTests: XCTestCase { func testInstallErrorReplay() { startSDK(sessionSampleRate: 0, errorSampleRate: 0.1) - XCTAssertEqual(SentrySDK.currentHub().trimmedInstalledIntegrationNames().count, 1) + XCTAssertEqual(SentrySDKInternal.currentHub().trimmedInstalledIntegrationNames().count, 1) XCTAssertEqual(globalEventProcessor.processors.count, 1) } func testWaitForNotificationWithNoWindow() throws { - uiApplication.windowsMock = nil + uiApplication.windows = nil startSDK(sessionSampleRate: 1, errorSampleRate: 0) let sut = try getSut() XCTAssertNil(sut.sessionReplay) - uiApplication.windowsMock = [UIWindow()] + uiApplication.windows = [UIWindow()] NotificationCenter.default.post(name: UIScene.didActivateNotification, object: nil) XCTAssertNotNil(sut.sessionReplay) } @@ -159,7 +143,7 @@ class SentrySessionReplayIntegrationTests: XCTestCase { let sut = try getSut() XCTAssertNotNil(sut.sessionReplay) - SentrySDK.currentHub().endSession() + SentrySDKInternal.currentHub().endSession() XCTAssertNil(sut.sessionReplay) } @@ -177,9 +161,9 @@ class SentrySessionReplayIntegrationTests: XCTestCase { let sut = try getSut() XCTAssertNotNil(sut.sessionReplay) - SentrySDK.currentHub().endSession() + SentrySDKInternal.currentHub().endSession() XCTAssertNil(sut.sessionReplay) - SentrySDK.currentHub().startSession() + SentrySDKInternal.currentHub().startSession() XCTAssertNotNil(sut.sessionReplay) } @@ -187,30 +171,30 @@ class SentrySessionReplayIntegrationTests: XCTestCase { startSDK(sessionSampleRate: 1, errorSampleRate: 0) let sut = try getSut() - SentrySDK.currentHub().startSession() + SentrySDKInternal.currentHub().startSession() XCTAssertNotNil(sut.sessionReplay) let oldSessionReplay = sut.sessionReplay XCTAssertTrue(oldSessionReplay?.isRunning ?? false) - SentrySDK.currentHub().startSession() + SentrySDKInternal.currentHub().startSession() XCTAssertFalse(oldSessionReplay?.isRunning ?? true) } func testScreenNameFromSentryUIApplication() throws { startSDK(sessionSampleRate: 1, errorSampleRate: 1) let sut: SentrySessionReplayDelegate = try getSut() as! SentrySessionReplayDelegate - uiApplication.screenName = "Test Screen" + uiApplication._relevantViewControllerNames = ["Test Screen"] XCTAssertEqual(sut.currentScreenNameForSessionReplay(), "Test Screen") } func testScreenNameFromSentryScope() throws { startSDK(sessionSampleRate: 1, errorSampleRate: 1) - SentrySDK.currentHub().configureScope { scope in + SentrySDKInternal.currentHub().configureScope { scope in scope.currentScreen = "Scope Screen" } let sut: SentrySessionReplayDelegate = try getSut() as! SentrySessionReplayDelegate - uiApplication.screenName = "Test Screen" + uiApplication._relevantViewControllerNames = ["Test Screen"] XCTAssertEqual(sut.currentScreenNameForSessionReplay(), "Scope Screen") } @@ -219,11 +203,11 @@ class SentrySessionReplayIntegrationTests: XCTestCase { startSDK(sessionSampleRate: 1, errorSampleRate: 1) - let client = SentryClient(options: try XCTUnwrap(SentrySDK.options)) + let client = SentryClient(options: try XCTUnwrap(SentrySDKInternal.options)) let scope = Scope() let hub = TestHub(client: client, andScope: scope) - SentrySDK.setCurrentHub(hub) - let expectation = expectation(description: "Replay to be capture") + SentrySDKInternal.setCurrentHub(hub) + let expectation = expectation(description: "Replay to be captured") hub.onReplayCapture = { expectation.fulfill() } @@ -247,11 +231,11 @@ class SentrySessionReplayIntegrationTests: XCTestCase { startSDK(sessionSampleRate: 1, errorSampleRate: 1) - let client = SentryClient(options: try XCTUnwrap(SentrySDK.options)) + let client = SentryClient(options: try XCTUnwrap(SentrySDKInternal.options)) let scope = Scope() let hub = TestHub(client: client, andScope: scope) - SentrySDK.setCurrentHub(hub) - let expectation = expectation(description: "Replay to be capture") + SentrySDKInternal.setCurrentHub(hub) + let expectation = expectation(description: "Replay to be captured") hub.onReplayCapture = { expectation.fulfill() } @@ -271,23 +255,73 @@ class SentrySessionReplayIntegrationTests: XCTestCase { } func testBufferReplayIgnoredBecauseSampleRateForCrash() throws { - startSDK(sessionSampleRate: 1, errorSampleRate: 1) + // -- Arrange -- + // Use deterministic random number to avoid flaky test behavior. + // CRITICAL: Set random value to 1.0 to ensure shouldReplayFullSession(sessionSampleRate) returns false, + // preventing the session from starting as a full session. Buffer replay sample rate checks + // only apply to non-full sessions. The sample rate check uses: random >= errorSampleRate + // With errorSampleRate=0 and random=1.0: 1.0 >= 0 = true → replay dropped + SentryDependencyContainer.sharedInstance().random = TestRandom(value: 1.0) + + // Start current session with 0% session sample rate to ensure it's NOT a full session + // (shouldReplayFullSession: 1.0 < 0 = false), but 100% error sample rate would normally + // capture all error replays if this were not a buffer replay from previous session + startSDK(sessionSampleRate: 0, errorSampleRate: 1) + + let client = SentryClient(options: try XCTUnwrap(SentrySDKInternal.options)) + let scope = Scope() + let hub = TestHub(client: client, andScope: scope) + SentrySDKInternal.setCurrentHub(hub) + let expectation = expectation(description: "Replay to be captured") + expectation.isInverted = true // We expect NO replay to be captured + hub.onReplayCapture = { + expectation.fulfill() + } + + // -- Act -- + // Create a previous session replay file with 0% error sample rate. + // This simulates a previous session that crashed and had error replay disabled. + // The key insight: replay capture decision uses the PREVIOUS session's sample rate, + // not the current session's sample rate, because the replay frames were recorded + // during the previous session with its own sampling configuration. + try createLastSessionReplay(writeSessionInfo: false, errorSampleRate: 0) + let crash = Event(error: NSError(domain: "Error", code: 1)) + crash.context = [:] + crash.isFatalEvent = true + globalEventProcessor.reportAll(crash) // This triggers resumePreviousSessionReplay + + // -- Assert -- + // The replay should be dropped because: + // 1. Previous session had errorSampleRate = 0 (no error replays wanted) + // 2. Sample rate check: 1.0 >= 0 = true → drop replay + // 3. Current session's errorSampleRate = 1 is irrelevant for previous session data + wait(for: [expectation], timeout: 1) + XCTAssertEqual(hub.capturedReplayRecordingVideo.count, 0) + } + + func testBufferReplayIgnoredBecauseEventDroppedInBeforeSend() throws { + try createLastSessionReplay(writeSessionInfo: false) - let client = SentryClient(options: try XCTUnwrap(SentrySDK.options)) + startSDK(sessionSampleRate: 1, errorSampleRate: 1, configure: { options in + options.beforeSend = { _ in + return nil + } + }) + + let client = SentryClient(options: try XCTUnwrap(SentrySDKInternal.options)) let scope = Scope() let hub = TestHub(client: client, andScope: scope) - SentrySDK.setCurrentHub(hub) - let expectation = expectation(description: "Replay to be capture") + SentrySDKInternal.setCurrentHub(hub) + let expectation = expectation(description: "Replay to be captured") expectation.isInverted = true hub.onReplayCapture = { expectation.fulfill() } - try createLastSessionReplay(writeSessionInfo: false, errorSampleRate: 0) let crash = Event(error: NSError(domain: "Error", code: 1)) crash.context = [:] crash.isFatalEvent = true - globalEventProcessor.reportAll(crash) + try XCTUnwrap(client).capture(event: crash) wait(for: [expectation], timeout: 1) XCTAssertEqual(hub.capturedReplayRecordingVideo.count, 0) @@ -342,7 +376,7 @@ class SentrySessionReplayIntegrationTests: XCTestCase { func testStartWithNoSessionReplay() throws { startSDK(sessionSampleRate: 0, errorSampleRate: 0, noIntegrations: true) - var sut = SentrySDK.currentHub().installedIntegrations().first as? SentrySessionReplayIntegration + var sut = SentrySDKInternal.currentHub().installedIntegrations().first as? SentrySessionReplayIntegration XCTAssertNil(sut) SentrySDK.replay.start() sut = try getSut() @@ -506,8 +540,12 @@ class SentrySessionReplayIntegrationTests: XCTestCase { let dispatchQueue = TestSentryDispatchQueueWrapper() SentryDependencyContainer.sharedInstance().dispatchQueueWrapper = dispatchQueue - SentryDependencyContainer.sharedInstance().fileManager = try SentryFileManager(options: options) - + SentryDependencyContainer.sharedInstance().fileManager = try SentryFileManager( + options: options, + dateProvider: SentryDependencyContainer.sharedInstance().dateProvider, + dispatchQueueWrapper: dispatchQueue + ) + if FileManager.default.fileExists(atPath: replayFolder()) { try FileManager.default.removeItem(atPath: replayFolder()) } @@ -561,7 +599,7 @@ class SentrySessionReplayIntegrationTests: XCTestCase { func testShowMaskPreviewForDebug() throws { SentryDependencyContainer.sharedInstance().crashWrapper = TestCrashWrapper(traced: true) let window = UIWindow() - uiApplication.windowsMock = [window] + uiApplication.windows = [window] startSDK(sessionSampleRate: 0, errorSampleRate: 1) let sut = try getSut() @@ -574,7 +612,7 @@ class SentrySessionReplayIntegrationTests: XCTestCase { func testDontShowMaskPreviewForRelese() throws { SentryDependencyContainer.sharedInstance().crashWrapper = TestCrashWrapper(traced: false) let window = UIWindow() - uiApplication.windowsMock = [window] + uiApplication.windows = [window] startSDK(sessionSampleRate: 0, errorSampleRate: 1) let sut = try getSut() @@ -667,6 +705,33 @@ class SentrySessionReplayIntegrationTests: XCTestCase { XCTAssertLessThan(processingQueue.queue.qos.relativePriority, assetWorkerQueue.queue.qos.relativePriority) } + /// This test ensures to not have memory leaks in the SentrySessionReplayIntegration, such as a strong reference cycle. + /// For example, removing the weak reference for accessing self when adding the globalEventProcessor would leak memory and + /// this test would start to fail when doing so. + func testSessionReplayIntegration_DoesNotLeakMemory() throws { + + // -- Arrange -- + weak var weakSut: SentrySessionReplayIntegration? + + // Put into extra func so ARC deallocates the sut + func allocateSutAndDealloc() throws { + let options = Options() + options.sessionReplay = SentryReplayOptions(sessionSampleRate: 1.0, onErrorSampleRate: 1.0) + + let instance = SentrySessionReplayIntegration() + instance.install(with: options) + instance.uninstall() + + weakSut = instance + } + + // -- Act -- + try allocateSutAndDealloc() + + // -- Assert -- + XCTAssertNil(weakSut, "SentrySessionReplayIntegration should be deallocated") + } + private func createLastSessionReplay(writeSessionInfo: Bool = true, errorSampleRate: Double = 1) throws { let replayFolder = replayFolder() let jsonPath = replayFolder + "/replay.current" diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentryVideoFrameProcessorTests.swift b/Tests/SentryTests/Integrations/SessionReplay/SentryVideoFrameProcessorTests.swift new file mode 100644 index 00000000000..07014849ac5 --- /dev/null +++ b/Tests/SentryTests/Integrations/SessionReplay/SentryVideoFrameProcessorTests.swift @@ -0,0 +1,639 @@ +import AVFoundation +import CoreGraphics +import Foundation +@_spi(Private) @testable import Sentry +@_spi(Private) import SentryTestUtils +import XCTest + +#if os(iOS) || os(tvOS) + +class SentryVideoFrameProcessorTests: XCTestCase { + + private class TestSentryPixelBuffer: SentryAppendablePixelBuffer { + var appendInvocations = Invocations<(image: UIImage, presentationTime: CMTime)>() + var appendShouldReturn = true + var appendShouldThrow = false + + func append(image: UIImage, presentationTime: CMTime) -> Bool { + appendInvocations.record((image: image, presentationTime: presentationTime)) + if appendShouldThrow { + return false + } + return appendShouldReturn + } + } + + private class TestAVAssetWriter: AVAssetWriter { + var statusOverride: AVAssetWriter.Status = .writing + var errorOverride: Error? + var cancelWritingCalled = false + var finishWritingCalled = false + var trackedInputs: [AVAssetWriterInput] = [] + + override var status: AVAssetWriter.Status { + return statusOverride + } + + override var error: Error? { + return errorOverride + } + + override func cancelWriting() { + cancelWritingCalled = true + } + + override func finishWriting(completionHandler: @escaping () -> Void) { + finishWritingCalled = true + completionHandler() + } + + override var inputs: [AVAssetWriterInput] { + return trackedInputs + } + + override func add(_ input: AVAssetWriterInput) { + trackedInputs.append(input) + } + } + + // Create a test AVAssetWriter that doesn't execute completion immediately + private class DelayedTestAVAssetWriter: TestAVAssetWriter { + var completionHandler: (() -> Void)? + var shouldExecuteCompletionImmediately = false + + override func finishWriting(completionHandler: @escaping () -> Void) { + finishWritingCalled = true + if shouldExecuteCompletionImmediately { + completionHandler() + } else { + self.completionHandler = completionHandler + } + } + + func executeCompletion() { + completionHandler?() + completionHandler = nil + } + } + + private class TestAVAssetWriterInput: AVAssetWriterInput { + var isReadyForMoreMediaDataOverride = true + var requestMediaDataWhenReadyCalled = false + var requestMediaDataWhenReadyQueue: DispatchQueue? + var requestMediaDataWhenReadyBlock: (() -> Void)? + var markAsFinishedInvocations = Invocations() + + override var isReadyForMoreMediaData: Bool { + return isReadyForMoreMediaDataOverride + } + + override func requestMediaDataWhenReady(on queue: DispatchQueue, using block: @escaping () -> Void) { + requestMediaDataWhenReadyCalled = true + requestMediaDataWhenReadyQueue = queue + requestMediaDataWhenReadyBlock = block + } + + override func markAsFinished() { + markAsFinishedInvocations.record(Void()) + } + } + + private class Fixture { + let videoFrames: [SentryReplayFrame] + let videoWriter: TestAVAssetWriter + let currentPixelBuffer: TestSentryPixelBuffer + let outputFileURL: URL + let videoHeight: CGFloat = 100 + let videoWidth: CGFloat = 200 + let frameRate: Int = 1 + let initialFrameIndex: Int = 0 + let initialImageSize: CGSize = CGSize(width: 200, height: 100) + + init() { + // Create test frames + let testImagePath = FileManager.default.temporaryDirectory.appendingPathComponent("test.png") + + videoFrames = [ + SentryReplayFrame(imagePath: testImagePath.path, time: Date(timeIntervalSinceReferenceDate: 0), screenName: "Screen1"), + SentryReplayFrame(imagePath: testImagePath.path, time: Date(timeIntervalSinceReferenceDate: 1), screenName: "Screen2"), + SentryReplayFrame(imagePath: testImagePath.path, time: Date(timeIntervalSinceReferenceDate: 2), screenName: "Screen3") + ] + + currentPixelBuffer = TestSentryPixelBuffer() + outputFileURL = FileManager.default.temporaryDirectory.appendingPathComponent("test_video.mp4") + videoWriter = try! TestAVAssetWriter(url: outputFileURL, fileType: .mp4) + + createTestImage() + } + + func getSut() -> SentryVideoFrameProcessor { + return SentryVideoFrameProcessor( + videoFrames: videoFrames, + videoWriter: videoWriter, + currentPixelBuffer: currentPixelBuffer, + outputFileURL: outputFileURL, + videoHeight: videoHeight, + videoWidth: videoWidth, + frameRate: frameRate, + initialFrameIndex: initialFrameIndex, + initialImageSize: initialImageSize + ) + } + + func createTestUIImage() -> UIImage { + let size = CGSize(width: 200, height: 100) + let format = UIGraphicsImageRendererFormat() + format.scale = 1.0 // avoid scaling + + let renderer = UIGraphicsImageRenderer(size: size, format: format) + + let image = renderer.image { _ in + } + + return image + } + + @discardableResult + func createTestImage() -> String { + let testImage = createTestUIImage() + let testImagePath = FileManager.default.temporaryDirectory.appendingPathComponent("test.png") + try? testImage.pngData()?.write(to: testImagePath) + return testImagePath.path + } + + func cleanTestImagePath() { + let testImagePath = FileManager.default.temporaryDirectory.appendingPathComponent("test.png") + try? FileManager.default.removeItem(atPath: testImagePath.path) + } + } + + private var fixture: Fixture! + + override func setUp() { + super.setUp() + fixture = Fixture() + } + + override func tearDown() { + super.tearDown() + // Clean up test files + try? FileManager.default.removeItem(at: fixture.outputFileURL) + fixture.cleanTestImagePath() + } + + // MARK: - Initialization Tests + + func testInit_WithValidParameters_ShouldInitializeCorrectly() { + let sut = fixture.getSut() + + XCTAssertEqual(sut.videoFrames.count, 3) + XCTAssertEqual(sut.videoHeight, 100) + XCTAssertEqual(sut.videoWidth, 200) + XCTAssertEqual(sut.frameRate, 1) + XCTAssertEqual(sut.frameIndex, 0) + XCTAssertEqual(sut.lastImageSize, CGSize(width: 200, height: 100)) + XCTAssertEqual(sut.usedFrames.count, 0) + } + + // MARK: - Process Frames Tests + + func testProcessFrames_WhenInputIsReady_ShouldProcessAvailableFrames() { + let sut = fixture.getSut() + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + videoWriterInput.isReadyForMoreMediaDataOverride = true + + sut.processFrames(videoWriterInput: videoWriterInput) { _ in } + + XCTAssertEqual(fixture.currentPixelBuffer.appendInvocations.count, 3) + XCTAssertEqual(sut.frameIndex, 3) + XCTAssertEqual(sut.usedFrames.count, 3) + } + + func testProcessFrames_WhenVideoWriterNotWriting_ShouldCancelWriting() { + let sut = fixture.getSut() + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + fixture.videoWriter.add(videoWriterInput) + fixture.videoWriter.statusOverride = .failed + let completionInvocations = Invocations>() + + sut.processFrames(videoWriterInput: videoWriterInput) { completionInvocations.record($0) } + + XCTAssertTrue(fixture.videoWriter.cancelWritingCalled) + XCTAssertEqual(videoWriterInput.markAsFinishedInvocations.count, 1) + XCTAssertEqual(completionInvocations.count, 1) + + let result = completionInvocations.invocations.first + XCTAssertNotNil(result) + + switch result { + case .failure(let error): + XCTAssertTrue(error is SentryOnDemandReplayError) + default: + XCTFail("Expected failure result") + } + } + + func testProcessFrames_WhenNoMoreFrames_ShouldFinishVideo() { + let sut = fixture.getSut() + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + fixture.videoWriter.add(videoWriterInput) + let completionInvocations = Invocations>() + + // Process all frames + sut.processFrames(videoWriterInput: videoWriterInput) { completionInvocations.record($0) } + + XCTAssertTrue(fixture.videoWriter.finishWritingCalled) + XCTAssertEqual(videoWriterInput.markAsFinishedInvocations.count, 1) + XCTAssertEqual(completionInvocations.count, 1) + } + + func testProcessFrames_WhenImageSizeChanges_ShouldFinishVideo() { + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + fixture.videoWriter.add(videoWriterInput) + let completionInvocations = Invocations>() + let sutWithDifferentSize = SentryVideoFrameProcessor( + videoFrames: fixture.videoFrames, + videoWriter: fixture.videoWriter, + currentPixelBuffer: fixture.currentPixelBuffer, + outputFileURL: fixture.outputFileURL, + videoHeight: fixture.videoHeight, + videoWidth: fixture.videoWidth, + frameRate: fixture.frameRate, + initialFrameIndex: 0, + initialImageSize: CGSize(width: 300, height: 150) // Any other size works + ) + + sutWithDifferentSize.processFrames(videoWriterInput: videoWriterInput) { completionInvocations.record($0) } + + XCTAssertTrue(fixture.videoWriter.finishWritingCalled) + XCTAssertEqual(videoWriterInput.markAsFinishedInvocations.count, 1) + XCTAssertEqual(completionInvocations.count, 1) + } + + func testProcessFrames_WhenPixelBufferAppendFails_ShouldCancelWriting() { + let sut = fixture.getSut() + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + fixture.videoWriter.add(videoWriterInput) + fixture.currentPixelBuffer.appendShouldReturn = false + let completionInvocations = Invocations>() + + // Process all frames + sut.processFrames(videoWriterInput: videoWriterInput) { completionInvocations.record($0) } + + XCTAssertTrue(fixture.videoWriter.cancelWritingCalled) + XCTAssertEqual(videoWriterInput.markAsFinishedInvocations.count, 1) + XCTAssertEqual(completionInvocations.count, 1) + + let result = completionInvocations.invocations.first + XCTAssertNotNil(result) + + switch result { + case .failure(let error): + XCTAssertTrue(error is SentryOnDemandReplayError) + default: + XCTFail("Expected failure result") + } + } + + func testProcessFrames_WhenImageCannotBeLoaded_ShouldSkipFrame() { + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + let completionInvocations = Invocations>() + + // Create frames with non-existent image paths + let nonExistentFrames = [ + SentryReplayFrame(imagePath: "/another/non/existent/path.png", time: Date(), screenName: "Screen2") + ] + + let sutWithNonExistentFrames = SentryVideoFrameProcessor( + videoFrames: nonExistentFrames, + videoWriter: fixture.videoWriter, + currentPixelBuffer: fixture.currentPixelBuffer, + outputFileURL: fixture.outputFileURL, + videoHeight: fixture.videoHeight, + videoWidth: fixture.videoWidth, + frameRate: fixture.frameRate, + initialFrameIndex: 0, + initialImageSize: fixture.initialImageSize + ) + + sutWithNonExistentFrames.processFrames(videoWriterInput: videoWriterInput) { completionInvocations.record($0) } + + // Should still increment frame index even if image can't be loaded + XCTAssertEqual(sutWithNonExistentFrames.frameIndex, 1) + XCTAssertEqual(sutWithNonExistentFrames.usedFrames.count, 0) + } + + // MARK: - Finish Video Tests + + func testFinishVideo_WhenWriterCompleted_ShouldReturnVideoInfo() { + let sut = fixture.getSut() + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + fixture.videoWriter.add(videoWriterInput) + fixture.videoWriter.statusOverride = .completed + let completionInvocations = Invocations>() + + // Create a test video file + let testData = Data("test video data".utf8) + try? testData.write(to: fixture.outputFileURL) + + // Add some used frames + sut.usedFrames = fixture.videoFrames + + sut.finishVideo(frameIndex: 3, onCompletion: { result in + completionInvocations.record(result) + }) + + XCTAssertEqual(videoWriterInput.markAsFinishedInvocations.count, 1) + XCTAssertEqual(completionInvocations.count, 1) + + let result = completionInvocations.invocations.first + XCTAssertNotNil(result) + + switch result { + case .success(let videoResult): + XCTAssertNotNil(videoResult) + XCTAssertEqual(videoResult.finalFrameIndex, 3) + XCTAssertNotNil(videoResult.info) + if let info = videoResult.info { + XCTAssertEqual(info.frameCount, 3) + XCTAssertEqual(info.frameRate, 1) + XCTAssertEqual(info.width, 200) + XCTAssertEqual(info.height, 100) + } + default: + XCTFail("Expected success result") + } + } + + func testFinishVideo_WhenWriterCancelled_ShouldReturnNilVideoInfo() { + let sut = fixture.getSut() + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + fixture.videoWriter.add(videoWriterInput) + fixture.videoWriter.statusOverride = .cancelled + let completionInvocations = Invocations>() + + sut.finishVideo(frameIndex: 2, onCompletion: { result in + completionInvocations.record(result) + }) + + XCTAssertEqual(videoWriterInput.markAsFinishedInvocations.count, 1) + XCTAssertEqual(completionInvocations.count, 1) + + let result = completionInvocations.invocations.first + XCTAssertNotNil(result) + + switch result { + case .success(let videoResult): + XCTAssertNotNil(videoResult) + XCTAssertEqual(videoResult.finalFrameIndex, 2) + XCTAssertNil(videoResult.info) + default: + XCTFail("Expected success result with nil info") + } + } + + func testFinishVideo_WhenWriterFailed_ShouldReturnError() { + let sut = fixture.getSut() + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + fixture.videoWriter.add(videoWriterInput) + fixture.videoWriter.statusOverride = .failed + fixture.videoWriter.errorOverride = SentryOnDemandReplayError.errorRenderingVideo + let completionInvocations = Invocations>() + + sut.finishVideo(frameIndex: 1, onCompletion: { result in + completionInvocations.record(result) + }) + + XCTAssertEqual(videoWriterInput.markAsFinishedInvocations.count, 1) + XCTAssertEqual(completionInvocations.count, 1) + + let result = completionInvocations.invocations.first + XCTAssertNotNil(result) + + switch result { + case .failure(let error): + XCTAssertTrue(error is SentryOnDemandReplayError) + default: + XCTFail("Expected failure result") + } + } + + func testFinishVideo_WhenSelfIsDeallocated_ShouldReturnNilVideoInfo() { + let delayedVideoWriter = try! DelayedTestAVAssetWriter(url: fixture.outputFileURL, fileType: .mp4) + delayedVideoWriter.statusOverride = .completed + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + delayedVideoWriter.add(videoWriterInput) + + // Create a weak reference to track deallocation + weak var weakSut: SentryVideoFrameProcessor? + let completionInvocations = Invocations>() + + // Create the processor in a scope that will be deallocated + autoreleasepool { + let sut = SentryVideoFrameProcessor( + videoFrames: fixture.videoFrames, + videoWriter: delayedVideoWriter, + currentPixelBuffer: fixture.currentPixelBuffer, + outputFileURL: fixture.outputFileURL, + videoHeight: fixture.videoHeight, + videoWidth: fixture.videoWidth, + frameRate: fixture.frameRate, + initialFrameIndex: 0, + initialImageSize: fixture.initialImageSize + ) + weakSut = sut + + // Start finishVideo but don't wait for completion + sut.finishVideo(frameIndex: 5, onCompletion: { result in + completionInvocations.record(result) + }) + + // The sut should be deallocated when this scope ends + } + + // Verify the instance was deallocated + XCTAssertNil(weakSut, "SUT should be deallocated") + + // Now execute the completion handler after deallocation + delayedVideoWriter.executeCompletion() + + // Verify the completion was called with nil video info + XCTAssertEqual(videoWriterInput.markAsFinishedInvocations.count, 1) + XCTAssertEqual(completionInvocations.count, 1) + + let result = completionInvocations.invocations.first + XCTAssertNotNil(result) + + switch result { + case .success(let videoResult): + XCTAssertNotNil(videoResult) + XCTAssertEqual(videoResult.finalFrameIndex, 5) + XCTAssertNil(videoResult.info, "Video info should be nil when self is deallocated") + default: + XCTFail("Expected success result with nil info") + } + } + + func testFinishVideo_WhenOutputFileDoesNotExist_ShouldReturnError() { + let sut = fixture.getSut() + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + fixture.videoWriter.add(videoWriterInput) + fixture.videoWriter.statusOverride = .completed + let completionInvocations = Invocations>() + + // Ensure the output file doesn't exist + try? FileManager.default.removeItem(at: fixture.outputFileURL) + + // Add some used frames + sut.usedFrames = fixture.videoFrames + + sut.finishVideo(frameIndex: 3, onCompletion: { result in + completionInvocations.record(result) + }) + + XCTAssertEqual(videoWriterInput.markAsFinishedInvocations.count, 1) + XCTAssertEqual(completionInvocations.count, 1) + + let result = completionInvocations.invocations.first + XCTAssertNotNil(result) + + switch result { + case .failure(let error): + // The error should be related to file system operations + XCTAssertTrue(error is SentryOnDemandReplayError || error.localizedDescription.contains("file")) + default: + XCTFail("Expected failure result when output file doesn't exist") + } + } + + // MARK: - Get Video Info Tests + + func testGetVideoInfo_WithValidFile_ShouldReturnVideoInfo() throws { + let sut = fixture.getSut() + + // Create a test video file + let testData = Data("test video data".utf8) + try testData.write(to: fixture.outputFileURL) + + // Add used frames + sut.usedFrames = fixture.videoFrames + + let videoInfo = try sut.getVideoInfo( + from: fixture.outputFileURL, + usedFrames: fixture.videoFrames, + videoWidth: 200, + videoHeight: 100 + ) + + XCTAssertEqual(videoInfo.path, fixture.outputFileURL) + XCTAssertEqual(videoInfo.width, 200) + XCTAssertEqual(videoInfo.height, 100) + XCTAssertEqual(videoInfo.frameCount, 3) + XCTAssertEqual(videoInfo.frameRate, 1) + XCTAssertEqual(videoInfo.fileSize, testData.count) + XCTAssertEqual(videoInfo.screens, ["Screen1", "Screen2", "Screen3"]) + } + + func testGetVideoInfo_WithNonExistentFile_ShouldThrowError() { + let sut = fixture.getSut() + + XCTAssertThrowsError(try sut.getVideoInfo( + from: URL(fileURLWithPath: "/non/existent/file.mp4"), + usedFrames: fixture.videoFrames, + videoWidth: 200, + videoHeight: 100 + )) + } + + func testGetVideoInfo_WithEmptyUsedFrames_ShouldThrowError() { + let sut = fixture.getSut() + + // Create a test video file + let testData = Data("test video data".utf8) + try? testData.write(to: fixture.outputFileURL) + + XCTAssertThrowsError(try sut.getVideoInfo( + from: fixture.outputFileURL, + usedFrames: [], + videoWidth: 200, + videoHeight: 100 + )) { error in + XCTAssertTrue(error is SentryOnDemandReplayError) + } + } + + // MARK: - Edge Cases + + func testProcessFrames_WithEmptyFramesArray_ShouldFinishImmediately() { + let completionInvocations = Invocations>() + let sut = SentryVideoFrameProcessor( + videoFrames: [], + videoWriter: fixture.videoWriter, + currentPixelBuffer: fixture.currentPixelBuffer, + outputFileURL: fixture.outputFileURL, + videoHeight: fixture.videoHeight, + videoWidth: fixture.videoWidth, + frameRate: fixture.frameRate, + initialFrameIndex: 0, + initialImageSize: fixture.initialImageSize + ) + + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + fixture.videoWriter.add(videoWriterInput) + sut.processFrames(videoWriterInput: videoWriterInput) { completionInvocations.record($0) } + + XCTAssertTrue(fixture.videoWriter.finishWritingCalled) + XCTAssertEqual(videoWriterInput.markAsFinishedInvocations.count, 1) + XCTAssertEqual(completionInvocations.count, 1) + XCTAssertEqual(sut.frameIndex, 0) + } + + func testProcessFrames_WithLargeFrameIndex_ShouldFinishImmediately() { + let sut = fixture.getSut() + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + fixture.videoWriter.add(videoWriterInput) + let completionInvocations = Invocations>() + + // Set frame index beyond available frames + sut.frameIndex = 10 + + sut.processFrames(videoWriterInput: videoWriterInput) { completionInvocations.record($0) } + + XCTAssertTrue(fixture.videoWriter.finishWritingCalled) + XCTAssertEqual(videoWriterInput.markAsFinishedInvocations.count, 1) + XCTAssertEqual(completionInvocations.count, 1) + XCTAssertEqual(sut.frameIndex, 10) + } + + func testProcessFrames_WithMixedValidAndInvalidFrames_ShouldProcessValidFrames() { + let videoWriterInput = TestAVAssetWriterInput(mediaType: .video, outputSettings: nil) + let completionInvocations = Invocations>() + + // Create mixed frames (valid and invalid) + let mixedFrames = [ + SentryReplayFrame(imagePath: fixture.createTestImage(), time: Date(), screenName: "Valid1"), + SentryReplayFrame(imagePath: "/non/existent/path.png", time: Date(), screenName: "Invalid"), + SentryReplayFrame(imagePath: fixture.createTestImage(), time: Date(), screenName: "Valid2") + ] + + let sutWithMixedFrames = SentryVideoFrameProcessor( + videoFrames: mixedFrames, + videoWriter: fixture.videoWriter, + currentPixelBuffer: fixture.currentPixelBuffer, + outputFileURL: fixture.outputFileURL, + videoHeight: fixture.videoHeight, + videoWidth: fixture.videoWidth, + frameRate: fixture.frameRate, + initialFrameIndex: 0, + initialImageSize: fixture.initialImageSize + ) + + sutWithMixedFrames.processFrames(videoWriterInput: videoWriterInput) { completionInvocations.record($0) } + + // Should process valid frames and skip invalid ones + XCTAssertEqual(sutWithMixedFrames.frameIndex, 3) + XCTAssertEqual(sutWithMixedFrames.usedFrames.count, 2) // Only valid frames + } +} + +#endif // os(iOS) || os(tvOS) diff --git a/Tests/SentryTests/Integrations/UIEvents/SentryUIEventTrackerTests.swift b/Tests/SentryTests/Integrations/UIEvents/SentryUIEventTrackerTests.swift index b33ce9bfceb..75d51ab0a51 100644 --- a/Tests/SentryTests/Integrations/UIEvents/SentryUIEventTrackerTests.swift +++ b/Tests/SentryTests/Integrations/UIEvents/SentryUIEventTrackerTests.swift @@ -40,7 +40,7 @@ class SentryUIEventTrackerTests: XCTestCase { sut = fixture.getSut() sut.start() - SentrySDK.setCurrentHub(fixture.hub) + SentrySDKInternal.setCurrentHub(fixture.hub) } override func tearDown() { diff --git a/Tests/SentryTests/Integrations/ViewHierarchy/SentryViewHierarchyIntegrationTests.swift b/Tests/SentryTests/Integrations/ViewHierarchy/SentryViewHierarchyIntegrationTests.swift index d62a6bbf5c7..d18aa578aa0 100644 --- a/Tests/SentryTests/Integrations/ViewHierarchy/SentryViewHierarchyIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/ViewHierarchy/SentryViewHierarchyIntegrationTests.swift @@ -35,34 +35,38 @@ class SentryViewHierarchyIntegrationTests: XCTestCase { clearTestState() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_attachViewHierarchy() { SentrySDK.start { $0.attachViewHierarchy = false $0.setIntegrations([SentryViewHierarchyIntegration.self]) } - XCTAssertEqual(SentrySDK.currentHub().getClient()?.attachmentProcessors.count, 0) + XCTAssertEqual(SentrySDKInternal.currentHub().getClient()?.attachmentProcessors.count, 0) XCTAssertFalse(sentrycrash_hasSaveViewHierarchyCallback()) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_attachViewHierarchy_enabled() { SentrySDK.start { $0.attachViewHierarchy = true $0.setIntegrations([SentryViewHierarchyIntegration.self]) } - XCTAssertEqual(SentrySDK.currentHub().getClient()?.attachmentProcessors.count, 1) + XCTAssertEqual(SentrySDKInternal.currentHub().getClient()?.attachmentProcessors.count, 1) XCTAssertTrue(sentrycrash_hasSaveViewHierarchyCallback()) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_uninstall() { SentrySDK.start { $0.attachViewHierarchy = true $0.setIntegrations([SentryViewHierarchyIntegration.self]) } SentrySDK.close() - XCTAssertNil(SentrySDK.currentHub().getClient()?.attachmentProcessors) + XCTAssertNil(SentrySDKInternal.currentHub().getClient()?.attachmentProcessors) XCTAssertFalse(sentrycrash_hasSaveViewHierarchyCallback()) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func test_integrationAddFileName() { SentrySDK.start { $0.attachViewHierarchy = true @@ -168,6 +172,7 @@ class SentryViewHierarchyIntegrationTests: XCTestCase { wait(for: [ex], timeout: 1) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testReportAccessibilityIdentifierTrue() { SentrySDK.start { $0.attachViewHierarchy = true @@ -176,6 +181,7 @@ class SentryViewHierarchyIntegrationTests: XCTestCase { XCTAssertTrue(SentryDependencyContainer.sharedInstance().viewHierarchyProvider.reportAccessibilityIdentifier) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testReportAccessibilityIdentifierFalse() { SentrySDK.start { $0.attachViewHierarchy = true diff --git a/Tests/SentryTests/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationAttributesProcessorTests.swift b/Tests/SentryTests/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationAttributesProcessorTests.swift index fa590edf210..8670b181195 100644 --- a/Tests/SentryTests/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationAttributesProcessorTests.swift +++ b/Tests/SentryTests/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationAttributesProcessorTests.swift @@ -3,319 +3,322 @@ import XCTest class SentryWatchdogTerminationAttributesProcessorTests: XCTestCase { - private static let dsn = TestConstants.dsnForTestCase(type: SentryWatchdogTerminationAttributesProcessorTests.self) - - private class Fixture { - let dispatchQueueWrapper: TestSentryDispatchQueueWrapper! - let scopePersistentStore: TestSentryScopePersistentStore! - let fileManager: TestFileManager! - - let context: [String: [String: Any]] = [ - "app": [ - "id": 123, - "name": "TestApp" - ], - "device": [ - "device.class": "iPhone", - "os": "iOS" - ] - ] - let invalidContext: [String: [String: Any]] = [ - "other": [ - "key": Double.infinity - ] - ] - - let user: User = { - let user = User(userId: "test-user-id") - user.email = "test@example.com" - user.username = "testuser" - user.name = "Test User" - user.ipAddress = "192.168.1.1" - user.data = ["custom_key": "custom_value"] - return user - }() - - let invalidUser: User = { - let user = User(userId: "test-user-id") - // Create an invalid user by setting data with non-serializable content - user.data = ["invalid_key": Double.infinity] - return user - }() - - let dist: String = "1.0.0" - - let env: String = "test" - - let tags: [String: String] = [ - "tag1": "value1", - "tag2": "value2", - "environment": "test" - ] - - let traceContext: [String: Any] = [ - "trace_id": "771a43a4192642f0b136d5159a501700", - "span_id": "6c0f0fea4c4c4c4c", - "sampled": "true", - "transaction": "test-transaction" - ] - - let invalidTraceContext: [String: Any] = [ - "trace_id": "771a43a4192642f0b136d5159a501700", - "span_id": "6c0f0fea4c4c4c4c", - "invalid_key": Double.infinity - ] - let level: NSNumber = NSNumber(value: SentryLevel.fatal.rawValue) - let invalidLevel: NSNumber = NSNumber(value: 999) // Invalid level value - - let extras: [String: Any] = [ - "extra_key": "extra_value", - "numeric_key": 42, - "bool_key": true, - "array_key": ["item1", "item2"] - ] - let invalidExtras: [String: Any] = [ - "invalid_key": Double.infinity - ] - - let fingerprint: [String] = ["fingerprint1", "fingerprint2", "fingerprint3"] - - init() throws { - let options = Options() - options.dsn = SentryWatchdogTerminationAttributesProcessorTests.dsn - - self.dispatchQueueWrapper = TestSentryDispatchQueueWrapper() - self.fileManager = try TestFileManager(options: Options()) - self.scopePersistentStore = TestSentryScopePersistentStore(fileManager: fileManager) - } - - func getSut() -> SentryWatchdogTerminationAttributesProcessor { - SentryWatchdogTerminationAttributesProcessor( - withDispatchQueueWrapper: dispatchQueueWrapper, - scopePersistentStore: scopePersistentStore - ) - } - } - - private var fixture: Fixture! - private var sut: SentryWatchdogTerminationAttributesProcessor! - - override func setUpWithError() throws { - fixture = try Fixture() - sut = fixture.getSut() - } - - // MARK: - Context Tests - - func testInit_fileExistsAtActiveFilePath_shouldDeleteFile() throws { - // -- Arrange -- - createPersistedFile(field: .context) - assertPersistedFileExists(field: .context) - - // -- Act -- - let _ = fixture.getSut() - - // -- Assert -- - assertPersistedFileNotExists(field: .context) - } - - func testInit_fileExistsAtContextPath_shouldDeleteFile() throws { - // -- Arrange -- - assertPersistedFileNotExists(field: .context) - - // -- Act -- - let _ = fixture.getSut() - - // -- Assert -- - assertPersistedFileNotExists(field: .context) - } - - func testSetContext_whenContextIsValid_shouldDispatchToQueue() { - // -- Act -- - sut.setContext(fixture.context) - - // -- Assert -- - XCTAssertEqual(fixture.dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) - } - - func testSetContext_whenProcessorIsDeallocatedWhileDispatching_shouldNotCauseRetainCycle() { - // The processor is dispatching the file operation on a background queue. - // This tests checks that the dispatch block is not keeping a strong reference to the - // processor and causes a retain cycle. - - // -- Arrange -- - // Configure the mock to not execute the block and only keep a reference to the block - fixture.dispatchQueueWrapper.dispatchAsyncExecutesBlock = false - - // Define a log mock to assert the execution path - let logOutput = TestLogOutput() - SentrySDKLog.setLogOutput(logOutput) - SentrySDKLog.configureLog(true, diagnosticLevel: .debug) - - // -- Act -- - sut.setContext(fixture.context) - sut = nil - - // Execute the block after the processor is deallocated to have a weak reference - // in the dispatch block - fixture.dispatchQueueWrapper.invokeLastDispatchAsync() - - // -- Assert -- - // This assertion is a best-effort check to see if the block was executed, as there is not other - // mechanism to assert this case - XCTAssertTrue(logOutput.loggedMessages.contains { line in - line.contains("Can not set context, reason: reference to processor is nil") - }) - } - - func testSetContext_whenContextIsNilAndActiveFileExists_shouldDeleteActiveFile() { - // -- Arrange -- - createPersistedFile(field: .context) - assertPersistedFileExists(field: .context) - - // -- Act -- - sut.setContext(nil) - - // -- Assert -- - assertPersistedFileNotExists(field: .context) - } - - func testSetContext_whenContextIsNilAndActiveFileNotExists_shouldNotThrow() { - // -- Arrange -- - assertPersistedFileNotExists(field: .context) - - // -- Act -- - sut.setContext(nil) - - // -- Assert -- - assertPersistedFileNotExists(field: .context) - } - - func testSetContext_whenContextIsInvalidJSON_shouldLogErrorAndNotThrow() { - // -- Arrange -- - // Define a log mock to assert the execution path - let logOutput = TestLogOutput() - SentrySDKLog.setLogOutput(logOutput) - SentrySDKLog.configureLog(true, diagnosticLevel: .debug) - - // -- Act -- - sut.setContext(fixture.invalidContext) - - // -- Assert -- - XCTAssertTrue(logOutput.loggedMessages.contains { line in - line.contains("[error]") && line.contains("Failed to serialize context, reason: ") - }) - } - - func testSetContext_whenContextIsInvalidJSON_shouldNotOverwriteExistingFile() throws { - // -- Arrange -- - let data = Data("Old content".utf8) - - createPersistedFile(field: .context, data: data) - assertPersistedFileExists(field: .context) - - // -- Act -- - sut.setContext(fixture.invalidContext) - - // -- Assert -- - let writtenData = try Data(contentsOf: fixture.scopePersistentStore.currentFileURLFor(field: .context)) - XCTAssertEqual(writtenData, data) - } - - // MARK: - User Tests - - func testSetUser_whenUserIsValid_shouldDispatchToQueue() { - // -- Act -- - sut.setUser(fixture.user) - - // -- Assert -- - XCTAssertEqual(fixture.dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) - } - - func testSetUser_whenProcessorIsDeallocatedWhileDispatching_shouldNotCauseRetainCycle() { - // The processor is dispatching the file operation on a background queue. - // This tests checks that the dispatch block is not keeping a strong reference to the - // processor and causes a retain cycle. - - // -- Arrange -- - // Configure the mock to not execute the block and only keep a reference to the block - fixture.dispatchQueueWrapper.dispatchAsyncExecutesBlock = false - - // Define a log mock to assert the execution path - let logOutput = TestLogOutput() - SentrySDKLog.setLogOutput(logOutput) - SentrySDKLog.configureLog(true, diagnosticLevel: .debug) - - // -- Act -- - sut.setUser(fixture.user) - sut = nil - - // Execute the block after the processor is deallocated to have a weak reference - // in the dispatch block - fixture.dispatchQueueWrapper.invokeLastDispatchAsync() - - // -- Assert -- - // This assertion is a best-effort check to see if the block was executed, as there is not other - // mechanism to assert this case - XCTAssertTrue(logOutput.loggedMessages.contains { line in - line.contains("Can not set user, reason: reference to processor is nil") - }) - } - - func testSetUser_whenUserIsNilAndActiveFileExists_shouldDeleteActiveFile() { - // -- Arrange -- - createPersistedFile(field: .user) - assertPersistedFileExists(field: .user) - - // -- Act -- - sut.setUser(nil) - - // -- Assert -- - assertPersistedFileNotExists(field: .user) - } - - func testSetUser_whenUserIsNilAndActiveFileNotExists_shouldNotThrow() { - // -- Arrange -- - assertPersistedFileNotExists(field: .user) - - // -- Act -- - sut.setUser(nil) - - // -- Assert -- - assertPersistedFileNotExists(field: .user) - } - - func testSetUser_whenUserIsInvalidJSON_shouldLogErrorAndNotThrow() { - // -- Arrange -- - // Define a log mock to assert the execution path - let logOutput = TestLogOutput() - SentrySDKLog.setLogOutput(logOutput) - SentrySDKLog.configureLog(true, diagnosticLevel: .debug) - - // -- Act -- - sut.setUser(fixture.invalidUser) - - // -- Assert -- - XCTAssertTrue(logOutput.loggedMessages.contains { line in - line.contains("[error]") && line.contains("Failed to serialize user, reason: ") - }) - } - - func testSetUser_whenUserIsInvalidJSON_shouldNotOverwriteExistingFile() throws { - // -- Arrange -- - let data = Data("Old content".utf8) - - createPersistedFile(field: .user, data: data) - assertPersistedFileExists(field: .user) - - // -- Act -- - sut.setUser(fixture.invalidUser) - - // -- Assert -- - let writtenData = try Data(contentsOf: fixture.scopePersistentStore.currentFileURLFor(field: .user)) - XCTAssertEqual(writtenData, data) - } - + private static let dsn = TestConstants.dsnForTestCase(type: SentryWatchdogTerminationAttributesProcessorTests.self) + + private class Fixture { + let dateProvider = TestCurrentDateProvider() + let dispatchQueueWrapper = TestSentryDispatchQueueWrapper() + let scopePersistentStore: TestSentryScopePersistentStore! + let fileManager: TestFileManager! + + let context: [String: [String: Any]] = [ + "app": [ + "id": 123, + "name": "TestApp" + ], + "device": [ + "device.class": "iPhone", + "os": "iOS" + ] + ] + let invalidContext: [String: [String: Any]] = [ + "other": [ + "key": Double.infinity + ] + ] + + let user: User = { + let user = User(userId: "test-user-id") + user.email = "test@example.com" + user.username = "testuser" + user.name = "Test User" + user.ipAddress = "192.168.1.1" + user.data = ["custom_key": "custom_value"] + return user + }() + + let invalidUser: User = { + let user = User(userId: "test-user-id") + // Create an invalid user by setting data with non-serializable content + user.data = ["invalid_key": Double.infinity] + return user + }() + + let dist: String = "1.0.0" + + let env: String = "test" + + let tags: [String: String] = [ + "tag1": "value1", + "tag2": "value2", + "environment": "test" + ] + + let traceContext: [String: Any] = [ + "trace_id": "771a43a4192642f0b136d5159a501700", + "span_id": "6c0f0fea4c4c4c4c", + "sampled": "true", + "transaction": "test-transaction" + ] + + let invalidTraceContext: [String: Any] = [ + "trace_id": "771a43a4192642f0b136d5159a501700", + "span_id": "6c0f0fea4c4c4c4c", + "invalid_key": Double.infinity + ] + let level: NSNumber = NSNumber(value: SentryLevel.fatal.rawValue) + let invalidLevel: NSNumber = NSNumber(value: 999) // Invalid level value + + let extras: [String: Any] = [ + "extra_key": "extra_value", + "numeric_key": 42, + "bool_key": true, + "array_key": ["item1", "item2"] + ] + let invalidExtras: [String: Any] = [ + "invalid_key": Double.infinity + ] + + let fingerprint: [String] = ["fingerprint1", "fingerprint2", "fingerprint3"] + + init() throws { + let options = Options() + options.dsn = SentryWatchdogTerminationAttributesProcessorTests.dsn + self.fileManager = try TestFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: dispatchQueueWrapper + ) + self.scopePersistentStore = TestSentryScopePersistentStore(fileManager: fileManager) + } + + func getSut() -> SentryWatchdogTerminationAttributesProcessor { + SentryWatchdogTerminationAttributesProcessor( + withDispatchQueueWrapper: dispatchQueueWrapper, + scopePersistentStore: scopePersistentStore + ) + } + } + + private var fixture: Fixture! + private var sut: SentryWatchdogTerminationAttributesProcessor! + + override func setUpWithError() throws { + fixture = try Fixture() + sut = fixture.getSut() + } + + // MARK: - Context Tests + + func testInit_fileExistsAtActiveFilePath_shouldDeleteFile() throws { + // -- Arrange -- + createPersistedFile(field: .context) + assertPersistedFileExists(field: .context) + + // -- Act -- + let _ = fixture.getSut() + + // -- Assert -- + assertPersistedFileNotExists(field: .context) + } + + func testInit_fileExistsAtContextPath_shouldDeleteFile() throws { + // -- Arrange -- + assertPersistedFileNotExists(field: .context) + + // -- Act -- + let _ = fixture.getSut() + + // -- Assert -- + assertPersistedFileNotExists(field: .context) + } + + func testSetContext_whenContextIsValid_shouldDispatchToQueue() { + // -- Act -- + sut.setContext(fixture.context) + + // -- Assert -- + XCTAssertEqual(fixture.dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) + } + + func testSetContext_whenProcessorIsDeallocatedWhileDispatching_shouldNotCauseRetainCycle() { + // The processor is dispatching the file operation on a background queue. + // This tests checks that the dispatch block is not keeping a strong reference to the + // processor and causes a retain cycle. + + // -- Arrange -- + // Configure the mock to not execute the block and only keep a reference to the block + fixture.dispatchQueueWrapper.dispatchAsyncExecutesBlock = false + + // Define a log mock to assert the execution path + let logOutput = TestLogOutput() + SentrySDKLog.setLogOutput(logOutput) + SentrySDKLog.configureLog(true, diagnosticLevel: .debug) + + // -- Act -- + sut.setContext(fixture.context) + sut = nil + + // Execute the block after the processor is deallocated to have a weak reference + // in the dispatch block + fixture.dispatchQueueWrapper.invokeLastDispatchAsync() + + // -- Assert -- + // This assertion is a best-effort check to see if the block was executed, as there is not other + // mechanism to assert this case + XCTAssertTrue(logOutput.loggedMessages.contains { line in + line.contains("Can not set context, reason: reference to processor is nil") + }) + } + + func testSetContext_whenContextIsNilAndActiveFileExists_shouldDeleteActiveFile() { + // -- Arrange -- + createPersistedFile(field: .context) + assertPersistedFileExists(field: .context) + + // -- Act -- + sut.setContext(nil) + + // -- Assert -- + assertPersistedFileNotExists(field: .context) + } + + func testSetContext_whenContextIsNilAndActiveFileNotExists_shouldNotThrow() { + // -- Arrange -- + assertPersistedFileNotExists(field: .context) + + // -- Act -- + sut.setContext(nil) + + // -- Assert -- + assertPersistedFileNotExists(field: .context) + } + + func testSetContext_whenContextIsInvalidJSON_shouldLogErrorAndNotThrow() { + // -- Arrange -- + // Define a log mock to assert the execution path + let logOutput = TestLogOutput() + SentrySDKLog.setLogOutput(logOutput) + SentrySDKLog.configureLog(true, diagnosticLevel: .debug) + + // -- Act -- + sut.setContext(fixture.invalidContext) + + // -- Assert -- + XCTAssertTrue(logOutput.loggedMessages.contains { line in + line.contains("[error]") && line.contains("Failed to serialize context, reason: ") + }) + } + + func testSetContext_whenContextIsInvalidJSON_shouldNotOverwriteExistingFile() throws { + // -- Arrange -- + let data = Data("Old content".utf8) + + createPersistedFile(field: .context, data: data) + assertPersistedFileExists(field: .context) + + // -- Act -- + sut.setContext(fixture.invalidContext) + + // -- Assert -- + let writtenData = try Data(contentsOf: fixture.scopePersistentStore.currentFileURLFor(field: .context)) + XCTAssertEqual(writtenData, data) + } + + // MARK: - User Tests + + func testSetUser_whenUserIsValid_shouldDispatchToQueue() { + // -- Act -- + sut.setUser(fixture.user) + + // -- Assert -- + XCTAssertEqual(fixture.dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) + } + + func testSetUser_whenProcessorIsDeallocatedWhileDispatching_shouldNotCauseRetainCycle() { + // The processor is dispatching the file operation on a background queue. + // This tests checks that the dispatch block is not keeping a strong reference to the + // processor and causes a retain cycle. + + // -- Arrange -- + // Configure the mock to not execute the block and only keep a reference to the block + fixture.dispatchQueueWrapper.dispatchAsyncExecutesBlock = false + + // Define a log mock to assert the execution path + let logOutput = TestLogOutput() + SentrySDKLog.setLogOutput(logOutput) + SentrySDKLog.configureLog(true, diagnosticLevel: .debug) + + // -- Act -- + sut.setUser(fixture.user) + sut = nil + + // Execute the block after the processor is deallocated to have a weak reference + // in the dispatch block + fixture.dispatchQueueWrapper.invokeLastDispatchAsync() + + // -- Assert -- + // This assertion is a best-effort check to see if the block was executed, as there is not other + // mechanism to assert this case + XCTAssertTrue(logOutput.loggedMessages.contains { line in + line.contains("Can not set user, reason: reference to processor is nil") + }) + } + + func testSetUser_whenUserIsNilAndActiveFileExists_shouldDeleteActiveFile() { + // -- Arrange -- + createPersistedFile(field: .user) + assertPersistedFileExists(field: .user) + + // -- Act -- + sut.setUser(nil) + + // -- Assert -- + assertPersistedFileNotExists(field: .user) + } + + func testSetUser_whenUserIsNilAndActiveFileNotExists_shouldNotThrow() { + // -- Arrange -- + assertPersistedFileNotExists(field: .user) + + // -- Act -- + sut.setUser(nil) + + // -- Assert -- + assertPersistedFileNotExists(field: .user) + } + + func testSetUser_whenUserIsInvalidJSON_shouldLogErrorAndNotThrow() { + // -- Arrange -- + // Define a log mock to assert the execution path + let logOutput = TestLogOutput() + SentrySDKLog.setLogOutput(logOutput) + SentrySDKLog.configureLog(true, diagnosticLevel: .debug) + + // -- Act -- + sut.setUser(fixture.invalidUser) + + // -- Assert -- + XCTAssertTrue(logOutput.loggedMessages.contains { line in + line.contains("[error]") && line.contains("Failed to serialize user, reason: ") + }) + } + + func testSetUser_whenUserIsInvalidJSON_shouldNotOverwriteExistingFile() throws { + // -- Arrange -- + let data = Data("Old content".utf8) + + createPersistedFile(field: .user, data: data) + assertPersistedFileExists(field: .user) + + // -- Act -- + sut.setUser(fixture.invalidUser) + + // -- Assert -- + let writtenData = try Data(contentsOf: fixture.scopePersistentStore.currentFileURLFor(field: .user)) + XCTAssertEqual(writtenData, data) + } + // MARK: - Dist Tests func testSetDist_whenDistIsValid_shouldDispatchToQueue() { @@ -378,7 +381,7 @@ class SentryWatchdogTerminationAttributesProcessorTests: XCTestCase { // -- Assert -- assertPersistedFileNotExists(field: .dist) } - + // MARK: - Environment Tests func testSetEnvironment_whenEnvironmentIsValid_shouldDispatchToQueue() { @@ -505,363 +508,363 @@ class SentryWatchdogTerminationAttributesProcessorTests: XCTestCase { assertPersistedFileNotExists(field: .tags) } - // MARK: - Extras Tests - - func testSetExtras_whenExtrasIsValid_shouldDispatchToQueue() { - // -- Act -- - sut.setExtras(fixture.extras) + // MARK: - Extras Tests + + func testSetExtras_whenExtrasIsValid_shouldDispatchToQueue() { + // -- Act -- + sut.setExtras(fixture.extras) + + // -- Assert -- + XCTAssertEqual(fixture.dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) + } + + func testSetExtras_whenProcessorIsDeallocatedWhileDispatching_shouldNotCauseRetainCycle() { + // The processor is dispatching the file operation on a background queue. + // This tests checks that the dispatch block is not keeping a strong reference to the + // processor and causes a retain cycle. + + // -- Arrange -- + // Configure the mock to not execute the block and only keep a reference to the block + fixture.dispatchQueueWrapper.dispatchAsyncExecutesBlock = false + + // Define a log mock to assert the execution path + let logOutput = TestLogOutput() + SentrySDKLog.setLogOutput(logOutput) + SentrySDKLog.configureLog(true, diagnosticLevel: .debug) + + // -- Act -- + sut.setExtras(fixture.extras) + sut = nil + + // Execute the block after the processor is deallocated to have a weak reference + // in the dispatch block + fixture.dispatchQueueWrapper.invokeLastDispatchAsync() + + // -- Assert -- + // This assertion is a best-effort check to see if the block was executed, as there is not other + // mechanism to assert this case + XCTAssertTrue(logOutput.loggedMessages.contains { line in + line.contains("Can not set extras, reason: reference to processor is nil") + }) + } + + func testSetExtras_whenExtrasIsNilAndActiveFileExists_shouldDeleteActiveFile() { + // -- Arrange -- + createPersistedFile(field: .extras) + assertPersistedFileExists(field: .extras) + + // -- Act -- + sut.setExtras(nil) + + // -- Assert -- + assertPersistedFileNotExists(field: .extras) + } + + func testSetExtras_whenExtrasIsNilAndActiveFileNotExists_shouldNotThrow() { + // -- Arrange -- + assertPersistedFileNotExists(field: .extras) + + // -- Act -- + sut.setExtras(nil) + + // -- Assert -- + assertPersistedFileNotExists(field: .extras) + } + + func testSetExtras_whenExtrasIsInvalidJSON_shouldLogErrorAndNotThrow() { + // -- Arrange -- + // Define a log mock to assert the execution path + let logOutput = TestLogOutput() + SentrySDKLog.setLogOutput(logOutput) + SentrySDKLog.configureLog(true, diagnosticLevel: .debug) + + // -- Act -- + sut.setExtras(fixture.invalidExtras) + + // -- Assert -- + XCTAssertTrue(logOutput.loggedMessages.contains { line in + line.contains("[error]") && line.contains("Failed to serialize extras, reason: ") + }) + } + + func testSetExtras_whenExtrasIsInvalidJSON_shouldNotOverwriteExistingFile() throws { + // -- Arrange -- + let data = Data("Old content".utf8) + + createPersistedFile(field: .extras, data: data) + assertPersistedFileExists(field: .extras) + + // -- Act -- + sut.setExtras(fixture.invalidExtras) + + // -- Assert -- + let writtenData = try Data(contentsOf: fixture.scopePersistentStore.currentFileURLFor(field: .extras)) + XCTAssertEqual(writtenData, data) + } + + func testSetExtras_whenExtrasIsValid_shouldWriteToDisk() { + // -- Act -- + sut.setExtras(fixture.extras) + + // -- Assert -- + fixture.dispatchQueueWrapper.invokeLastDispatchAsync() + assertPersistedFileExists(field: .extras) + } + + // MARK: - Fingerprint Tests + + func testSetFingerprint_whenFingerprintIsValid_shouldDispatchToQueue() { + // -- Act -- + sut.setFingerprint(fixture.fingerprint) + + // -- Assert -- + XCTAssertEqual(fixture.dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) + } + + func testSetFingerprint_whenProcessorIsDeallocatedWhileDispatching_shouldNotCauseRetainCycle() { + // The processor is dispatching the file operation on a background queue. + // This tests checks that the dispatch block is not keeping a strong reference to the + // processor and causes a retain cycle. + + // -- Arrange -- + // Configure the mock to not execute the block and only keep a reference to the block + fixture.dispatchQueueWrapper.dispatchAsyncExecutesBlock = false + + // Define a log mock to assert the execution path + let logOutput = TestLogOutput() + SentrySDKLog.setLogOutput(logOutput) + SentrySDKLog.configureLog(true, diagnosticLevel: .debug) + + // -- Act -- + sut.setFingerprint(fixture.fingerprint) + sut = nil + + // Execute the block after the processor is deallocated to have a weak reference + // in the dispatch block + fixture.dispatchQueueWrapper.invokeLastDispatchAsync() + + // -- Assert -- + // This assertion is a best-effort check to see if the block was executed, as there is not other + // mechanism to assert this case + XCTAssertTrue(logOutput.loggedMessages.contains { line in + line.contains("Can not set fingerprint, reason: reference to processor is nil") + }) + } + + func testSetFingerprint_whenFingerprintIsNilAndActiveFileExists_shouldDeleteActiveFile() { + // -- Arrange -- + createPersistedFile(field: .fingerprint) + assertPersistedFileExists(field: .fingerprint) + + // -- Act -- + sut.setFingerprint(nil) + + // -- Assert -- + assertPersistedFileNotExists(field: .fingerprint) + } + + func testSetFingerprint_whenFingerprintIsNilAndActiveFileNotExists_shouldNotThrow() { + // -- Arrange -- + assertPersistedFileNotExists(field: .fingerprint) + + // -- Act -- + sut.setFingerprint(nil) + + // -- Assert -- + assertPersistedFileNotExists(field: .fingerprint) + } + + func testSetFingerprint_whenFingerprintIsValid_shouldWriteToDisk() { + // -- Act -- + sut.setFingerprint(fixture.fingerprint) + + // -- Assert -- + fixture.dispatchQueueWrapper.invokeLastDispatchAsync() + assertPersistedFileExists(field: .fingerprint) + } + + // MARK: - Clear Tests + + func testClear_whenContextFileExistsNot_shouldNotThrow() { + // -- Arrange -- + // Assert the preconditions + assertPersistedFileNotExists(field: .context) + + // -- Act -- + sut.clear() + + // -- Assert -- + assertPersistedFileNotExists(field: .context) + } + + func testClear_whenContextFileExists_shouldDeleteFileWithoutError() { + // -- Arrange -- + let data = Data("Old content".utf8) + createPersistedFile(field: .context, data: data) + // Assert the preconditions + assertPersistedFileExists(field: .context) + + // -- Act -- + sut.clear() + + // -- Assert -- + assertPersistedFileNotExists(field: .context) + } + + func testClear_whenUserFileExistsNot_shouldNotThrow() { + // -- Arrange -- + // Assert the preconditions + assertPersistedFileNotExists(field: .user) + + // -- Act -- + sut.clear() + + // -- Assert -- + assertPersistedFileNotExists(field: .user) + } + + func testClear_whenUserFileExists_shouldDeleteFileWithoutError() { + // -- Arrange -- + let data = Data("Old content".utf8) + createPersistedFile(field: .user, data: data) + // Assert the preconditions + assertPersistedFileExists(field: .user) + + // -- Act -- + sut.clear() + + // -- Assert -- + assertPersistedFileNotExists(field: .user) + } + + func testClear_whenTagsFileExistsNot_shouldNotThrow() { + // -- Arrange -- + // Assert the preconditions + assertPersistedFileNotExists(field: .tags) + + // -- Act -- + sut.clear() + + // -- Assert -- + assertPersistedFileNotExists(field: .tags) + } + + func testClear_whenTagsFileExists_shouldDeleteFileWithoutError() { + // -- Arrange -- + let data = Data("Old content".utf8) + createPersistedFile(field: .tags, data: data) + // Assert the preconditions + assertPersistedFileExists(field: .tags) - // -- Assert -- - XCTAssertEqual(fixture.dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) - } + // -- Act -- + sut.clear() - func testSetExtras_whenProcessorIsDeallocatedWhileDispatching_shouldNotCauseRetainCycle() { - // The processor is dispatching the file operation on a background queue. - // This tests checks that the dispatch block is not keeping a strong reference to the - // processor and causes a retain cycle. + // -- Assert -- + assertPersistedFileNotExists(field: .tags) + } + + func testClear_whenExtrasFileExistsNot_shouldNotThrow() { + // -- Arrange -- + // Assert the preconditions + assertPersistedFileNotExists(field: .extras) + + // -- Act -- + sut.clear() + + // -- Assert -- + assertPersistedFileNotExists(field: .extras) + } + + func testClear_whenExtrasFileExists_shouldDeleteFileWithoutError() { + // -- Arrange -- + let data = Data("Old content".utf8) + createPersistedFile(field: .extras, data: data) + // Assert the preconditions + assertPersistedFileExists(field: .extras) + + // -- Act -- + sut.clear() + + // -- Assert -- + assertPersistedFileNotExists(field: .extras) + } + + func testClear_whenFingerprintFileExistsNot_shouldNotThrow() { + // -- Arrange -- + // Assert the preconditions + assertPersistedFileNotExists(field: .fingerprint) + + // -- Act -- + sut.clear() + + // -- Assert -- + assertPersistedFileNotExists(field: .fingerprint) + } + + func testClear_whenFingerprintFileExists_shouldDeleteFileWithoutError() { + // -- Arrange -- + let data = Data("Old content".utf8) + createPersistedFile(field: .fingerprint, data: data) + // Assert the preconditions + assertPersistedFileExists(field: .fingerprint) - // -- Arrange -- - // Configure the mock to not execute the block and only keep a reference to the block - fixture.dispatchQueueWrapper.dispatchAsyncExecutesBlock = false + // -- Act -- + sut.clear() - // Define a log mock to assert the execution path - let logOutput = TestLogOutput() - SentrySDKLog.setLogOutput(logOutput) - SentrySDKLog.configureLog(true, diagnosticLevel: .debug) + // -- Assert -- + assertPersistedFileNotExists(field: .fingerprint) + } - // -- Act -- - sut.setExtras(fixture.extras) - sut = nil + func testClear_whenAllFilesExist_shouldDeleteAllFiles() { + // -- Arrange -- + let contextData = Data("Context content".utf8) + let userData = Data("User content".utf8) + let distData = Data("Dist content".utf8) + let envData = Data("Environment content".utf8) + let tagsData = Data("Tags content".utf8) + let extrasData = Data("Extras content".utf8) + let fingerprintData = Data("Fingerprint content".utf8) + + createPersistedFile(field: .context, data: contextData) + createPersistedFile(field: .user, data: userData) + createPersistedFile(field: .dist, data: distData) + createPersistedFile(field: .environment, data: envData) + createPersistedFile(field: .tags, data: tagsData) + createPersistedFile(field: .extras, data: extrasData) + createPersistedFile(field: .fingerprint, data: fingerprintData) + + assertPersistedFileExists(field: .context) + assertPersistedFileExists(field: .user) + assertPersistedFileExists(field: .dist) + assertPersistedFileExists(field: .environment) + assertPersistedFileExists(field: .tags) + assertPersistedFileExists(field: .extras) + assertPersistedFileExists(field: .fingerprint) - // Execute the block after the processor is deallocated to have a weak reference - // in the dispatch block - fixture.dispatchQueueWrapper.invokeLastDispatchAsync() + // -- Act -- + sut.clear() - // -- Assert -- - // This assertion is a best-effort check to see if the block was executed, as there is not other - // mechanism to assert this case - XCTAssertTrue(logOutput.loggedMessages.contains { line in - line.contains("Can not set extras, reason: reference to processor is nil") - }) - } - - func testSetExtras_whenExtrasIsNilAndActiveFileExists_shouldDeleteActiveFile() { - // -- Arrange -- - createPersistedFile(field: .extras) - assertPersistedFileExists(field: .extras) - - // -- Act -- - sut.setExtras(nil) - - // -- Assert -- - assertPersistedFileNotExists(field: .extras) - } - - func testSetExtras_whenExtrasIsNilAndActiveFileNotExists_shouldNotThrow() { - // -- Arrange -- - assertPersistedFileNotExists(field: .extras) - - // -- Act -- - sut.setExtras(nil) - - // -- Assert -- - assertPersistedFileNotExists(field: .extras) - } - - func testSetExtras_whenExtrasIsInvalidJSON_shouldLogErrorAndNotThrow() { - // -- Arrange -- - // Define a log mock to assert the execution path - let logOutput = TestLogOutput() - SentrySDKLog.setLogOutput(logOutput) - SentrySDKLog.configureLog(true, diagnosticLevel: .debug) - - // -- Act -- - sut.setExtras(fixture.invalidExtras) - - // -- Assert -- - XCTAssertTrue(logOutput.loggedMessages.contains { line in - line.contains("[error]") && line.contains("Failed to serialize extras, reason: ") - }) - } - - func testSetExtras_whenExtrasIsInvalidJSON_shouldNotOverwriteExistingFile() throws { - // -- Arrange -- - let data = Data("Old content".utf8) - - createPersistedFile(field: .extras, data: data) - assertPersistedFileExists(field: .extras) - - // -- Act -- - sut.setExtras(fixture.invalidExtras) - - // -- Assert -- - let writtenData = try Data(contentsOf: fixture.scopePersistentStore.currentFileURLFor(field: .extras)) - XCTAssertEqual(writtenData, data) - } - - func testSetExtras_whenExtrasIsValid_shouldWriteToDisk() { - // -- Act -- - sut.setExtras(fixture.extras) - - // -- Assert -- - fixture.dispatchQueueWrapper.invokeLastDispatchAsync() - assertPersistedFileExists(field: .extras) - } - - // MARK: - Fingerprint Tests - - func testSetFingerprint_whenFingerprintIsValid_shouldDispatchToQueue() { - // -- Act -- - sut.setFingerprint(fixture.fingerprint) - - // -- Assert -- - XCTAssertEqual(fixture.dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) - } - - func testSetFingerprint_whenProcessorIsDeallocatedWhileDispatching_shouldNotCauseRetainCycle() { - // The processor is dispatching the file operation on a background queue. - // This tests checks that the dispatch block is not keeping a strong reference to the - // processor and causes a retain cycle. - - // -- Arrange -- - // Configure the mock to not execute the block and only keep a reference to the block - fixture.dispatchQueueWrapper.dispatchAsyncExecutesBlock = false - - // Define a log mock to assert the execution path - let logOutput = TestLogOutput() - SentrySDKLog.setLogOutput(logOutput) - SentrySDKLog.configureLog(true, diagnosticLevel: .debug) - - // -- Act -- - sut.setFingerprint(fixture.fingerprint) - sut = nil - - // Execute the block after the processor is deallocated to have a weak reference - // in the dispatch block - fixture.dispatchQueueWrapper.invokeLastDispatchAsync() - - // -- Assert -- - // This assertion is a best-effort check to see if the block was executed, as there is not other - // mechanism to assert this case - XCTAssertTrue(logOutput.loggedMessages.contains { line in - line.contains("Can not set fingerprint, reason: reference to processor is nil") - }) - } - - func testSetFingerprint_whenFingerprintIsNilAndActiveFileExists_shouldDeleteActiveFile() { - // -- Arrange -- - createPersistedFile(field: .fingerprint) - assertPersistedFileExists(field: .fingerprint) - - // -- Act -- - sut.setFingerprint(nil) - - // -- Assert -- - assertPersistedFileNotExists(field: .fingerprint) - } - - func testSetFingerprint_whenFingerprintIsNilAndActiveFileNotExists_shouldNotThrow() { - // -- Arrange -- - assertPersistedFileNotExists(field: .fingerprint) - - // -- Act -- - sut.setFingerprint(nil) - - // -- Assert -- - assertPersistedFileNotExists(field: .fingerprint) - } - - func testSetFingerprint_whenFingerprintIsValid_shouldWriteToDisk() { - // -- Act -- - sut.setFingerprint(fixture.fingerprint) - - // -- Assert -- - fixture.dispatchQueueWrapper.invokeLastDispatchAsync() - assertPersistedFileExists(field: .fingerprint) - } - - // MARK: - Clear Tests - - func testClear_whenContextFileExistsNot_shouldNotThrow() { - // -- Arrange -- - // Assert the preconditions - assertPersistedFileNotExists(field: .context) - - // -- Act -- - sut.clear() - - // -- Assert -- - assertPersistedFileNotExists(field: .context) - } - - func testClear_whenContextFileExists_shouldDeleteFileWithoutError() { - // -- Arrange -- - let data = Data("Old content".utf8) - createPersistedFile(field: .context, data: data) - // Assert the preconditions - assertPersistedFileExists(field: .context) - - // -- Act -- - sut.clear() - - // -- Assert -- - assertPersistedFileNotExists(field: .context) - } - - func testClear_whenUserFileExistsNot_shouldNotThrow() { - // -- Arrange -- - // Assert the preconditions - assertPersistedFileNotExists(field: .user) - - // -- Act -- - sut.clear() - - // -- Assert -- - assertPersistedFileNotExists(field: .user) - } - - func testClear_whenUserFileExists_shouldDeleteFileWithoutError() { - // -- Arrange -- - let data = Data("Old content".utf8) - createPersistedFile(field: .user, data: data) - // Assert the preconditions - assertPersistedFileExists(field: .user) - - // -- Act -- - sut.clear() - - // -- Assert -- - assertPersistedFileNotExists(field: .user) - } - - func testClear_whenTagsFileExistsNot_shouldNotThrow() { - // -- Arrange -- - // Assert the preconditions - assertPersistedFileNotExists(field: .tags) - - // -- Act -- - sut.clear() - - // -- Assert -- - assertPersistedFileNotExists(field: .tags) - } - - func testClear_whenTagsFileExists_shouldDeleteFileWithoutError() { - // -- Arrange -- - let data = Data("Old content".utf8) - createPersistedFile(field: .tags, data: data) - // Assert the preconditions - assertPersistedFileExists(field: .tags) - - // -- Act -- - sut.clear() - - // -- Assert -- - assertPersistedFileNotExists(field: .tags) - } - - func testClear_whenExtrasFileExistsNot_shouldNotThrow() { - // -- Arrange -- - // Assert the preconditions - assertPersistedFileNotExists(field: .extras) - - // -- Act -- - sut.clear() - - // -- Assert -- - assertPersistedFileNotExists(field: .extras) - } - - func testClear_whenExtrasFileExists_shouldDeleteFileWithoutError() { - // -- Arrange -- - let data = Data("Old content".utf8) - createPersistedFile(field: .extras, data: data) - // Assert the preconditions - assertPersistedFileExists(field: .extras) - - // -- Act -- - sut.clear() - - // -- Assert -- - assertPersistedFileNotExists(field: .extras) - } - - func testClear_whenFingerprintFileExistsNot_shouldNotThrow() { - // -- Arrange -- - // Assert the preconditions - assertPersistedFileNotExists(field: .fingerprint) - - // -- Act -- - sut.clear() - - // -- Assert -- - assertPersistedFileNotExists(field: .fingerprint) - } - - func testClear_whenFingerprintFileExists_shouldDeleteFileWithoutError() { - // -- Arrange -- - let data = Data("Old content".utf8) - createPersistedFile(field: .fingerprint, data: data) - // Assert the preconditions - assertPersistedFileExists(field: .fingerprint) - - // -- Act -- - sut.clear() - - // -- Assert -- - assertPersistedFileNotExists(field: .fingerprint) - } - - func testClear_whenAllFilesExist_shouldDeleteAllFiles() { - // -- Arrange -- - let contextData = Data("Context content".utf8) - let userData = Data("User content".utf8) - let distData = Data("Dist content".utf8) - let envData = Data("Environment content".utf8) - let tagsData = Data("Tags content".utf8) - let extrasData = Data("Extras content".utf8) - let fingerprintData = Data("Fingerprint content".utf8) - - createPersistedFile(field: .context, data: contextData) - createPersistedFile(field: .user, data: userData) - createPersistedFile(field: .dist, data: distData) - createPersistedFile(field: .environment, data: envData) - createPersistedFile(field: .tags, data: tagsData) - createPersistedFile(field: .extras, data: extrasData) - createPersistedFile(field: .fingerprint, data: fingerprintData) - - assertPersistedFileExists(field: .context) - assertPersistedFileExists(field: .user) - assertPersistedFileExists(field: .dist) - assertPersistedFileExists(field: .environment) - assertPersistedFileExists(field: .tags) - assertPersistedFileExists(field: .extras) - assertPersistedFileExists(field: .fingerprint) - - // -- Act -- - sut.clear() - - // -- Assert -- - assertPersistedFileNotExists(field: .context) - assertPersistedFileNotExists(field: .user) - assertPersistedFileNotExists(field: .dist) - assertPersistedFileNotExists(field: .environment) - assertPersistedFileNotExists(field: .tags) - assertPersistedFileNotExists(field: .extras) - assertPersistedFileNotExists(field: .fingerprint) - } - - // MARK: - Assertion Helpers - - fileprivate func createPersistedFile(field: SentryScopeField, data: Data = Data(), file: StaticString = #file, line: UInt = #line) { - FileManager.default.createFile(atPath: fixture.scopePersistentStore.currentFileURLFor(field: field).path, contents: data) - } - - fileprivate func assertPersistedFileExists(field: SentryScopeField, file: StaticString = #file, line: UInt = #line) { - XCTAssertTrue(FileManager.default.fileExists(atPath: fixture.scopePersistentStore.currentFileURLFor(field: field).path), file: file, line: line) - } - - fileprivate func assertPersistedFileNotExists(field: SentryScopeField, file: StaticString = #file, line: UInt = #line) { - XCTAssertFalse(FileManager.default.fileExists(atPath: fixture.scopePersistentStore.currentFileURLFor(field: field).path), file: file, line: line) - } + // -- Assert -- + assertPersistedFileNotExists(field: .context) + assertPersistedFileNotExists(field: .user) + assertPersistedFileNotExists(field: .dist) + assertPersistedFileNotExists(field: .environment) + assertPersistedFileNotExists(field: .tags) + assertPersistedFileNotExists(field: .extras) + assertPersistedFileNotExists(field: .fingerprint) + } + + // MARK: - Assertion Helpers + + fileprivate func createPersistedFile(field: SentryScopeField, data: Data = Data(), file: StaticString = #file, line: UInt = #line) { + FileManager.default.createFile(atPath: fixture.scopePersistentStore.currentFileURLFor(field: field).path, contents: data) + } + + fileprivate func assertPersistedFileExists(field: SentryScopeField, file: StaticString = #file, line: UInt = #line) { + XCTAssertTrue(FileManager.default.fileExists(atPath: fixture.scopePersistentStore.currentFileURLFor(field: field).path), file: file, line: line) + } + + fileprivate func assertPersistedFileNotExists(field: SentryScopeField, file: StaticString = #file, line: UInt = #line) { + XCTAssertFalse(FileManager.default.fileExists(atPath: fixture.scopePersistentStore.currentFileURLFor(field: field).path), file: file, line: line) + } } diff --git a/Tests/SentryTests/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationBreadcrumbProcessorTests.swift b/Tests/SentryTests/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationBreadcrumbProcessorTests.swift index 778c8e04115..43ce36d5855 100644 --- a/Tests/SentryTests/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationBreadcrumbProcessorTests.swift +++ b/Tests/SentryTests/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationBreadcrumbProcessorTests.swift @@ -21,7 +21,11 @@ class SentryWatchdogTerminationBreadcrumbProcessorTests: XCTestCase { options = Options() options.dsn = SentryWatchdogTerminationBreadcrumbProcessorTests.dsn - fileManager = try! SentryFileManager(options: options, dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) + fileManager = try! SentryFileManager( + options: options, + dateProvider: currentDate, + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ) } func getSut() -> SentryWatchdogTerminationBreadcrumbProcessor { diff --git a/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationScopeObserverTests.swift b/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationScopeObserverTests.swift index 4be91c40aef..bddce6bafeb 100644 --- a/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationScopeObserverTests.swift +++ b/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationScopeObserverTests.swift @@ -6,6 +6,9 @@ import XCTest class SentryWatchdogTerminationScopeObserverTests: XCTestCase { private class Fixture { + private let dateProvider = TestCurrentDateProvider() + private let dispatchQueueWrapper = TestSentryDispatchQueueWrapper() + let breadcrumbProcessor: TestSentryWatchdogTerminationBreadcrumbProcessor let attributesProcessor: TestSentryWatchdogTerminationAttributesProcessor @@ -35,14 +38,21 @@ class SentryWatchdogTerminationScopeObserverTests: XCTestCase { let fingerprint: [String] = ["fingerprint1", "fingerprint2", "fingerprint3"] init() throws { - let fileManager = try TestFileManager(options: Options()) + let options = Options() + options.dsn = TestConstants.dsnForTestCase(type: SentryWatchdogTerminationScopeObserverTests.self) + let fileManager = try TestFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: dispatchQueueWrapper + ) + let persistendStore = try XCTUnwrap(SentryScopePersistentStore(fileManager: fileManager)) breadcrumbProcessor = TestSentryWatchdogTerminationBreadcrumbProcessor( maxBreadcrumbs: 10, fileManager: fileManager ) - attributesProcessor = try TestSentryWatchdogTerminationAttributesProcessor( - withDispatchQueueWrapper: TestSentryDispatchQueueWrapper(), - scopePersistentStore: XCTUnwrap(SentryScopePersistentStore(fileManager: fileManager)) + attributesProcessor = TestSentryWatchdogTerminationAttributesProcessor( + withDispatchQueueWrapper: dispatchQueueWrapper, + scopePersistentStore: persistendStore ) } diff --git a/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackerTests.swift b/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackerTests.swift index b49d3ac784e..6f7de502d04 100644 --- a/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackerTests.swift +++ b/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackerTests.swift @@ -34,7 +34,7 @@ class SentryWatchdogTerminationTrackerTests: NotificationCenterTestCase { options.dsn = SentryWatchdogTerminationTrackerTests.dsnAsString options.releaseName = TestData.appState.releaseName - fileManager = try! SentryFileManager(options: options, dispatchQueueWrapper: dispatchQueue) + fileManager = try! SentryFileManager(options: options, dateProvider: currentDate, dispatchQueueWrapper: dispatchQueue) breadcrumbProcessor = SentryWatchdogTerminationBreadcrumbProcessor(maxBreadcrumbs: Int(options.maxBreadcrumbs), fileManager: fileManager) let backgroundQueueWrapper = TestSentryDispatchQueueWrapper() @@ -46,10 +46,10 @@ class SentryWatchdogTerminationTrackerTests: NotificationCenterTestCase { client = TestClient(options: options) - crashWrapper = TestSentryCrashWrapper.sharedInstance() + crashWrapper = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo) let hub = SentryHub(client: client, andScope: nil, andCrashWrapper: crashWrapper, andDispatchQueue: SentryDispatchQueueWrapper()) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) } func getSut() throws -> SentryWatchdogTerminationTracker { @@ -62,7 +62,7 @@ class SentryWatchdogTerminationTrackerTests: NotificationCenterTestCase { crashWrapper: crashWrapper, fileManager: fileManager, dispatchQueueWrapper: self.dispatchQueue, - notificationCenterWrapper: SentryNSNotificationCenterWrapper() + notificationCenterWrapper: NotificationCenter.default ) let logic = SentryWatchdogTerminationLogic( options: options, @@ -91,7 +91,7 @@ class SentryWatchdogTerminationTrackerTests: NotificationCenterTestCase { fixture = try Fixture() sut = try fixture.getSut() - SentrySDK.startInvocations = 1 + SentrySDKInternal.startInvocations = 1 } override func tearDown() { @@ -244,7 +244,7 @@ class SentryWatchdogTerminationTrackerTests: NotificationCenterTestCase { sut.start() goToForeground() - SentrySDK.startInvocations = 2 + SentrySDKInternal.startInvocations = 2 sut.start() assertNoOOMSent() } @@ -414,7 +414,7 @@ class SentryWatchdogTerminationTrackerTests: NotificationCenterTestCase { } func testStop_StopsObserving_NoMoreFileManagerInvocations() throws { - let fileManager = try! TestFileManager(options: Options()) + let fileManager = try! TestFileManager(options: Options(), dateProvider: fixture.currentDate, dispatchQueueWrapper: fixture.dispatchQueue) sut = try fixture.getSut(fileManager: fileManager) sut.start() diff --git a/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackingIntegrationTests.swift b/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackingIntegrationTests.swift index dbffe63cd8b..1f50ca25f91 100644 --- a/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackingIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackingIntegrationTests.swift @@ -12,7 +12,7 @@ class SentryWatchdogTerminationIntegrationTests: XCTestCase { let crashWrapper: TestSentryCrashWrapper let fileManager: SentryFileManager - let processInfoWrapper: TestSentryNSProcessInfoWrapper + let processInfoWrapper: MockSentryProcessInfo let watchdogTerminationAttributesProcessor: TestSentryWatchdogTerminationAttributesProcessor let hub: SentryHub let scope: Scope @@ -32,15 +32,20 @@ class SentryWatchdogTerminationIntegrationTests: XCTestCase { let container = SentryDependencyContainer.sharedInstance() + let dateProvider = TestCurrentDateProvider() let dispatchQueueWrapper = TestSentryDispatchQueueWrapper() - processInfoWrapper = TestSentryNSProcessInfoWrapper() + processInfoWrapper = MockSentryProcessInfo() container.processInfoWrapper = processInfoWrapper - crashWrapper = TestSentryCrashWrapper.sharedInstance() + crashWrapper = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo) container.crashWrapper = crashWrapper - fileManager = try SentryFileManager(options: options) + fileManager = try SentryFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: dispatchQueueWrapper + ) container.fileManager = fileManager let notificationCenterWrapper = TestNSNotificationCenterWrapper() @@ -64,7 +69,7 @@ class SentryWatchdogTerminationIntegrationTests: XCTestCase { let client = TestClient(options: options) scope = Scope() hub = SentryHub(client: client, andScope: scope, andCrashWrapper: crashWrapper, andDispatchQueue: dispatchQueueWrapper) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) } func getSut() -> SentryWatchdogTerminationTrackingIntegration { diff --git a/Tests/SentryTests/Integrations/WatchdogTerminations/TestSentryWatchdogTerminationAttributesProcessorTests.swift b/Tests/SentryTests/Integrations/WatchdogTerminations/TestSentryWatchdogTerminationAttributesProcessorTests.swift index 97f48c91f4f..509da188280 100644 --- a/Tests/SentryTests/Integrations/WatchdogTerminations/TestSentryWatchdogTerminationAttributesProcessorTests.swift +++ b/Tests/SentryTests/Integrations/WatchdogTerminations/TestSentryWatchdogTerminationAttributesProcessorTests.swift @@ -15,16 +15,20 @@ class TestSentryWatchdogTerminationAttributesProcessorTests: XCTestCase { private class Fixture { - let dispatchQueueWrapper: SentryDispatchQueueWrapper + private let dateProvider = TestCurrentDateProvider() + let dispatchQueueWrapper = TestSentryDispatchQueueWrapper() let fileManager: SentryFileManager let scopePersistentStore: SentryScopePersistentStore init() throws { let options = Options() options.dsn = TestSentryWatchdogTerminationAttributesProcessorTests.dsn - fileManager = try TestFileManager(options: options) + fileManager = try TestFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: dispatchQueueWrapper + ) - dispatchQueueWrapper = TestSentryDispatchQueueWrapper() scopePersistentStore = try XCTUnwrap(SentryScopePersistentStore(fileManager: fileManager)) } diff --git a/Tests/SentryTests/Integrations/WatchdogTerminations/TestSentryWatchdogTerminationBreadcrumbProcessorTests.swift b/Tests/SentryTests/Integrations/WatchdogTerminations/TestSentryWatchdogTerminationBreadcrumbProcessorTests.swift index 57f805713b3..38ea1cc4ef2 100644 --- a/Tests/SentryTests/Integrations/WatchdogTerminations/TestSentryWatchdogTerminationBreadcrumbProcessorTests.swift +++ b/Tests/SentryTests/Integrations/WatchdogTerminations/TestSentryWatchdogTerminationBreadcrumbProcessorTests.swift @@ -1,5 +1,5 @@ @testable import Sentry -import SentryTestUtils +@_spi(Private) import SentryTestUtils import XCTest // This test is used to verify the functionality of the mock of TestSentryWatchdogTerminationBreadcrumbProcessor. @@ -19,7 +19,11 @@ class TestSentryWatchdogTerminationBreadcrumbProcessorTests: XCTestCase { init() throws { let options = Options() options.dsn = TestSentryWatchdogTerminationBreadcrumbProcessorTests.dsn - fileManager = try TestFileManager(options: options) + fileManager = try TestFileManager( + options: options, + dateProvider: TestCurrentDateProvider(), + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ) } func getSut() -> TestSentryWatchdogTerminationBreadcrumbProcessor { diff --git a/Tests/SentryTests/Networking/RateLimits/SentryConcurrentRateLimitsDictionaryTests.swift b/Tests/SentryTests/Networking/RateLimits/SentryConcurrentRateLimitsDictionaryTests.swift index 6aa0f75389b..47567cf97dd 100644 --- a/Tests/SentryTests/Networking/RateLimits/SentryConcurrentRateLimitsDictionaryTests.swift +++ b/Tests/SentryTests/Networking/RateLimits/SentryConcurrentRateLimitsDictionaryTests.swift @@ -33,16 +33,18 @@ class SentryConcurrentRateLimitsDictionaryTests: XCTestCase { } func testConcurrentReadWrite() { - let queue1 = DispatchQueue(label: "SentryConcurrentRateLimitsStorageTests1", qos: .background, attributes: [.concurrent, .initiallyInactive]) - let queue2 = DispatchQueue(label: "SentryConcurrentRateLimitsStorageTests2", qos: .utility, attributes: [.concurrent, .initiallyInactive]) + let queue1 = DispatchQueue(label: "SentryConcurrentRateLimitsStorageTests1", attributes: [.concurrent, .initiallyInactive]) + let queue2 = DispatchQueue(label: "SentryConcurrentRateLimitsStorageTests2", attributes: [.concurrent, .initiallyInactive]) - let group = DispatchGroup() + let loopCount = 10 + let expectation = XCTestExpectation(description: "ConcurrentReadWrite") + expectation.expectedFulfillmentCount = loopCount * 2 + expectation.assertForOverFulfill = true - for i in 0...10 { - + for i in 0.. SentryEnvelope { var envelopeItems = [SentryEnvelopeItem]() for _ in 0...2 { diff --git a/Tests/SentryTests/Networking/SentryDataCategoryMapperTests.swift b/Tests/SentryTests/Networking/SentryDataCategoryMapperTests.swift index 1fc9a8999a5..9be42dffdcd 100644 --- a/Tests/SentryTests/Networking/SentryDataCategoryMapperTests.swift +++ b/Tests/SentryTests/Networking/SentryDataCategoryMapperTests.swift @@ -13,6 +13,7 @@ class SentryDataCategoryMapperTests: XCTestCase { XCTAssertEqual(sentryDataCategoryForEnvelopItemType("statsd"), .metricBucket) XCTAssertEqual(sentryDataCategoryForEnvelopItemType("replay_video"), .replay) XCTAssertEqual(sentryDataCategoryForEnvelopItemType("feedback"), .feedback) + XCTAssertEqual(sentryDataCategoryForEnvelopItemType("log"), .logItem) XCTAssertEqual(sentryDataCategoryForEnvelopItemType("unknown item type"), .default) } @@ -30,9 +31,10 @@ class SentryDataCategoryMapperTests: XCTestCase { XCTAssertEqual(sentryDataCategoryForNSUInteger(10), .profileChunk) XCTAssertEqual(sentryDataCategoryForNSUInteger(11), .span) XCTAssertEqual(sentryDataCategoryForNSUInteger(12), .feedback) - XCTAssertEqual(sentryDataCategoryForNSUInteger(13), .unknown) + XCTAssertEqual(sentryDataCategoryForNSUInteger(13), .logItem) + XCTAssertEqual(sentryDataCategoryForNSUInteger(14), .unknown) - XCTAssertEqual(.unknown, sentryDataCategoryForNSUInteger(13), "Failed to map unknown category number to case .unknown") + XCTAssertEqual(.unknown, sentryDataCategoryForNSUInteger(14), "Failed to map unknown category number to case .unknown") } func testMapStringToCategory() { @@ -49,6 +51,7 @@ class SentryDataCategoryMapperTests: XCTestCase { XCTAssertEqual(sentryDataCategoryForString(kSentryDataCategoryNameReplay), .replay) XCTAssertEqual(sentryDataCategoryForString(kSentryDataCategoryNameFeedback), .feedback) XCTAssertEqual(sentryDataCategoryForString(kSentryDataCategoryNameSpan), .span) + XCTAssertEqual(sentryDataCategoryForString(kSentryDataCategoryNameLogItem), .logItem) XCTAssertEqual(sentryDataCategoryForString(kSentryDataCategoryNameUnknown), .unknown) XCTAssertEqual(.unknown, sentryDataCategoryForString("gdfagdfsa"), "Failed to map unknown category name to case .unknown") @@ -68,6 +71,7 @@ class SentryDataCategoryMapperTests: XCTestCase { XCTAssertEqual(nameForSentryDataCategory(.replay), kSentryDataCategoryNameReplay) XCTAssertEqual(nameForSentryDataCategory(.feedback), kSentryDataCategoryNameFeedback) XCTAssertEqual(nameForSentryDataCategory(.span), kSentryDataCategoryNameSpan) + XCTAssertEqual(nameForSentryDataCategory(.logItem), kSentryDataCategoryNameLogItem) XCTAssertEqual(nameForSentryDataCategory(.unknown), kSentryDataCategoryNameUnknown) } } diff --git a/Tests/SentryTests/Networking/SentryDsnTests.m b/Tests/SentryTests/Networking/SentryDsnTests.m index 99f4f4015f1..48fbe1128ba 100644 --- a/Tests/SentryTests/Networking/SentryDsnTests.m +++ b/Tests/SentryTests/Networking/SentryDsnTests.m @@ -1,7 +1,7 @@ #import "SentryDsn.h" #import "SentryError.h" #import "SentryMeta.h" -#import "SentryOptions+HybridSDKs.h" +#import "SentryOptionsInternal.h" #import "SentrySwift.h" #import @@ -14,7 +14,7 @@ @implementation SentryDsnTests - (void)testMissingUsernamePassword { NSError *error = nil; - SentryOptions *options = [[SentryOptions alloc] initWithDict:@{ @"dsn" : @"https://sentry.io" } + SentryOptions *options = [SentryOptionsInternal initWithDict:@{ @"dsn" : @"https://sentry.io" } didFailWithError:&error]; XCTAssertEqual(kSentryErrorInvalidDsnError, error.code); XCTAssertNil(options); @@ -23,7 +23,7 @@ - (void)testMissingUsernamePassword - (void)testMissingScheme { NSError *error = nil; - SentryOptions *options = [[SentryOptions alloc] initWithDict:@{ @"dsn" : @"https://sentry.io" } + SentryOptions *options = [SentryOptionsInternal initWithDict:@{ @"dsn" : @"https://sentry.io" } didFailWithError:&error]; XCTAssertEqual(kSentryErrorInvalidDsnError, error.code); XCTAssertNil(options); @@ -32,7 +32,7 @@ - (void)testMissingScheme - (void)testMissingHost { NSError *error = nil; - SentryOptions *options = [[SentryOptions alloc] initWithDict:@{ @"dsn" : @"http:///1" } + SentryOptions *options = [SentryOptionsInternal initWithDict:@{ @"dsn" : @"http:///1" } didFailWithError:&error]; XCTAssertEqual(kSentryErrorInvalidDsnError, error.code); XCTAssertNil(options); @@ -41,7 +41,7 @@ - (void)testMissingHost - (void)testUnsupportedProtocol { NSError *error = nil; - SentryOptions *options = [[SentryOptions alloc] initWithDict:@{ @"dsn" : @"ftp://sentry.io/1" } + SentryOptions *options = [SentryOptionsInternal initWithDict:@{ @"dsn" : @"ftp://sentry.io/1" } didFailWithError:&error]; XCTAssertEqual(kSentryErrorInvalidDsnError, error.code); XCTAssertNil(options); diff --git a/Tests/SentryTests/Networking/SentryHttpDateParserTests.swift b/Tests/SentryTests/Networking/SentryHttpDateParserTests.swift index 88ba12a9755..f6fbf05fdc2 100644 --- a/Tests/SentryTests/Networking/SentryHttpDateParserTests.swift +++ b/Tests/SentryTests/Networking/SentryHttpDateParserTests.swift @@ -22,29 +22,36 @@ class SentryHttpDateParserTests: XCTestCase { } func testWithMultipleWorkItemsInParallel() { - let queue1 = DispatchQueue(label: "SentryHttpDateParserTests1", qos: .utility, attributes: [.concurrent, .initiallyInactive]) - let queue2 = DispatchQueue(label: "SentryHttpDateParserTests2", qos: .utility, attributes: [.concurrent, .initiallyInactive]) + let queue1 = DispatchQueue(label: "SentryHttpDateParserTests1", attributes: [.concurrent, .initiallyInactive]) + let queue2 = DispatchQueue(label: "SentryHttpDateParserTests2", attributes: [.concurrent, .initiallyInactive]) - let group = DispatchGroup() - for i in 0...1_000 { - startWorkItemTest(i: i, queue: queue1, group: group) - startWorkItemTest(i: i, queue: queue2, group: group) + let loopCount = 1_000 + let expectation = XCTestExpectation(description: "WithMultipleWorkItemsInParallel") + expectation.expectedFulfillmentCount = loopCount * 2 + expectation.assertForOverFulfill = true + + for i in 0.. (SentryHttpTransport, TestRequestManager, SentryFileManager, SentryDispatchQueueWrapper) { + let options = Options() + options.debug = true + options.dsn = TestConstants.dsnAsString(username: "SentryHttpTransportFlushIntegrationTests.\(testName)") + + let currentDate = SentryDefaultCurrentDateProvider() + let dispatchQueueWrapper = SentryDispatchQueueWrapper() + + let fileManager = try SentryFileManager( + options: options, + dateProvider: currentDate, + dispatchQueueWrapper: dispatchQueueWrapper + ) + fileManager.deleteAllEnvelopes() + + let requestManager = TestRequestManager(session: URLSession(configuration: URLSessionConfiguration.ephemeral)) + requestManager.returnResponse(response: HTTPURLResponse()) + + let rateLimits = DefaultRateLimits(retryAfterHeaderParser: RetryAfterHeaderParser(httpDateParser: HttpDateParser(), currentDateProvider: currentDate), andRateLimitParser: RateLimitParser(currentDateProvider: currentDate), currentDateProvider: currentDate) + + return (SentryHttpTransport( + dsn: try XCTUnwrap(options.parsedDsn), + sendClientReports: options.sendClientReports, + cachedEnvelopeSendDelay: 0.0, + dateProvider: SentryDefaultCurrentDateProvider(), + fileManager: fileManager, + requestManager: requestManager, + requestBuilder: TestNSURLRequestBuilder(), + rateLimits: rateLimits, + envelopeRateLimit: EnvelopeRateLimit(rateLimits: rateLimits), + dispatchQueueWrapper: dispatchQueueWrapper + ), requestManager, fileManager, dispatchQueueWrapper) + } + + private func waitForEnvelopeToBeStored(_ dispatchQueueWrapper: SentryDispatchQueueWrapper) { + // Wait until the dispath queue drains to confirm the envelope is stored + let expectation = XCTestExpectation(description: "Envelope sent") + dispatchQueueWrapper.dispatchAsync { + expectation.fulfill() + } + wait(for: [expectation], timeout: 10.0) + } +} diff --git a/Tests/SentryTests/Networking/SentryHttpTransportTests.swift b/Tests/SentryTests/Networking/SentryHttpTransportTests.swift index a245c0c1b1a..8d3f46875f2 100644 --- a/Tests/SentryTests/Networking/SentryHttpTransportTests.swift +++ b/Tests/SentryTests/Networking/SentryHttpTransportTests.swift @@ -51,6 +51,7 @@ class SentryHttpTransportTests: XCTestCase { let queue = DispatchQueue(label: "SentryHttpTransportTests", qos: .userInitiated, attributes: [.concurrent, .initiallyInactive]) + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") init() { SentryDependencyContainer.sharedInstance().reachability = reachability @@ -81,22 +82,22 @@ class SentryHttpTransportTests: XCTestCase { options = Options() options.dsn = SentryHttpTransportTests.dsnAsString - fileManager = try! TestFileManager(options: options) + fileManager = try! TestFileManager(options: options, dateProvider: currentDateProvider, dispatchQueueWrapper: dispatchQueueWrapper) requestManager = TestRequestManager(session: URLSession(configuration: URLSessionConfiguration.ephemeral)) let currentDate = TestCurrentDateProvider() rateLimits = DefaultRateLimits(retryAfterHeaderParser: RetryAfterHeaderParser(httpDateParser: HttpDateParser(), currentDateProvider: currentDate), andRateLimitParser: RateLimitParser(currentDateProvider: currentDate), currentDateProvider: currentDate) - let beforeSendTransaction = SentryDiscardedEvent(reason: .beforeSend, category: .transaction, quantity: 2) - let sampleRateTransaction = SentryDiscardedEvent(reason: .sampleRate, category: .transaction, quantity: 1) - let rateLimitBackoffError = SentryDiscardedEvent(reason: .rateLimitBackoff, category: .error, quantity: 1) + let beforeSendTransaction = SentryDiscardedEvent(reason: nameForSentryDiscardReason(.beforeSend), category: nameForSentryDataCategory(.transaction), quantity: 2) + let sampleRateTransaction = SentryDiscardedEvent(reason: nameForSentryDiscardReason(.sampleRate), category: nameForSentryDataCategory(.transaction), quantity: 1) + let rateLimitBackoffError = SentryDiscardedEvent(reason: nameForSentryDiscardReason(.rateLimitBackoff), category: nameForSentryDataCategory(.error), quantity: 1) clientReport = SentryClientReport(discardedEvents: [ beforeSendTransaction, sampleRateTransaction, rateLimitBackoffError - ]) + ], dateProvider: SentryDependencyContainer.sharedInstance().dateProvider) let clientReportEnvelopeItems = [ SentryEnvelopeItem(event: event), @@ -108,6 +109,7 @@ class SentryHttpTransportTests: XCTestCase { clientReportRequest = buildRequest(clientReportEnvelope) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func getTransactionEnvelope() -> SentryEnvelope { let tracer = SentryTracer(transactionContext: TransactionContext(name: "SomeTransaction", operation: "SomeOperation"), hub: nil) @@ -136,9 +138,10 @@ class SentryHttpTransportTests: XCTestCase { func getSut( fileManager: SentryFileManager? = nil, dispatchQueueWrapper: SentryDispatchQueueWrapper? = nil - ) -> SentryHttpTransport { + ) throws -> SentryHttpTransport { return SentryHttpTransport( - options: options, + dsn: try XCTUnwrap(options.parsedDsn), + sendClientReports: options.sendClientReports, cachedEnvelopeSendDelay: 0.0, dateProvider: currentDateProvider, fileManager: fileManager ?? self.fileManager, @@ -163,13 +166,14 @@ class SentryHttpTransportTests: XCTestCase { private var fixture: Fixture! private var sut: SentryHttpTransport! - override func setUp() { + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + override func setUpWithError() throws { super.setUp() fixture = Fixture() fixture.fileManager.deleteAllEnvelopes() fixture.requestManager.returnResponse(response: HTTPURLResponse()) - sut = fixture.getSut() + sut = try fixture.getSut() } override func tearDown() { @@ -179,14 +183,14 @@ class SentryHttpTransportTests: XCTestCase { clearTestState() } - func testInitSendsCachedEnvelopes() { + func testInitSendsCachedEnvelopes() throws { givenNoInternetConnection() sendEventAsync() assertEnvelopesStored(envelopeCount: 1) waitForAllRequests() givenOkResponse() - let sut = fixture.getSut() + let sut = try fixture.getSut() XCTAssertNotNil(sut) waitForAllRequests() @@ -198,29 +202,31 @@ class SentryHttpTransportTests: XCTestCase { sendEvent() assertRequestsSent(requestCount: 1) - assertEventIsSentAsEnvelope() + try assertEventIsSentAsEnvelope() assertEnvelopesStored(envelopeCount: 0) } - func testSendEventWhenSessionRateLimitActive() { - fixture.rateLimits.update(TestResponseFactory.createRateLimitResponse(headerValue: "1:\(SentryEnvelopeItemTypeSession):key")) + func testSendEventWhenSessionRateLimitActive() throws { + fixture.rateLimits.update(TestResponseFactory.createRateLimitResponse(headerValue: "1:\(SentryEnvelopeItemTypes.session):key")) sendEvent() - assertEventIsSentAsEnvelope() + try assertEventIsSentAsEnvelope() assertEnvelopesStored(envelopeCount: 0) } - func testSendEventWithSession_SentInOneEnvelope() { + @available(iOS 16.0, *) + func testSendEventWithSession_SentInOneEnvelope() throws { sut.send(envelope: fixture.eventWithSessionEnvelope) waitForAllRequests() assertRequestsSent(requestCount: 1) assertEnvelopesStored(envelopeCount: 0) - assertEventAndSessionAreSentInOneEnvelope() + try assertEventAndSessionAreSentInOneEnvelope() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSendEventWithFaultyNSUrlRequest() { let envelope = SentryEnvelope(event: TestConstants.eventWithSerializationError) sut.send(envelope: envelope) @@ -245,6 +251,7 @@ class SentryHttpTransportTests: XCTestCase { try EnvelopeUtils.assertEnvelope(expected: expectedEnvelope, actual: actualEnvelope) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSendEventWithSession_RateLimitForEventIsActive_OnlySessionSent() throws { givenRateLimitResponse(forCategory: "error") sendEvent() @@ -256,8 +263,8 @@ class SentryHttpTransportTests: XCTestCase { assertEnvelopesStored(envelopeCount: 0) // Envelope with only session and client report is sent - let discardedError = SentryDiscardedEvent(reason: .rateLimitBackoff, category: .error, quantity: 1) - let clientReport = SentryClientReport(discardedEvents: [discardedError]) + let discardedError = SentryDiscardedEvent(reason: nameForSentryDiscardReason(.rateLimitBackoff), category: nameForSentryDataCategory(.error), quantity: 1) + let clientReport = SentryClientReport(discardedEvents: [discardedError], dateProvider: SentryDependencyContainer.sharedInstance().dateProvider) let envelopeItems = [ SentryEnvelopeItem(session: fixture.session), SentryEnvelopeItem(clientReport: clientReport) @@ -275,6 +282,7 @@ class SentryHttpTransportTests: XCTestCase { try EnvelopeUtils.assertEnvelope(expected: expectedEnvelope, actual: actualEnvelope) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSendAllCachedEvents() { givenNoInternetConnection() sendEvent() @@ -286,6 +294,7 @@ class SentryHttpTransportTests: XCTestCase { assertEnvelopesStored(envelopeCount: 0) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSendAllCachedEnvelopes() { givenNoInternetConnection() let envelope = SentryEnvelope(session: SentrySession(releaseName: "1.9.0", distinctId: "some-id")) @@ -299,6 +308,7 @@ class SentryHttpTransportTests: XCTestCase { assertEnvelopesStored(envelopeCount: 0) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSendCachedButNotReady() { givenNoInternetConnection() sendEnvelope() @@ -380,7 +390,7 @@ class SentryHttpTransportTests: XCTestCase { func testSendEventWithRateLimitResponse() { fixture.requestManager.nextError = NSError(domain: "something", code: 12) - let response = givenRateLimitResponse(forCategory: SentryEnvelopeItemTypeSession) + let response = givenRateLimitResponse(forCategory: SentryEnvelopeItemTypes.session) sendEvent() @@ -391,7 +401,7 @@ class SentryHttpTransportTests: XCTestCase { func testSendEventWithMetricBucketRateLimitResponse() { fixture.requestManager.nextError = NSError(domain: "something", code: 12) - let response = givenRateLimitResponse(forCategory: SentryEnvelopeItemTypeSession) + let response = givenRateLimitResponse(forCategory: SentryEnvelopeItemTypes.session) sendEvent() @@ -399,6 +409,7 @@ class SentryHttpTransportTests: XCTestCase { assertClientReportStoredInMemory() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSendEnvelopeWithRetryAfterResponse() { let response = givenRetryAfterResponse() @@ -407,8 +418,9 @@ class SentryHttpTransportTests: XCTestCase { assertRateLimitUpdated(response: response) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSendEnvelopeWithRateLimitResponse() { - let response = givenRateLimitResponse(forCategory: SentryEnvelopeItemTypeSession) + let response = givenRateLimitResponse(forCategory: SentryEnvelopeItemTypes.session) sendEnvelope() @@ -436,12 +448,14 @@ class SentryHttpTransportTests: XCTestCase { assertRequestsSent(requestCount: 3) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSendOneEnvelope() { sendEnvelope() assertRequestsSent(requestCount: 1) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testActiveRateLimitForAllEnvelopeItems() { givenRateLimitResponse(forCategory: "error") sendEvent() @@ -462,6 +476,7 @@ class SentryHttpTransportTests: XCTestCase { assertEnvelopesStored(envelopeCount: 0) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testActiveRateLimitForAllCachedEnvelopeItems() { givenNoInternetConnection() sendEnvelope() @@ -478,6 +493,7 @@ class SentryHttpTransportTests: XCTestCase { XCTAssertEqual(fixture.dispatchQueueWrapper.dispatchAfterInvocations.first?.interval, 0.0) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testActiveRateLimitForSomeCachedEnvelopeItems() throws { givenNoInternetConnection() sendEvent() @@ -496,12 +512,17 @@ class SentryHttpTransportTests: XCTestCase { let sessionRequest = try! SentryURLRequestFactory.envelopeRequest(with: SentryHttpTransportTests.dsn(), data: sessionData) if fixture.requestManager.requests.invocations.count > 3 { - XCTAssertEqual(sessionRequest.httpBody, try XCTUnwrap(fixture.requestManager.requests.invocations.element(at: 3)).httpBody, "Envelope with only session item should be sent.") + let unzippedBody = try XCTUnwrap(sentry_unzippedData(XCTUnwrap(sessionRequest.httpBody))) + let requestUnzippedBody = try XCTUnwrap(sentry_unzippedData(XCTUnwrap(XCTUnwrap(fixture.requestManager.requests.invocations.element(at: 3)).httpBody))) + let actualEnvelope = try XCTUnwrap(SentrySerialization.envelope(with: unzippedBody)) + let expectedEnvelope = try XCTUnwrap(SentrySerialization.envelope(with: requestUnzippedBody)) + try EnvelopeUtils.assertEnvelope(expected: expectedEnvelope, actual: actualEnvelope) } else { XCTFail("Expected a fourth invocation") } } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testAllCachedEnvelopesCantDeserializeEnvelope() throws { let path = try XCTUnwrap(fixture.fileManager.store(TestConstants.envelope)) let faultyEnvelope = Data([0x70, 0xa3, 0x10, 0x45]) @@ -514,10 +535,10 @@ class SentryHttpTransportTests: XCTestCase { } func testFailureToStoreEvenlopeEventStillSendsRequest() throws { - let fileManger = try TestFileManager(options: fixture.options) + let fileManger = try TestFileManager(options: fixture.options, dateProvider: fixture.currentDateProvider, dispatchQueueWrapper: fixture.dispatchQueueWrapper) fileManger.storeEnvelopePathNil = true // Failure to store envelope returns nil path - let sut = fixture.getSut(fileManager: fileManger) - + let sut = try fixture.getSut(fileManager: fileManger) + sut.send(envelope: fixture.eventEnvelope) XCTAssertEqual(fileManger.storeEnvelopeInvocations.count, 1) @@ -533,35 +554,35 @@ class SentryHttpTransportTests: XCTestCase { fixture.requestManager.waitForAllRequests() XCTAssertEqual(3, fixture.requestManager.requests.count) - XCTAssertEqual(fixture.eventWithAttachmentRequest.httpBody, try XCTUnwrap(fixture.requestManager.requests.invocations.element(at: 1)).httpBody, "Cached envelope was not sent first.") + try compareEnvelopes(fixture.eventWithAttachmentRequest.httpBody, try XCTUnwrap(fixture.requestManager.requests.invocations.element(at: 1)).httpBody, message: "Cached envelope was not sent first.") if fixture.requestManager.requests.invocations.count > 2 { - XCTAssertEqual(fixture.sessionRequest.httpBody, try XCTUnwrap(fixture.requestManager.requests.invocations.element(at: 2)).httpBody, "Cached envelope was not sent first.") + try compareEnvelopes(fixture.sessionRequest.httpBody, try XCTUnwrap(fixture.requestManager.requests.invocations.element(at: 2)).httpBody, message: "Cached envelope was not sent first.") } else { XCTFail("Expected a third invocation") } } - func testRecordLostEvent_SendingEvent_AttachesClientReport() { + func testRecordLostEvent_SendingEvent_AttachesClientReport() throws { givenRecordedLostEvents() sendEvent() let actualEventRequest = fixture.requestManager.requests.last - XCTAssertEqual(fixture.clientReportRequest.httpBody, actualEventRequest?.httpBody, "Client report not sent.") + try compareEnvelopes(fixture.clientReportRequest.httpBody, actualEventRequest?.httpBody, message: "Client report not sent.") } - func testRecordLostEvent_SendingEvent_ClearsLostEvents() { + func testRecordLostEvent_SendingEvent_ClearsLostEvents() throws { givenRecordedLostEvents() sendEvent() // Second envelope item doesn't contain client reports sendEvent() - assertEventIsSentAsEnvelope() + try assertEventIsSentAsEnvelope() } - func testRecordLostEvent_NoInternet_StoredWithEnvelope() { + func testRecordLostEvent_NoInternet_StoredWithEnvelope() throws { givenNoInternetConnection() givenRecordedLostEvents() @@ -570,12 +591,13 @@ class SentryHttpTransportTests: XCTestCase { sendEvent() let actualEventRequest = fixture.requestManager.requests.first - XCTAssertEqual(fixture.clientReportRequest.httpBody, actualEventRequest?.httpBody, "Client report not sent.") + try compareEnvelopes(fixture.clientReportRequest.httpBody, actualEventRequest?.httpBody, message: "Client report not sent.") } - func testEventRateLimited_RecordsLostEvent() { - let rateLimitBackoffError = SentryDiscardedEvent(reason: .rateLimitBackoff, category: .error, quantity: 1) - let clientReport = SentryClientReport(discardedEvents: [rateLimitBackoffError]) + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + func testEventRateLimited_RecordsLostEvent() throws { + let rateLimitBackoffError = SentryDiscardedEvent(reason: nameForSentryDiscardReason(.rateLimitBackoff), category: nameForSentryDataCategory(.error), quantity: 1) + let clientReport = SentryClientReport(discardedEvents: [rateLimitBackoffError], dateProvider: SentryDependencyContainer.sharedInstance().dateProvider) let clientReportEnvelopeItems = [ fixture.attachmentEnvelopeItem, @@ -590,15 +612,17 @@ class SentryHttpTransportTests: XCTestCase { sendEvent() let actualEventRequest = fixture.requestManager.requests.last - XCTAssertEqual(clientReportRequest.httpBody, actualEventRequest?.httpBody, "Client report not sent.") + try compareEnvelopes(clientReportRequest.httpBody, actualEventRequest?.httpBody, message: "Client report not sent.") } - func testTransactionRateLimited_RecordsLostSpans() { + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + func testTransactionRateLimited_RecordsLostSpans() throws { let clientReport = SentryClientReport( discardedEvents: [ - SentryDiscardedEvent(reason: .rateLimitBackoff, category: .transaction, quantity: 1), - SentryDiscardedEvent(reason: .rateLimitBackoff, category: .span, quantity: 4) - ] + SentryDiscardedEvent(reason: nameForSentryDiscardReason(.rateLimitBackoff), category: nameForSentryDataCategory(.transaction), quantity: 1), + SentryDiscardedEvent(reason: nameForSentryDiscardReason(.rateLimitBackoff), category: nameForSentryDataCategory(.span), quantity: 4) + ], + dateProvider: SentryDependencyContainer.sharedInstance().dateProvider ) let clientReportEnvelopeItems = [ @@ -621,7 +645,7 @@ class SentryHttpTransportTests: XCTestCase { waitForAllRequests() let actualEventRequest = fixture.requestManager.requests.last - XCTAssertEqual(clientReportRequest.httpBody, actualEventRequest?.httpBody, "Client report not sent.") + try compareEnvelopes(clientReportRequest.httpBody, actualEventRequest?.httpBody, message: "Client report not sent.") } func testCacheFull_RecordsLostEvent() { @@ -642,6 +666,7 @@ class SentryHttpTransportTests: XCTestCase { XCTAssertEqual(1, attachment?.quantity) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCacheFull_RecordsLostSpans() { givenNoInternetConnection() for _ in 0...fixture.options.maxCacheItems { @@ -667,22 +692,25 @@ class SentryHttpTransportTests: XCTestCase { let queue = fixture.queue - let group = DispatchGroup() - for _ in 0...20 { - group.enter() + let loopCount = 21 + + let expectation = XCTestExpectation(description: "Send envelopes concurrently") + expectation.expectedFulfillmentCount = loopCount + + for _ in 0.. SentryDiscardReason { + switch reason { + case kSentryDiscardReasonNameBeforeSend: + return .beforeSend + case kSentryDiscardReasonNameEventProcessor: + return .eventProcessor + case kSentryDiscardReasonNameSampleRate: + return .sampleRate + case kSentryDiscardReasonNameNetworkError: + return .networkError + case kSentryDiscardReasonNameQueueOverflow: + return .queueOverflow + case kSentryDiscardReasonNameCacheOverflow: + return .cacheOverflow + case kSentryDiscardReasonNameRateLimitBackoff: + return .rateLimitBackoff + case kSentryDiscardReasonNameInsufficientData: + return .insufficientData + default: + fatalError("Unsupported reason: \(reason)") + } + } + private func waitForAllRequests() { fixture.requestManager.waitForAllRequests() } @@ -1075,15 +1036,18 @@ class SentryHttpTransportTests: XCTestCase { sut.send(envelope: fixture.eventEnvelope) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") private func sendTransaction() { sendTransactionAsync() waitForAllRequests() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") private func sendTransactionAsync() { sut.send(envelope: fixture.getTransactionEnvelope()) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") private func sendEnvelope(envelope: SentryEnvelope = TestConstants.envelope) { sut.send(envelope: envelope) waitForAllRequests() @@ -1103,14 +1067,15 @@ class SentryHttpTransportTests: XCTestCase { XCTAssertEqual(requestCount, fixture.requestManager.requests.count) } - private func assertEventIsSentAsEnvelope() { + private func assertEventIsSentAsEnvelope() throws { let actualEventRequest = fixture.requestManager.requests.last - XCTAssertEqual(fixture.eventWithAttachmentRequest.httpBody, actualEventRequest?.httpBody, "Event was not sent as envelope.") + try compareEnvelopes(fixture.eventWithAttachmentRequest.httpBody, actualEventRequest?.httpBody, message: "Event was not sent as envelope.") } - private func assertEventAndSessionAreSentInOneEnvelope() { + @available(iOS 16.0, *) + private func assertEventAndSessionAreSentInOneEnvelope() throws { let actualEventRequest = fixture.requestManager.requests.last - XCTAssertEqual(fixture.eventWithSessionRequest.httpBody, actualEventRequest?.httpBody, "Request for event with session is faulty.") + try compareEnvelopes(fixture.eventWithSessionRequest.httpBody, actualEventRequest?.httpBody, message: "Request for event with session is faulty.") } private func assertEnvelopesStored(envelopeCount: Int) { diff --git a/Tests/SentryTests/Networking/SentryNSURLRequestBuilderTests.swift b/Tests/SentryTests/Networking/SentryNSURLRequestBuilderTests.swift index 18f351918b1..734c724c915 100644 --- a/Tests/SentryTests/Networking/SentryNSURLRequestBuilderTests.swift +++ b/Tests/SentryTests/Networking/SentryNSURLRequestBuilderTests.swift @@ -1,9 +1,10 @@ -@testable import Sentry +@_spi(Private) @testable import Sentry import SentryTestUtils import XCTest class SentryNSURLRequestBuilderTests: XCTestCase { + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCreateEnvelopeRequestWithDsn() throws { let sut = getSut() @@ -14,6 +15,7 @@ class SentryNSURLRequestBuilderTests: XCTestCase { XCTAssertNotNil(request) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCreateEnvelopeRequestWithUrl() throws { let sut = getSut() @@ -56,6 +58,7 @@ class SentryNSURLRequestBuilderTests: XCTestCase { return try XCTUnwrap(URL(string: "sentry.io/test")) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") private func givenEnvelope() -> SentryEnvelope { return SentryEnvelope( id: SentryId(), @@ -69,7 +72,8 @@ class SentryNSURLRequestBuilderTests: XCTestCase { version: "8.0.0", integrations: [], features: [], - packages: [] + packages: [], + settings: SentrySDKSettings(dict: [:]) ) let headerWithInvalidJSON = SentryEnvelopeHeader( id: nil, diff --git a/Tests/SentryTests/Networking/SentrySpotlightTransportTests.swift b/Tests/SentryTests/Networking/SentrySpotlightTransportTests.swift index 340dba4c0a1..b744cfe84dd 100644 --- a/Tests/SentryTests/Networking/SentrySpotlightTransportTests.swift +++ b/Tests/SentryTests/Networking/SentrySpotlightTransportTests.swift @@ -5,7 +5,7 @@ import XCTest final class SentrySpotlightTransportTests: XCTestCase { private var options: Options! - private var requestManager: TestRequestManager! + private var requestManager: SyncTestRequestManager! private var requestBuilder: TestNSURLRequestBuilder! override func setUp() { @@ -14,8 +14,8 @@ final class SentrySpotlightTransportTests: XCTestCase { options = Options() options.enableSpotlight = true - requestManager = TestRequestManager(session: URLSession(configuration: URLSessionConfiguration.ephemeral)) - + requestManager = SyncTestRequestManager(session: URLSession(configuration: URLSessionConfiguration.ephemeral)) + requestBuilder = TestNSURLRequestBuilder() } @@ -27,6 +27,7 @@ final class SentrySpotlightTransportTests: XCTestCase { return SentrySpotlightTransport(options: options, requestManager: requestManager, requestBuilder: requestBuilder, dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") private func givenEventEnvelope(withAttachment: Bool = false) throws -> SentryEnvelope { let event = TestData.event @@ -42,13 +43,15 @@ final class SentrySpotlightTransportTests: XCTestCase { return SentryEnvelope(id: event.eventId, items: envelopeItems) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") private func givenTransactionEnvelope() throws -> SentryEnvelope { let transaction = Transaction(level: .debug) - transaction.type = SentryEnvelopeItemTypeTransaction + transaction.type = SentryEnvelopeItemTypes.transaction return SentryEnvelope(id: transaction.eventId, items: [SentryEnvelopeItem(event: transaction)]) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testShouldSendEventEnvelope() throws { let eventEnvelope = try givenEventEnvelope() let sut = givenSut() @@ -61,9 +64,10 @@ final class SentrySpotlightTransportTests: XCTestCase { XCTAssertEqual(request.url?.absoluteString, options.spotlightUrl) let expectedData = try getSerializedGzippedData(envelope: eventEnvelope) - XCTAssertEqual(request.httpBody, expectedData) + try compareEnvelopes(request.httpBody, expectedData, message: "Envelopes should be equal") } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testShouldSendTransactionEnvelope() throws { let transactionEnvelope = try givenTransactionEnvelope() let sut = givenSut() @@ -76,9 +80,10 @@ final class SentrySpotlightTransportTests: XCTestCase { XCTAssertEqual(request.url?.absoluteString, options.spotlightUrl) let expectedData = try getSerializedGzippedData(envelope: transactionEnvelope) - XCTAssertEqual(request.httpBody, expectedData) + try compareEnvelopes(request.httpBody, expectedData, message: "Envelopes should be equal") } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testShouldRemoveAttachmentsFromEventEnvelope() throws { let eventEnvelope = try givenEventEnvelope(withAttachment: true) let sut = givenSut() @@ -99,39 +104,40 @@ final class SentrySpotlightTransportTests: XCTestCase { XCTAssert((expectedDataCountLower...expectedDataCountUpper).contains(try XCTUnwrap(request.httpBody?.count))) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testShouldNotSendEnvelope_WhenMalformedURL() throws { let eventEnvelope = try givenEventEnvelope() requestBuilder.shouldFailWithError = true let sut = givenSut(spotlightUrl: TestData.malformedURLString) sut.send(envelope: eventEnvelope) - - requestManager.waitForAllRequests() + XCTAssertEqual(self.requestManager.requests.count, 0) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testShouldNotSendEnvelope_WhenRequestError() throws { let eventEnvelope = try givenEventEnvelope() requestBuilder.shouldFailWithError = true let sut = givenSut() sut.send(envelope: eventEnvelope) - - requestManager.waitForAllRequests() + XCTAssertEqual(self.requestManager.requests.count, 0) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testShouldNotSendEnvelope_WhenRequestNil() throws { let eventEnvelope = try givenEventEnvelope() requestBuilder.shouldFailReturningNil = true let sut = givenSut() sut.send(envelope: eventEnvelope) - - requestManager.waitForAllRequests() + XCTAssertEqual(self.requestManager.requests.count, 0) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testShouldLogError_WhenRequestManagerCompletesWithError() throws { let logOutput = TestLogOutput() SentrySDKLog.setLogOutput(logOutput) @@ -143,8 +149,6 @@ final class SentrySpotlightTransportTests: XCTestCase { sut.send(envelope: eventEnvelope) - requestManager.waitForAllRequests() - let logMessages = logOutput.loggedMessages.filter { $0.contains("[Sentry] [error]") && $0.contains("Error while performing request") @@ -157,5 +161,26 @@ final class SentrySpotlightTransportTests: XCTestCase { let expectedData = try XCTUnwrap(SentrySerialization.data(with: envelope)) as NSData return try SentryNSDataUtils.sentry_gzipped(with: expectedData as Data, compressionLevel: -1) } +} + +/// The SentrySpotlightTransport has simple logic and doesn't require the TestRequestManager using dispatch queues to validate its logic. +/// This simplifies the tests by removing DispatchQueues and makes them more deterministic. +private class SyncTestRequestManager: NSObject, RequestManager { + + var nextError: NSError? + public var isReady: Bool + var requests = Invocations() + + public required init(session: URLSession) { + self.isReady = true + } + + public func add( _ request: URLRequest, completionHandler: SentryRequestOperationFinished? = nil) { + requests.record(request) + + if let handler = completionHandler { + handler(nil, self.nextError) + } + } } diff --git a/Tests/SentryTests/Networking/SentryTransportAdapterTests.swift b/Tests/SentryTests/Networking/SentryTransportAdapterTests.swift index 5e4a95677ad..fd9a584bde3 100644 --- a/Tests/SentryTests/Networking/SentryTransportAdapterTests.swift +++ b/Tests/SentryTests/Networking/SentryTransportAdapterTests.swift @@ -1,4 +1,4 @@ -import Sentry +@_spi(Private) @testable import Sentry @_spi(Private) import SentryTestUtils import XCTest @@ -34,6 +34,7 @@ class SentryTransportAdapterTests: XCTestCase { clearTestState() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSendEventWithSession_SendsCorrectEnvelope() throws { let session = SentrySession(releaseName: "1.0.1", distinctId: "some-id") let event = TestData.event @@ -48,6 +49,7 @@ class SentryTransportAdapterTests: XCTestCase { try assertSentEnvelope(expected: expectedEnvelope) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSendFaultyAttachment_FaultyAttachmentGetsDropped() throws { let event = TestData.event sut.send(event: event, traceContext: nil, attachments: [fixture.faultyAttachment, fixture.attachment]) @@ -70,6 +72,7 @@ class SentryTransportAdapterTests: XCTestCase { try assertSentEnvelope(expected: expectedEnvelope) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testStoreEvent_StoresCorrectEnvelope() throws { let event = TestData.event sut.store(event, traceContext: nil) @@ -114,11 +117,11 @@ enum EnvelopeUtils { XCTAssertTrue(containsHeader, "Envelope doesn't contain item with type:\(expectedHeader.type).") - let jsonExpected = try? JSONSerialization.jsonObject(with: expectedItem.data) as? NSDictionary + let jsonExpected = try? JSONSerialization.jsonObject(with: XCTUnwrap(expectedItem.data)) as? NSDictionary let containsData = actual.items.contains { actualItem in // JSON cannot compare the raw Data because the keys are not guaranteed to be in the same order. if let jsonExpected { - if let jsonActual = try? JSONSerialization.jsonObject(with: actualItem.data) as? NSDictionary { + if let jsonActual = try? JSONSerialization.jsonObject(with: XCTUnwrap(actualItem.data)) as? NSDictionary { return jsonExpected == jsonActual } return false diff --git a/Tests/SentryTests/Networking/SentryTransportFactoryTests.swift b/Tests/SentryTests/Networking/SentryTransportFactoryTests.swift index ec0d3ac0f6f..19fe9f14f1d 100644 --- a/Tests/SentryTests/Networking/SentryTransportFactoryTests.swift +++ b/Tests/SentryTests/Networking/SentryTransportFactoryTests.swift @@ -3,10 +3,11 @@ import Sentry import XCTest class SentryTransportFactoryTests: XCTestCase { - private static let dsnAsString = TestConstants.dsnAsString(username: "SentryTransportFactoryTests") func testIntegration_UrlSessionDelegate_PassedToRequestManager() throws { + // -- Arrange -- + let dateProvider = TestCurrentDateProvider() let urlSessionDelegateSpy = UrlSessionDelegateSpy() let expect = expectation(description: "UrlSession Delegate of Options called in RequestManager") @@ -18,10 +19,16 @@ class SentryTransportFactoryTests: XCTestCase { options.dsn = SentryTransportFactoryTests.dsnAsString options.urlSessionDelegate = urlSessionDelegateSpy - let fileManager = try! SentryFileManager(options: options, dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) + let fileManager = try! SentryFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ) + + // -- Act -- let transports = TransportInitializer.initTransports( options, - dateProvider: SentryDependencyContainer.sharedInstance().dateProvider, + dateProvider: dateProvider, sentryFileManager: fileManager, rateLimits: rateLimiting() ) @@ -32,11 +39,14 @@ class SentryTransportFactoryTests: XCTestCase { let request = URLRequest(url: imgUrl) requestManager.add(request) { _, _ in /* We don't care about the result */ } + + // -- Assert -- wait(for: [expect], timeout: 10) } func testShouldReturnTransports_WhenURLSessionPassed() throws { - + // -- Arrange -- + let dateProvider = TestCurrentDateProvider() let urlSessionDelegateSpy = UrlSessionDelegateSpy() let expect = expectation(description: "UrlSession Delegate of Options called in RequestManager") @@ -46,12 +56,19 @@ class SentryTransportFactoryTests: XCTestCase { } let options = Options() + options.dsn = SentryTransportFactoryTests.dsnAsString options.urlSession = sessionConfiguration - let fileManager = try! SentryFileManager(options: options, dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) + let fileManager = try! SentryFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ) + + // -- Act -- let transports = TransportInitializer.initTransports( options, - dateProvider: SentryDependencyContainer.sharedInstance().dateProvider, + dateProvider: dateProvider, sentryFileManager: fileManager, rateLimits: rateLimiting() ) @@ -63,29 +80,95 @@ class SentryTransportFactoryTests: XCTestCase { let request = URLRequest(url: imgUrl) requestManager.add(request) { _, _ in /* We don't care about the result */ } + + // -- Assert -- wait(for: [expect], timeout: 10) } func testShouldReturnTwoTransports_WhenSpotlightEnabled() throws { + // -- Arrange -- + let dateProvider = TestCurrentDateProvider() + let options = Options() + options.dsn = SentryTransportFactoryTests.dsnAsString options.enableSpotlight = true + + // -- Act -- let transports = TransportInitializer.initTransports( options, - dateProvider: SentryDependencyContainer.sharedInstance().dateProvider, - sentryFileManager: try SentryFileManager(options: options), + dateProvider: dateProvider, + sentryFileManager: try SentryFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ), rateLimits: rateLimiting() ) - + + // -- Assert -- + XCTAssertEqual(transports.count, 2) XCTAssert(transports.contains { $0.isKind(of: SentrySpotlightTransport.self) }) - XCTAssert(transports.contains { $0.isKind(of: SentryHttpTransport.self) }) } + func testInitTransports_whenOptionsParsedDsnNilAndSpotlightDisabled_shouldReturnEmptyTransports() throws { + // -- Arrange -- + let dateProvider = TestCurrentDateProvider() + + let options = Options() + options.dsn = nil + options.enableSpotlight = false + + // -- Act -- + let transports = TransportInitializer.initTransports( + options, + dateProvider: dateProvider, + sentryFileManager: try SentryFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ), + rateLimits: rateLimiting() + ) + + // -- Assert -- + XCTAssertEqual(transports.count, 0) + } + + func testInitTransports_whenOptionsParsedDsnNilAndSpotlightEnabled_shouldReturnSpotlightTransport() throws { + // -- Arrange -- + let dateProvider = TestCurrentDateProvider() + + let options = Options() + options.dsn = nil + options.enableSpotlight = true + + // -- Act -- + let transports = TransportInitializer.initTransports( + options, + dateProvider: dateProvider, + sentryFileManager: try SentryFileManager( + options: options, + dateProvider: dateProvider, + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ), + rateLimits: rateLimiting() + ) + + // -- Assert -- + XCTAssertEqual(transports.count, 1) + XCTAssert(transports.contains { + $0.isKind(of: SentrySpotlightTransport.self) + }) + } + + // MARK: - Helpers + private func rateLimiting() -> RateLimits { let dateProvider = TestCurrentDateProvider() let retryAfterHeaderParser = RetryAfterHeaderParser(httpDateParser: HttpDateParser(), currentDateProvider: dateProvider) @@ -93,5 +176,4 @@ class SentryTransportFactoryTests: XCTestCase { return DefaultRateLimits(retryAfterHeaderParser: retryAfterHeaderParser, andRateLimitParser: rateLimitParser, currentDateProvider: dateProvider) } - } diff --git a/Tests/SentryTests/Networking/SentryTransportInitializerTests.swift b/Tests/SentryTests/Networking/SentryTransportInitializerTests.swift index ad111b6f19f..684c155271e 100644 --- a/Tests/SentryTests/Networking/SentryTransportInitializerTests.swift +++ b/Tests/SentryTests/Networking/SentryTransportInitializerTests.swift @@ -14,13 +14,17 @@ class SentryTransportInitializerTests: XCTestCase { super.setUp() let options = Options() options.dsn = SentryTransportInitializerTests.dsnAsString - fileManager = try! SentryFileManager(options: options, dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) + fileManager = try! SentryFileManager( + options: options, + dateProvider: TestCurrentDateProvider(), + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ) dateProvider = TestCurrentDateProvider() rateLimits = SentryDependencyContainer.sharedInstance().rateLimits } func testDefault() throws { - let options = try Options(dict: ["dsn": SentryTransportInitializerTests.dsnAsString]) + let options = try SentryOptionsInternal.initWithDict(["dsn": SentryTransportInitializerTests.dsnAsString]) let result = TransportInitializer.initTransports( options, diff --git a/Tests/SentryTests/Networking/TestRequestManager.swift b/Tests/SentryTests/Networking/TestRequestManager.swift index db8654a636a..d7b42a2caf2 100644 --- a/Tests/SentryTests/Networking/TestRequestManager.swift +++ b/Tests/SentryTests/Networking/TestRequestManager.swift @@ -1,6 +1,10 @@ import Foundation import SentryTestUtils +// We should replace the use of DispatchGroup in tests with XCTestExpectation. +// This is a workaround to enable the swiftlint rule to avoid adding new occurrences +// of DispatchGroup in tests. +// swiftlint:disable avoid_dispatch_groups_in_tests public class TestRequestManager: NSObject, RequestManager { private var nextResponse: () -> HTTPURLResponse? = { return nil } @@ -9,7 +13,7 @@ public class TestRequestManager: NSObject, RequestManager { var requests = Invocations() - private let queue = DispatchQueue(label: "TestRequestManager", qos: .background, attributes: []) + private let queue = DispatchQueue(label: "TestRequestManager") private let group = DispatchGroup() public required init(session: URLSession) { @@ -40,8 +44,8 @@ public class TestRequestManager: NSObject, RequestManager { }) } - public func waitForAllRequests() { - group.waitWithTimeout() + public func waitForAllRequests(timeout: Double = 100) { + group.waitWithTimeout(timeout: timeout) } func returnResponse(response: HTTPURLResponse?) { @@ -53,3 +57,5 @@ public class TestRequestManager: NSObject, RequestManager { } } + +// swiftlint:enable avoid_dispatch_groups_in_tests diff --git a/Tests/SentryTests/Persistence/SentryScopePersistentStoreTests.swift b/Tests/SentryTests/Persistence/SentryScopePersistentStoreTests.swift index 88c8c9d0485..946497e2b49 100644 --- a/Tests/SentryTests/Persistence/SentryScopePersistentStoreTests.swift +++ b/Tests/SentryTests/Persistence/SentryScopePersistentStoreTests.swift @@ -6,12 +6,15 @@ class SentryScopePersistentStoreTests: XCTestCase { private static let dsn = TestConstants.dsnForTestCase(type: SentryScopePersistentStore.self) private class Fixture { + private let dateProvider = TestCurrentDateProvider() + private let dispatchQueueWrapper = TestSentryDispatchQueueWrapper() + let fileManager: TestFileManager init() throws { let options = Options() options.dsn = SentryScopePersistentStoreTests.dsn - fileManager = try TestFileManager(options: options) + fileManager = try TestFileManager(options: options, dateProvider: dateProvider, dispatchQueueWrapper: dispatchQueueWrapper) } func getSut() throws -> SentryScopePersistentStore { diff --git a/Tests/SentryTests/Protocol/SentryAppState+Equality.h b/Tests/SentryTests/Protocol/SentryAppState+Equality.h index 304482db3bb..55ca95500b6 100644 --- a/Tests/SentryTests/Protocol/SentryAppState+Equality.h +++ b/Tests/SentryTests/Protocol/SentryAppState+Equality.h @@ -1,4 +1,4 @@ -#import "SentryAppState.h" +#import "SentrySwift.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Tests/SentryTests/Protocol/SentryClientReportTests.swift b/Tests/SentryTests/Protocol/SentryClientReportTests.swift index 6398bb90618..18ee5e48f11 100644 --- a/Tests/SentryTests/Protocol/SentryClientReportTests.swift +++ b/Tests/SentryTests/Protocol/SentryClientReportTests.swift @@ -13,11 +13,11 @@ class SentryClientReportTests: XCTestCase { func testSerialize() throws { SentryDependencyContainer.sharedInstance().dateProvider = TestCurrentDateProvider() - let event1 = SentryDiscardedEvent(reason: .sampleRate, category: .transaction, quantity: 2) - let event2 = SentryDiscardedEvent(reason: .beforeSend, category: .transaction, quantity: 3) - let event3 = SentryDiscardedEvent(reason: .rateLimitBackoff, category: .error, quantity: 1) + let event1 = SentryDiscardedEvent(reason: nameForSentryDiscardReason(.sampleRate), category: nameForSentryDataCategory(.transaction), quantity: 2) + let event2 = SentryDiscardedEvent(reason: nameForSentryDiscardReason(.beforeSend), category: nameForSentryDataCategory(.transaction), quantity: 3) + let event3 = SentryDiscardedEvent(reason: nameForSentryDiscardReason(.rateLimitBackoff), category: nameForSentryDataCategory(.error), quantity: 1) - let report = SentryClientReport(discardedEvents: [event1, event2, event3]) + let report = SentryClientReport(discardedEvents: [event1, event2, event3], dateProvider: SentryDependencyContainer.sharedInstance().dateProvider) let actual = report.serialize() diff --git a/Tests/SentryTests/Protocol/SentryDiscardedEventTests.swift b/Tests/SentryTests/Protocol/SentryDiscardedEventTests.swift index c0dfe5932ac..c35e7414674 100644 --- a/Tests/SentryTests/Protocol/SentryDiscardedEventTests.swift +++ b/Tests/SentryTests/Protocol/SentryDiscardedEventTests.swift @@ -1,9 +1,10 @@ +@_spi(Private) import Sentry import XCTest class SentryDiscardedEventTests: XCTestCase { func testSerialize() { - let discardedEvent = SentryDiscardedEvent(reason: SentryDiscardReason.sampleRate, category: SentryDataCategory.transaction, quantity: 2) + let discardedEvent = SentryDiscardedEvent(reason: nameForSentryDiscardReason(.sampleRate), category: nameForSentryDataCategory(.transaction), quantity: 2) let actual = discardedEvent.serialize() diff --git a/Tests/SentryTests/Protocol/SentryEnvelopeTests.swift b/Tests/SentryTests/Protocol/SentryEnvelopeTests.swift index a3b551be9fa..c22faff8f38 100644 --- a/Tests/SentryTests/Protocol/SentryEnvelopeTests.swift +++ b/Tests/SentryTests/Protocol/SentryEnvelopeTests.swift @@ -62,8 +62,15 @@ class SentryEnvelopeTests: XCTestCase { clearTestState() } - private let defaultSdkInfo = SentrySdkInfo(name: SentryMeta.sdkName, version: SentryMeta.versionString, integrations: [], features: [], packages: []) + private let defaultSdkSettings = SentrySDKSettings(dict: [:]) + private lazy var defaultSdkInfo = SentrySdkInfo(name: SentryMeta.sdkName, + version: SentryMeta.versionString, + integrations: [], + features: [], + packages: [], + settings: defaultSdkSettings) + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSentryEnvelopeFromEvent() throws { let event = Event() @@ -76,9 +83,10 @@ class SentryEnvelopeTests: XCTestCase { let json = try! JSONSerialization.data(withJSONObject: event.serialize(), options: JSONSerialization.WritingOptions(rawValue: 0)) - assertJsonIsEqual(actual: json, expected: try XCTUnwrap(envelope.items.first).data) + assertJsonIsEqual(actual: json, expected: try XCTUnwrap(XCTUnwrap(envelope.items.first).data)) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSentryEnvelopeWithExplicitInitMessages() { let attachment = "{}" let data = attachment.data(using: .utf8)! @@ -98,6 +106,7 @@ class SentryEnvelopeTests: XCTestCase { XCTAssertEqual(data, try XCTUnwrap(envelope.items.first).data) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSentryEnvelopeWithExplicitInitMessagesMultipleItems() { var items: [SentryEnvelopeItem] = [] let itemCount = 3 @@ -123,6 +132,7 @@ class SentryEnvelopeTests: XCTestCase { } } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testInitSentryEnvelopeHeader_DefaultSdkInfoIsSet() { XCTAssertEqual(defaultSdkInfo, SentryEnvelopeHeader(id: nil).sdkInfo) } @@ -134,6 +144,7 @@ class SentryEnvelopeTests: XCTestCase { XCTAssertNil(allNil.traceContext) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testInitSentryEnvelopeHeader_IdAndTraceStateNil() { let allNil = SentryEnvelopeHeader(id: nil, traceContext: nil) XCTAssertNil(allNil.eventId) @@ -143,13 +154,14 @@ class SentryEnvelopeTests: XCTestCase { func testInitSentryEnvelopeHeader_SetIdAndSdkInfo() { let eventId = SentryId() - let sdkInfo = SentrySdkInfo(name: "sdk", version: "1.2.3-alpha.0", integrations: [], features: [], packages: []) + let sdkInfo = SentrySdkInfo(name: "sdk", version: "1.2.3-alpha.0", integrations: [], features: [], packages: [], settings: SentrySDKSettings(dict: [:])) let envelopeHeader = SentryEnvelopeHeader(id: eventId, sdkInfo: sdkInfo, traceContext: nil) XCTAssertEqual(eventId, envelopeHeader.eventId) XCTAssertEqual(sdkInfo, envelopeHeader.sdkInfo) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testInitSentryEnvelopeHeader_SetIdAndTraceState() { let eventId = SentryId() let traceContext = TraceContext(trace: SentryId(), publicKey: "publicKey", releaseName: "releaseName", environment: "environment", transaction: "transaction", userSegment: nil, sampleRate: nil, sampled: nil, replayId: nil) @@ -159,12 +171,14 @@ class SentryEnvelopeTests: XCTestCase { XCTAssertEqual(traceContext, envelopeHeader.traceContext) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testInitSentryEnvelopeWithSession_DefaultSdkInfoIsSet() { let envelope = SentryEnvelope(session: SentrySession(releaseName: "1.1.1", distinctId: "some-id")) XCTAssertEqual(defaultSdkInfo, envelope.header.sdkInfo) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testInitWithEvent() throws { let event = fixture.event let envelope = SentryEnvelope(event: event) @@ -178,6 +192,7 @@ class SentryEnvelopeTests: XCTestCase { XCTAssertEqual(expected, actual) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testInitWithEvent_SerializationFails_SendsEventWithSerializationFailure() { let event = fixture.eventWithContinousSerializationFailure let envelope = SentryEnvelope(event: event) @@ -233,6 +248,7 @@ class SentryEnvelopeTests: XCTestCase { XCTAssertEqual(attachment.contentType, envelopeItem.header.contentType) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testEmptyHeader() { let sut = SentryEnvelopeHeader.empty() XCTAssertNil(sut.eventId) @@ -319,7 +335,32 @@ class SentryEnvelopeTests: XCTestCase { XCTAssertNotNil( SentryEnvelopeItem(attachment: attachment, maxAttachmentSize: fixture.maxAttachmentSize)) } - + + func testInitWithReplayEvent_replayRecordingFailsToSerialize_shouldReturnNil() { + // -- Arrange -- + class MockReplayRecording: SentryReplayRecording { + override func serialize() -> [[String: Any]] { + // This will cause serialization to fail, because NSObject cannot be serialized to JSON + return [["KEY": NSObject()]] + } + } + + let event = SentryReplayEvent( + eventId: SentryId(), + replayStartTimestamp: Date(timeIntervalSince1970: 1_000), + replayType: SentryReplayType.buffer, + segmentId: 5 + ) + let recording = MockReplayRecording(segmentId: 5, size: 5_000, start: Date(timeIntervalSince1970: 2), duration: 5_000, frameCount: 5, frameRate: 1, height: 320, width: 950, extraEvents: []) + let videoUrl = URL(fileURLWithPath: fixture.path) + + // -- Act -- + let result = SentryEnvelopeItem(replayEvent: event, replayRecording: recording, video: videoUrl) + + // -- Assert -- + XCTAssertNil(result, "Expected nil result when replay recording serialization fails.") + } + private func writeDataToFile(data: Data) { do { try data.write(to: URL(fileURLWithPath: fixture.path)) diff --git a/Tests/SentryTests/Protocol/SentryFrameTests.swift b/Tests/SentryTests/Protocol/SentryFrameTests.swift index 0aaf6c20f46..97ae035ee40 100644 --- a/Tests/SentryTests/Protocol/SentryFrameTests.swift +++ b/Tests/SentryTests/Protocol/SentryFrameTests.swift @@ -21,10 +21,40 @@ class SentryFrameTests: XCTestCase { XCTAssertEqual(frame.imageAddress, actual["image_addr"] as? String) XCTAssertEqual(frame.instructionAddress, actual["instruction_addr"] as? String) XCTAssertEqual(frame.platform, actual["platform"] as? String) + XCTAssertEqual(frame.contextLine, actual["context_line"] as? String) + XCTAssertEqual(frame.preContext, actual["pre_context"] as? [String]) + XCTAssertEqual(frame.postContext, actual["post_context"] as? [String]) + XCTAssertEqual(frame.vars as? [String: AnyHashable], actual["vars"] as? [String: AnyHashable]) XCTAssertEqual(frame.inApp, actual["in_app"] as? NSNumber) XCTAssertEqual(frame.stackStart, actual["stack_start"] as? NSNumber) } - + + func testSerialize_WithGodotFrame() { + // Arrange + let frame = TestData.godotFrame + + // Act + let actual = frame.serialize() + + // Assert + XCTAssertEqual(frame.symbolAddress, actual["symbol_addr"] as? String) + XCTAssertEqual(frame.fileName, actual["filename"] as? String) + XCTAssertEqual(frame.function, actual["function"] as? String) + XCTAssertEqual(frame.module, actual["module"] as? String) + XCTAssertEqual(frame.lineNumber, actual["lineno"] as? NSNumber) + XCTAssertEqual(frame.columnNumber, actual["colno"] as? NSNumber) + XCTAssertEqual(frame.package, actual["package"] as? String) + XCTAssertEqual(frame.imageAddress, actual["image_addr"] as? String) + XCTAssertEqual(frame.instructionAddress, actual["instruction_addr"] as? String) + XCTAssertEqual(frame.platform, actual["platform"] as? String) + XCTAssertEqual(frame.contextLine, actual["context_line"] as? String) + XCTAssertEqual(frame.preContext, actual["pre_context"] as? [String]) + XCTAssertEqual(frame.postContext, actual["post_context"] as? [String]) + XCTAssertEqual(frame.vars as? [String: AnyHashable], actual["vars"] as? [String: AnyHashable]) + XCTAssertEqual(frame.inApp, actual["in_app"] as? NSNumber) + XCTAssertEqual(frame.stackStart, actual["stack_start"] as? NSNumber) + } + func testDecode_WithAllProperties() throws { // Arrange let frame = TestData.mainFrame @@ -42,11 +72,43 @@ class SentryFrameTests: XCTestCase { XCTAssertEqual(frame.columnNumber, decoded.columnNumber) XCTAssertEqual(frame.package, decoded.package) XCTAssertEqual(frame.imageAddress, decoded.imageAddress) + XCTAssertEqual(frame.instructionAddress, decoded.instructionAddress) XCTAssertEqual(frame.platform, decoded.platform) + XCTAssertEqual(frame.contextLine, decoded.contextLine) + XCTAssertEqual(frame.preContext, decoded.preContext) + XCTAssertEqual(frame.postContext, decoded.postContext) + XCTAssertEqual(frame.vars as? [String: AnyHashable], decoded.vars as? [String: AnyHashable]) XCTAssertEqual(frame.inApp, decoded.inApp) XCTAssertEqual(frame.stackStart, decoded.stackStart) } - + + func testDecode_WithGodotFrame() throws { + // Arrange + let frame = TestData.godotFrame + let data = try XCTUnwrap(SentrySerialization.data(withJSONObject: frame.serialize())) + + // Act + let decoded = try XCTUnwrap(decodeFromJSONData(jsonData: data) as Frame?) + + // Assert + XCTAssertEqual(frame.symbolAddress, decoded.symbolAddress) + XCTAssertEqual(frame.fileName, decoded.fileName) + XCTAssertEqual(frame.function, decoded.function) + XCTAssertEqual(frame.module, decoded.module) + XCTAssertEqual(frame.lineNumber, decoded.lineNumber) + XCTAssertEqual(frame.columnNumber, decoded.columnNumber) + XCTAssertEqual(frame.package, decoded.package) + XCTAssertEqual(frame.imageAddress, decoded.imageAddress) + XCTAssertEqual(frame.instructionAddress, decoded.instructionAddress) + XCTAssertEqual(frame.platform, decoded.platform) + XCTAssertEqual(frame.contextLine, decoded.contextLine) + XCTAssertEqual(frame.preContext, decoded.preContext) + XCTAssertEqual(frame.postContext, decoded.postContext) + XCTAssertEqual(frame.vars as? [String: AnyHashable], decoded.vars as? [String: AnyHashable]) + XCTAssertEqual(frame.inApp, decoded.inApp) + XCTAssertEqual(frame.stackStart, decoded.stackStart) + } + func testDecode_WithAllPropertiesNil() throws { // Arrange let frame = Frame() @@ -66,6 +128,10 @@ class SentryFrameTests: XCTestCase { XCTAssertNil(decoded.imageAddress) XCTAssertNil(decoded.instructionAddress) XCTAssertNil(decoded.platform) + XCTAssertNil(decoded.contextLine) + XCTAssertNil(decoded.preContext) + XCTAssertNil(decoded.postContext) + XCTAssertNil(decoded.vars) XCTAssertNil(decoded.inApp) XCTAssertNil(decoded.stackStart) } @@ -73,5 +139,5 @@ class SentryFrameTests: XCTestCase { func testSerialize_Bools() { SentryBooleanSerialization.test(Frame(), property: "inApp", serializedProperty: "in_app") SentryBooleanSerialization.test(Frame(), property: "stackStart", serializedProperty: "stack_start") - } + } } diff --git a/Tests/SentryTests/Protocol/SentryLogAttributeTests.swift b/Tests/SentryTests/Protocol/SentryLogAttributeTests.swift index f2095d4cf4a..c3e47827f09 100644 --- a/Tests/SentryTests/Protocol/SentryLogAttributeTests.swift +++ b/Tests/SentryTests/Protocol/SentryLogAttributeTests.swift @@ -6,7 +6,7 @@ final class SentryLogAttributeTests: XCTestCase { // MARK: - Encoding Tests func testEncodeStringAttribute() throws { - let attribute = SentryLog.Attribute.string("test value") + let attribute = SentryLog.Attribute(string: "test value") let data = try JSONEncoder().encode(attribute) let json = try XCTUnwrap(JSONSerialization.jsonObject(with: data) as? [String: Any]) @@ -16,7 +16,7 @@ final class SentryLogAttributeTests: XCTestCase { } func testEncodeBooleanAttribute() throws { - let attribute = SentryLog.Attribute.boolean(true) + let attribute = SentryLog.Attribute(boolean: true) let data = try JSONEncoder().encode(attribute) let json = try XCTUnwrap(JSONSerialization.jsonObject(with: data) as? [String: Any]) @@ -26,7 +26,7 @@ final class SentryLogAttributeTests: XCTestCase { } func testEncodeIntegerAttribute() throws { - let attribute = SentryLog.Attribute.integer(42) + let attribute = SentryLog.Attribute(integer: 42) let data = try JSONEncoder().encode(attribute) let json = try XCTUnwrap(JSONSerialization.jsonObject(with: data) as? [String: Any]) @@ -36,7 +36,7 @@ final class SentryLogAttributeTests: XCTestCase { } func testEncodeDoubleAttribute() throws { - let attribute = SentryLog.Attribute.double(3.14159) + let attribute = SentryLog.Attribute(double: 3.14159) let data = try JSONEncoder().encode(attribute) let json = try XCTUnwrap(JSONSerialization.jsonObject(with: data) as? [String: Any]) @@ -158,7 +158,7 @@ final class SentryLogAttributeTests: XCTestCase { // MARK: - Round-trip Tests func testRoundTripStringAttribute() throws { - let original = SentryLog.Attribute.string("round trip test") + let original = SentryLog.Attribute(string: "round trip test") let data = try JSONEncoder().encode(original) let decoded = try XCTUnwrap(decodeFromJSONData(jsonData: data) as SentryLog.Attribute?) @@ -168,7 +168,7 @@ final class SentryLogAttributeTests: XCTestCase { } func testRoundTripBooleanAttribute() throws { - let original = SentryLog.Attribute.boolean(false) + let original = SentryLog.Attribute(boolean: false) let data = try JSONEncoder().encode(original) let decoded = try XCTUnwrap(decodeFromJSONData(jsonData: data) as SentryLog.Attribute?) @@ -178,7 +178,7 @@ final class SentryLogAttributeTests: XCTestCase { } func testRoundTripIntegerAttribute() throws { - let original = SentryLog.Attribute.integer(-999) + let original = SentryLog.Attribute(integer: -999) let data = try JSONEncoder().encode(original) let decoded = try XCTUnwrap(decodeFromJSONData(jsonData: data) as SentryLog.Attribute?) @@ -188,7 +188,7 @@ final class SentryLogAttributeTests: XCTestCase { } func testRoundTripDoubleAttribute() throws { - let original = SentryLog.Attribute.double(-123.456) + let original = SentryLog.Attribute(double: -123.456) let data = try JSONEncoder().encode(original) let decoded = try XCTUnwrap(decodeFromJSONData(jsonData: data) as SentryLog.Attribute?) @@ -198,4 +198,97 @@ final class SentryLogAttributeTests: XCTestCase { let originalValue = try XCTUnwrap(original.value as? Double) XCTAssertEqual(decodedValue, originalValue, accuracy: 0.00001) } + + // MARK: - Initializer Tests + + func testInitializer_StringValue() { + let attribute = SentryLog.Attribute(string: "test string") + XCTAssertEqual(attribute.type, "string") + XCTAssertEqual(attribute.value as? String, "test string") + } + + func testInitializer_EmptyStringValue() { + let attribute = SentryLog.Attribute(string: "") + XCTAssertEqual(attribute.type, "string") + XCTAssertEqual(attribute.value as? String, "") + } + + func testInitializer_BooleanValue() { + let trueAttribute = SentryLog.Attribute(boolean: true) + XCTAssertEqual(trueAttribute.type, "boolean") + XCTAssertEqual(trueAttribute.value as? Bool, true) + + let falseAttribute = SentryLog.Attribute(boolean: false) + XCTAssertEqual(falseAttribute.type, "boolean") + XCTAssertEqual(falseAttribute.value as? Bool, false) + } + + func testInitializer_IntegerValue() { + let attribute = SentryLog.Attribute(integer: 42) + XCTAssertEqual(attribute.type, "integer") + XCTAssertEqual(attribute.value as? Int, 42) + } + + func testInitializer_ZeroIntegerValue() { + let attribute = SentryLog.Attribute(integer: 0) + XCTAssertEqual(attribute.type, "integer") + XCTAssertEqual(attribute.value as? Int, 0) + } + + func testInitializer_NegativeIntegerValue() { + let attribute = SentryLog.Attribute(integer: -42) + XCTAssertEqual(attribute.type, "integer") + XCTAssertEqual(attribute.value as? Int, -42) + } + + func testInitializer_DoubleValue() { + let attribute = SentryLog.Attribute(double: 3.14159) + XCTAssertEqual(attribute.type, "double") + XCTAssertEqual(attribute.value as? Double, 3.14159) + } + + func testInitializer_ZeroDoubleValue() { + let attribute = SentryLog.Attribute(double: 0.0) + XCTAssertEqual(attribute.type, "double") + XCTAssertEqual(attribute.value as? Double, 0.0) + } + + func testInitializer_NegativeDoubleValue() { + let attribute = SentryLog.Attribute(double: -3.14) + XCTAssertEqual(attribute.type, "double") + XCTAssertEqual(attribute.value as? Double, -3.14) + } + + func testInitializer_FloatValue() { + let attribute = SentryLog.Attribute(float: Float(2.71828)) + XCTAssertEqual(attribute.type, "double") + let doubleValue = attribute.value as? Double + XCTAssertNotNil(doubleValue) + XCTAssertEqual(doubleValue!, 2.71828, accuracy: 0.00001) + } + + func testInitializer_NSStringValue() { + let attribute = SentryLog.Attribute(value: NSString("nsstring test")) + XCTAssertEqual(attribute.type, "string") + XCTAssertEqual(attribute.value as? String, "nsstring test") + } + + func testInitializer_UnsupportedValue() { + let url = URL(string: "https://example.com")! + let attribute = SentryLog.Attribute(value: url) + XCTAssertEqual(attribute.type, "string") + XCTAssertTrue((attribute.value as? String)?.contains("https://example.com") == true) + } + + func testInitializer_ArrayValue() { + let attribute = SentryLog.Attribute(value: [1, 2, 3]) + XCTAssertEqual(attribute.type, "string") + XCTAssertTrue((attribute.value as? String)?.contains("1") == true) + } + + func testInitializer_DictionaryValue() { + let attribute = SentryLog.Attribute(value: ["key": "value"]) + XCTAssertEqual(attribute.type, "string") + XCTAssertTrue((attribute.value as? String)?.contains("key") == true) + } } diff --git a/Tests/SentryTests/Protocol/SentryLogLevelTests.swift b/Tests/SentryTests/Protocol/SentryLogLevelTests.swift index 965f79e01c7..d993c6ce571 100644 --- a/Tests/SentryTests/Protocol/SentryLogLevelTests.swift +++ b/Tests/SentryTests/Protocol/SentryLogLevelTests.swift @@ -187,7 +187,7 @@ final class SentryLogLevelTests: XCTestCase { for level in levels { let data = try JSONEncoder().encode(level) let jsonString = String(data: data, encoding: .utf8) - let expectedString = "\"\(level.rawValue)\"" + let expectedString = "\"\(level.value)\"" XCTAssertEqual(jsonString, expectedString, "Failed for level: \(level)") } diff --git a/Tests/SentryTests/Protocol/SentryLogMessageTests.swift b/Tests/SentryTests/Protocol/SentryLogMessageTests.swift new file mode 100644 index 00000000000..a8d1351fb0a --- /dev/null +++ b/Tests/SentryTests/Protocol/SentryLogMessageTests.swift @@ -0,0 +1,443 @@ +@testable import Sentry +import XCTest + +final class SentryLogMessageTests: XCTestCase { + + // MARK: - String Literal Tests + + func testStringLiteral() { + let logString: SentryLogMessage = "Simple string message" + + XCTAssertEqual(logString.message, "Simple string message") + XCTAssertEqual(logString.template, "Simple string message") + XCTAssertTrue(logString.attributes.isEmpty) + } + + func testEmptyStringLiteral() { + let logString: SentryLogMessage = "" + + XCTAssertEqual(logString.message, "") + XCTAssertTrue(logString.attributes.isEmpty) + } + + // MARK: - String Interpolation Tests + + func testStringInterpolation() { + let value = "test_value" + let logString: SentryLogMessage = "User: \(value)" + + XCTAssertEqual(logString.message, "User: test_value") + XCTAssertEqual(logString.template, "User: {0}") + XCTAssertEqual(logString.attributes.count, 1) + + guard let attributeValue = logString.attributes[0].value as? String else { + XCTFail("Expected string attribute") + return + } + XCTAssertEqual(attributeValue, "test_value") + } + + func testBoolInterpolation() { + let value = true + let logString: SentryLogMessage = "Active: \(value)" + + XCTAssertEqual(logString.message, "Active: true") + XCTAssertEqual(logString.attributes.count, 1) + + guard let attributeValue = logString.attributes[0].value as? Bool else { + XCTFail("Expected boolean attribute") + return + } + XCTAssertEqual(attributeValue, true) + } + + func testBoolInterpolationFalse() { + let value = false + let logString: SentryLogMessage = "Enabled: \(value)" + + XCTAssertEqual(logString.message, "Enabled: false") + XCTAssertEqual(logString.attributes.count, 1) + + guard let attributeValue = logString.attributes[0].value as? Bool else { + XCTFail("Expected boolean attribute") + return + } + XCTAssertEqual(attributeValue, false) + } + + func testIntInterpolation() { + let value = 42 + let logString: SentryLogMessage = "Count: \(value)" + + XCTAssertEqual(logString.message, "Count: 42") + XCTAssertEqual(logString.attributes.count, 1) + + guard let attributeValue = logString.attributes[0].value as? Int else { + XCTFail("Expected integer attribute") + return + } + XCTAssertEqual(attributeValue, 42) + } + + func testNegativeIntInterpolation() { + let value = -123 + let logString: SentryLogMessage = "Value: \(value)" + + XCTAssertEqual(logString.message, "Value: -123") + XCTAssertEqual(logString.attributes.count, 1) + + guard let attributeValue = logString.attributes[0].value as? Int else { + XCTFail("Expected integer attribute") + return + } + XCTAssertEqual(attributeValue, -123) + } + + func testDoubleInterpolation() { + let value = 3.14159 + let logString: SentryLogMessage = "Pi: \(value)" + + XCTAssertEqual(logString.message, "Pi: 3.14159") + XCTAssertEqual(logString.attributes.count, 1) + + guard let attributeValue = logString.attributes[0].value as? Double else { + XCTFail("Expected double attribute") + return + } + XCTAssertEqual(attributeValue, 3.14159, accuracy: 0.00001) + } + + func testFloatInterpolation() { + let value: Float = 2.718 + let logString: SentryLogMessage = "E: \(value)" + + XCTAssertEqual(logString.message, "E: 2.718") + XCTAssertEqual(logString.attributes.count, 1) + + guard let attributeValue = logString.attributes[0].value as? Double else { + XCTFail("Expected double attribute (from Float)") + return + } + XCTAssertEqual(attributeValue, Double(value), accuracy: 0.001) + } + + func testNegativeDoubleInterpolation() { + let value = -3.14159 + let logString: SentryLogMessage = "Negative Pi: \(value)" + + XCTAssertEqual(logString.message, "Negative Pi: -3.14159") + XCTAssertEqual(logString.attributes.count, 1) + + guard let attributeValue = logString.attributes[0].value as? Double else { + XCTFail("Expected double attribute") + return + } + XCTAssertEqual(attributeValue, -3.14159, accuracy: 0.00001) + } + + func testNegativeFloatInterpolation() { + let value: Float = -2.718 + let logString: SentryLogMessage = "Negative E: \(value)" + + XCTAssertEqual(logString.message, "Negative E: -2.718") + XCTAssertEqual(logString.attributes.count, 1) + + guard let attributeValue = logString.attributes[0].value as? Double else { + XCTFail("Expected double attribute (from Float)") + return + } + XCTAssertEqual(attributeValue, Double(value), accuracy: 0.001) + } + + // MARK: - Multiple Interpolation Tests + + func testMultipleInterpolations() { + let user = "john" + let active = true + let score = 95.5 + let attempts = 3 + + let logString: SentryLogMessage = "User \(user) has active=\(active), score=\(score), attempts=\(attempts)" + + XCTAssertEqual(logString.message, "User john has active=true, score=95.5, attempts=3") + XCTAssertEqual(logString.template, "User {0} has active={1}, score={2}, attempts={3}") + XCTAssertEqual(logString.attributes.count, 4) + + guard let userValue = logString.attributes[0].value as? String else { + XCTFail("Expected string attribute for user") + return + } + XCTAssertEqual(userValue, "john") + + guard let activeValue = logString.attributes[1].value as? Bool else { + XCTFail("Expected boolean attribute for active") + return + } + XCTAssertEqual(activeValue, true) + + guard let scoreValue = logString.attributes[2].value as? Double else { + XCTFail("Expected double attribute for score") + return + } + XCTAssertEqual(scoreValue, 95.5, accuracy: 0.001) + + guard let attemptsValue = logString.attributes[3].value as? Int else { + XCTFail("Expected integer attribute for attempts") + return + } + XCTAssertEqual(attemptsValue, 3) + } + + func testMixedTypesWithLiterals() { + let count = 10 + let percentage = 85.7 + + let logString: SentryLogMessage = "Processing \(count) items with \(percentage)% completion rate" + + XCTAssertEqual(logString.message, "Processing 10 items with 85.7% completion rate") + XCTAssertEqual(logString.attributes.count, 2) + + guard let countValue = logString.attributes[0].value as? Int else { + XCTFail("Expected integer attribute") + return + } + XCTAssertEqual(countValue, 10) + + guard let percentageValue = logString.attributes[1].value as? Double else { + XCTFail("Expected double attribute") + return + } + XCTAssertEqual(percentageValue, 85.7, accuracy: 0.001) + } + + // MARK: - Edge Cases + + func testZeroValues() { + let zero = 0 + let zeroFloat = 0.0 + let emptyString = "" + + let logString: SentryLogMessage = "Zero int: \(zero), zero double: \(zeroFloat), empty: '\(emptyString)'" + + XCTAssertEqual(logString.message, "Zero int: 0, zero double: 0.0, empty: ''") + XCTAssertEqual(logString.attributes.count, 3) + + guard let zeroValue = logString.attributes[0].value as? Int else { + XCTFail("Expected integer attribute") + return + } + XCTAssertEqual(zeroValue, 0) + + guard let zeroFloatValue = logString.attributes[1].value as? Double else { + XCTFail("Expected double attribute") + return + } + XCTAssertEqual(zeroFloatValue, 0.0) + + guard let emptyValue = logString.attributes[2].value as? String else { + XCTFail("Expected string attribute") + return + } + XCTAssertEqual(emptyValue, "") + } + + func testLargeNumbers() { + let largeInt = Int.max + let largeDouble = Double.greatestFiniteMagnitude + + let logString: SentryLogMessage = "Large int: \(largeInt), large double: \(largeDouble)" + + XCTAssertTrue(logString.message.contains("Large int: \(Int.max)")) + XCTAssertEqual(logString.attributes.count, 2) + + guard let largeIntValue = logString.attributes[0].value as? Int else { + XCTFail("Expected integer attribute") + return + } + XCTAssertEqual(largeIntValue, Int.max) + + guard let largeDoubleValue = logString.attributes[1].value as? Double else { + XCTFail("Expected double attribute") + return + } + XCTAssertEqual(largeDoubleValue, Double.greatestFiniteMagnitude) + } + + func testComplexInterpolationPattern() { + let logString: SentryLogMessage = "\("prefix") \(42) \(true) \(3.14) \("suffix")" + + XCTAssertEqual(logString.message, "prefix 42 true 3.14 suffix") + XCTAssertEqual(logString.attributes.count, 5) + + let expectedTypes = ["string", "integer", "boolean", "double", "string"] + for (index, expectedType) in expectedTypes.enumerated() { + XCTAssertEqual(logString.attributes[index].type, expectedType, "Attribute \(index) should be \(expectedType)") + } + } + + // MARK: - Template Tests + + func testStringLiteralTemplate() { + let logString: SentryLogMessage = "No interpolation here" + + XCTAssertEqual(logString.template, "No interpolation here") + XCTAssertEqual(logString.message, logString.template) + } + + func testEmptyStringTemplate() { + let logString: SentryLogMessage = "" + + XCTAssertEqual(logString.template, "") + XCTAssertEqual(logString.message, "") + } + + func testSingleInterpolationTemplate() { + let value = "test" + let logString: SentryLogMessage = "Value: \(value)" + + XCTAssertEqual(logString.template, "Value: {0}") + XCTAssertEqual(logString.message, "Value: test") + } + + func testMultipleInterpolationsTemplate() { + let name = "Alice" + let age = 30 + let active = true + let score = 95.5 + + let logString: SentryLogMessage = "User \(name), age \(age), active: \(active), score: \(score)" + + XCTAssertEqual(logString.template, "User {0}, age {1}, active: {2}, score: {3}") + XCTAssertEqual(logString.message, "User Alice, age 30, active: true, score: 95.5") + } + + func testIntermixedLiteralsAndInterpolations() { + let userId = "user123" + let count = 42 + + let logString: SentryLogMessage = "Processing user \(userId) with \(count) items completed successfully" + + XCTAssertEqual(logString.template, "Processing user {0} with {1} items completed successfully") + XCTAssertEqual(logString.message, "Processing user user123 with 42 items completed successfully") + } + + func testFloatInterpolationTemplate() { + let temperature: Float = 98.6 + let humidity = 65.2 + + let logString: SentryLogMessage = "Temperature: \(temperature)°F, Humidity: \(humidity)%" + + XCTAssertEqual(logString.template, "Temperature: {0}°F, Humidity: {1}%") + XCTAssertEqual(logString.message, "Temperature: 98.6°F, Humidity: 65.2%") + } + + func testTemplateWithSpecialCharacters() { + let message = "Hello, World!" + let percentage = 100.0 + + let logString: SentryLogMessage = "Message: \(message) - Complete: \(percentage)%" + + XCTAssertEqual(logString.template, "Message: {0} - Complete: {1}%") + XCTAssertEqual(logString.message, "Message: Hello, World! - Complete: 100.0%") + } + + func testTemplateWithZeroValues() { + let zeroInt = 0 + let zeroDouble = 0.0 + let emptyString = "" + let falseValue = false + + let logString: SentryLogMessage = "Int: \(zeroInt), Double: \(zeroDouble), String: '\(emptyString)', Bool: \(falseValue)" + + XCTAssertEqual(logString.template, "Int: {0}, Double: {1}, String: '{2}', Bool: {3}") + XCTAssertEqual(logString.message, "Int: 0, Double: 0.0, String: '', Bool: false") + XCTAssertEqual(logString.attributes.count, 4) + } + + func testTemplateWithNegativeValues() { + let negativeInt = -42 + let negativeDouble = -3.14159 + + let logString: SentryLogMessage = "Negative int: \(negativeInt), negative double: \(negativeDouble)" + + XCTAssertEqual(logString.template, "Negative int: {0}, negative double: {1}") + XCTAssertEqual(logString.message, "Negative int: -42, negative double: -3.14159") + } + + func testTemplateNumberingSequence() { + let a = "first" + let b = "second" + let c = "third" + let d = "fourth" + let e = "fifth" + + let logString: SentryLogMessage = "\(a) \(b) \(c) \(d) \(e)" + + XCTAssertEqual(logString.template, "{0} {1} {2} {3} {4}") + XCTAssertEqual(logString.message, "first second third fourth fifth") + XCTAssertEqual(logString.attributes.count, 5) + } + + func testTemplateWithOnlyInterpolations() { + let value1 = "hello" + let value2 = 42 + + let logString: SentryLogMessage = "\(value1)\(value2)" + + XCTAssertEqual(logString.template, "{0}{1}") + XCTAssertEqual(logString.message, "hello42") + } + + func testTemplateStartsAndEndsWithInterpolations() { + let start = "BEGIN" + let middle = "middle" + let end = "END" + + let logString: SentryLogMessage = "\(start) some text \(middle) more text \(end)" + + XCTAssertEqual(logString.template, "{0} some text {1} more text {2}") + XCTAssertEqual(logString.message, "BEGIN some text middle more text END") + } + + func testComplexTemplatePattern() { + let user = "john" + let action = "login" + let timestamp = 1_234_567_890 + let success = true + let duration = 1.5 + + let logString: SentryLogMessage = "[\(timestamp)] User '\(user)' performed '\(action)' - Success: \(success), Duration: \(duration)s" + + let expectedTemplate = "[{0}] User '{1}' performed '{2}' - Success: {3}, Duration: {4}s" + XCTAssertEqual(logString.template, expectedTemplate) + + let expectedMessage = "[1234567890] User 'john' performed 'login' - Success: true, Duration: 1.5s" + XCTAssertEqual(logString.message, expectedMessage) + + XCTAssertEqual(logString.attributes.count, 5) + } + + // MARK: - CustomStringConvertible Interpolation Tests + + func testCustomStringConvertibleInterpolation() { + let customObject = TestCustomStringConvertible(value: "test_description") + let logString: SentryLogMessage = "Custom object: \(customObject)" + + XCTAssertEqual(logString.message, "Custom object: test_description") + XCTAssertEqual(logString.template, "Custom object: {0}") + XCTAssertEqual(logString.attributes.count, 1) + + guard let attributeValue = logString.attributes[0].value as? String else { + XCTFail("Expected string attribute") + return + } + XCTAssertEqual(attributeValue, "test_description") + } +} + +// MARK: - Test Helper Classes + +private struct TestCustomStringConvertible: CustomStringConvertible { + let value: String + var description: String { value } +} diff --git a/Tests/SentryTests/Protocol/SentryLogTests.swift b/Tests/SentryTests/Protocol/SentryLogTests.swift index cb5d5a6a6d0..d7eee96e121 100644 --- a/Tests/SentryTests/Protocol/SentryLogTests.swift +++ b/Tests/SentryTests/Protocol/SentryLogTests.swift @@ -11,12 +11,12 @@ final class SentryLogTests: XCTestCase { level: SentryLog.Level.info, body: "Test log message", attributes: [ - "user_id": .string("12345"), - "is_active": .boolean(true), - "count": .integer(42), - "score": .double(3.14159) + "user_id": SentryLog.Attribute(string: "12345"), + "is_active": SentryLog.Attribute(boolean: true), + "count": SentryLog.Attribute(integer: 42), + "score": SentryLog.Attribute(double: 3.14159) ], - severityNumber: 21 + severityNumber: NSNumber(value: 21) ) private let jsonData = Data(""" @@ -39,6 +39,75 @@ final class SentryLogTests: XCTestCase { } """.utf8) + // MARK: - Severity Number Fallback Tests + + func testConstructorWithExplicitSeverityNumber() throws { + let log = SentryLog( + timestamp: Date(), + traceId: SentryId(), + level: .info, + body: "Test message", + attributes: [:], + severityNumber: 99 // Explicit value different from level's default + ) + + XCTAssertEqual(log.severityNumber, 99, "Should use explicitly provided severity number") + XCTAssertEqual(log.level, .info) + } + + func testConstructorWithoutSeverityNumberFallsBackToLevel() throws { + let log = SentryLog( + timestamp: Date(), + traceId: SentryId(), + level: .info, + body: "Test message", + attributes: [:] + // severityNumber not provided - should default to nil and fallback to level + ) + + XCTAssertEqual(log.severityNumber, 9, "Should derive severity number from info level") + XCTAssertEqual(log.level, .info) + } + + func testConstructorWithNilSeverityNumberFallsBackToLevel() throws { + let log = SentryLog( + timestamp: Date(), + traceId: SentryId(), + level: .error, + body: "Error message", + attributes: [:], + severityNumber: nil // Explicitly nil + ) + + XCTAssertEqual(log.severityNumber, 17, "Should derive severity number from error level") + XCTAssertEqual(log.level, .error) + } + + func testSeverityNumberFallbackForAllLevels() throws { + let testCases: [(SentryLog.Level, Int)] = [ + (.trace, 1), + (.debug, 5), + (.info, 9), + (.warn, 13), + (.error, 17), + (.fatal, 21) + ] + + for (level, expectedSeverity) in testCases { + let log = SentryLog( + timestamp: Date(), + traceId: SentryId(), + level: level, + body: "Test message", + attributes: [:] + // severityNumber not provided + ) + + XCTAssertEqual(log.severityNumber?.intValue, expectedSeverity, + "Level \(level) should derive severity number \(expectedSeverity)") + } + } + func testEncode() throws { let data = try encodeToJSONData(data: log) let json = try XCTUnwrap(JSONSerialization.jsonObject(with: data) as? [String: Any]) diff --git a/Tests/SentryTests/Protocol/SentrySDKSettings+Equality.h b/Tests/SentryTests/Protocol/SentrySDKSettings+Equality.h new file mode 100644 index 00000000000..3dbf371b2d8 --- /dev/null +++ b/Tests/SentryTests/Protocol/SentrySDKSettings+Equality.h @@ -0,0 +1,13 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface SentrySDKSettings (Equality) + +- (BOOL)isEqual:(id _Nullable)object; + +- (NSUInteger)hash; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Tests/SentryTests/Protocol/SentrySDKSettings+Equality.m b/Tests/SentryTests/Protocol/SentrySDKSettings+Equality.m new file mode 100644 index 00000000000..37b9e3559f5 --- /dev/null +++ b/Tests/SentryTests/Protocol/SentrySDKSettings+Equality.m @@ -0,0 +1,32 @@ +#import "SentryInternalDefines.h" +#import "SentrySDKSettings+Equality.h" + +@implementation SentrySDKSettings (Equality) + +- (BOOL)isEqual:(id _Nullable)object +{ + if (object == self) + return YES; + if ([self class] != [object class]) + return NO; + + SentrySDKSettings *_Nonnull otherSDKSettings + = SENTRY_UNWRAP_NULLABLE(SentrySDKSettings, object); + + if (!self.autoInferIP == otherSDKSettings.autoInferIP) { + return NO; + } + + return YES; +} + +- (NSUInteger)hash +{ + NSUInteger hash = 19; + + hash = hash * 29 + [@(self.autoInferIP) integerValue]; + + return hash; +} + +@end diff --git a/Tests/SentryTests/Protocol/SentrySDKSettingsTests.swift b/Tests/SentryTests/Protocol/SentrySDKSettingsTests.swift new file mode 100644 index 00000000000..e71c5281529 --- /dev/null +++ b/Tests/SentryTests/Protocol/SentrySDKSettingsTests.swift @@ -0,0 +1,186 @@ +@_spi(Private) @testable import Sentry +import XCTest + +class SentrySDKSettingsTests: XCTestCase { + + // MARK: - initWithOptions tests + + func testInitWithOptions_WhenOptionsNil_ReturnsDefaultSettings() { + let settings = SentrySDKSettings(options: nil) + + XCTAssertNotNil(settings) + XCTAssertFalse(settings.autoInferIP) + } + + func testInitWithOptions_WhenSendDefaultPiiTrue_SetsAutoInferIPToTrue() { + let options = try! SentryOptionsInternal.initWithDict([ + "dsn": "https://username:password@app.getsentry.com/12345", + "sendDefaultPii": true + ]) + + XCTAssertNotNil(options) + + let settings = SentrySDKSettings(options: options) + + XCTAssertNotNil(settings) + XCTAssertTrue(settings.autoInferIP) + } + + func testInitWithOptions_WhenSendDefaultPiiFalse_SetsAutoInferIPToFalse() { + let options = try! SentryOptionsInternal.initWithDict([ + "dsn": "https://username:password@app.getsentry.com/12345", + "sendDefaultPii": false + ]) + + XCTAssertNotNil(options) + + let settings = SentrySDKSettings(options: options) + + XCTAssertNotNil(settings) + XCTAssertFalse(settings.autoInferIP) + } + + // MARK: - initWithDict tests + + func testInitWithDict_WhenInferIpIsAuto_SetsAutoInferIPToTrue() { + let settings = SentrySDKSettings(dict: [ + "infer_ip": "auto" + ]) + + XCTAssertNotNil(settings) + XCTAssertTrue(settings.autoInferIP) + } + + func testInitWithDict_WhenInferIpIsNever_SetsAutoInferIPToFalse() { + let settings = SentrySDKSettings(dict: [ + "infer_ip": "never" + ]) + + XCTAssertNotNil(settings) + XCTAssertFalse(settings.autoInferIP) + } + + func testInitWithDict_WhenInferIpIsInvalidString_SetsAutoInferIPToFalse() { + let settings = SentrySDKSettings(dict: [ + "infer_ip": "invalid_value" + ]) + + XCTAssertNotNil(settings) + XCTAssertFalse(settings.autoInferIP) + } + + func testInitWithDict_WhenInferIpIsNotString_SetsAutoInferIPToFalse() { + let settings = SentrySDKSettings(dict: [ + "infer_ip": true + ]) + + XCTAssertNotNil(settings) + XCTAssertFalse(settings.autoInferIP) + } + + func testInitWithDict_WhenInferIpKeyMissing_SetsAutoInferIPToFalse() { + let settings = SentrySDKSettings(dict: [:]) + + XCTAssertNotNil(settings) + XCTAssertFalse(settings.autoInferIP) + } + + func testInitWithDict_WhenInferIpIsNil_SetsAutoInferIPToFalse() { + let settings = SentrySDKSettings(dict: [ + "infer_ip": NSNull() + ]) + + XCTAssertNotNil(settings) + XCTAssertFalse(settings.autoInferIP) + } + + // MARK: - serialize tests + + func testSerialize_WhenAutoInferIPIsTrue_ReturnsCorrectDictionary() { + let settings = SentrySDKSettings(dict: [ + "infer_ip": "auto" + ]) + + let serialized = settings.serialize() + + XCTAssertNotNil(serialized) + XCTAssertEqual(serialized["infer_ip"] as? String, "auto") + } + + func testSerialize_WhenAutoInferIPIsFalse_ReturnsCorrectDictionary() { + let settings = SentrySDKSettings(dict: [ + "infer_ip": "never" + ]) + + let serialized = settings.serialize() + + XCTAssertNotNil(serialized) + XCTAssertEqual(serialized["infer_ip"] as? String, "never") + } + + func testSerialize_WhenAutoInferIPIsSetDirectly_ReturnsCorrectDictionary() { + let settings = SentrySDKSettings() + settings.autoInferIP = true + + let serialized = settings.serialize() + + XCTAssertNotNil(serialized) + XCTAssertEqual(serialized["infer_ip"] as? String, "auto") + } + + func testSerialize_WhenAutoInferIPIsSetToFalseDirectly_ReturnsCorrectDictionary() { + let settings = SentrySDKSettings() + settings.autoInferIP = false + + let serialized = settings.serialize() + + XCTAssertNotNil(serialized) + XCTAssertEqual(serialized["infer_ip"] as? String, "never") + } + + // MARK: - autoInferIP property tests + + func testAutoInferIPProperty_CanBeSetAndRetrieved() { + let settings = SentrySDKSettings() + + // Test default value + XCTAssertFalse(settings.autoInferIP) + + // Test setting to true + settings.autoInferIP = true + XCTAssertTrue(settings.autoInferIP) + + // Test setting to false + settings.autoInferIP = false + XCTAssertFalse(settings.autoInferIP) + } + + // MARK: - edge case tests + + func testEdgeCase_EmptyDictionaryInitialization() { + let settings = SentrySDKSettings(dict: [:]) + + XCTAssertNotNil(settings) + XCTAssertFalse(settings.autoInferIP) + } + + func testEdgeCase_NonStringValuesInDictionary() { + let settings = SentrySDKSettings(dict: [ + "infer_ip": 42, + "other_key": "value" + ]) + + XCTAssertNotNil(settings) + XCTAssertFalse(settings.autoInferIP) + } + + func testEdgeCase_CaseSensitiveInferIpValues() { + let settings1 = SentrySDKSettings(dict: ["infer_ip": "AUTO"]) + let settings2 = SentrySDKSettings(dict: ["infer_ip": "Auto"]) + let settings3 = SentrySDKSettings(dict: ["infer_ip": "auto"]) + + XCTAssertFalse(settings1.autoInferIP) // Should be case sensitive + XCTAssertFalse(settings2.autoInferIP) // Should be case sensitive + XCTAssertTrue(settings3.autoInferIP) // Exact match should work + } +} diff --git a/Tests/SentryTests/Protocol/SentrySdkInfo+Equality.h b/Tests/SentryTests/Protocol/SentrySdkInfo+Equality.h index b22fe628d46..b33a3809837 100644 --- a/Tests/SentryTests/Protocol/SentrySdkInfo+Equality.h +++ b/Tests/SentryTests/Protocol/SentrySdkInfo+Equality.h @@ -1,4 +1,4 @@ -#import "SentrySdkInfo.h" +#import "SentrySwift.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Tests/SentryTests/Protocol/SentrySdkInfo+Equality.m b/Tests/SentryTests/Protocol/SentrySdkInfo+Equality.m index a2284a81818..64744b690c9 100644 --- a/Tests/SentryTests/Protocol/SentrySdkInfo+Equality.m +++ b/Tests/SentryTests/Protocol/SentrySdkInfo+Equality.m @@ -1,4 +1,5 @@ #import "SentrySdkInfo+Equality.h" +#import @implementation SentrySdkInfo (Equality) @@ -34,6 +35,10 @@ - (BOOL)isEqual:(id _Nullable)object return NO; } + if (![self.settings isEqual:otherSdkInfo.settings]) { + return NO; + } + return YES; } @@ -46,6 +51,7 @@ - (NSUInteger)hash hash = hash * 23 + [self.integrations hash]; hash = hash * 23 + [self.features hash]; hash = hash * 23 + [self.packages hash]; + hash = hash * 23 + [self.settings hash]; return hash; } diff --git a/Tests/SentryTests/Protocol/SentrySdkInfoNilTests.m b/Tests/SentryTests/Protocol/SentrySdkInfoNilTests.m index 74ac72e4432..74e4f7e6209 100644 --- a/Tests/SentryTests/Protocol/SentrySdkInfoNilTests.m +++ b/Tests/SentryTests/Protocol/SentrySdkInfoNilTests.m @@ -1,4 +1,5 @@ -#import "SentrySdkInfo.h" +#import "SentrySwift.h" +#import #import @interface SentrySdkInfoNilTests : XCTestCase @@ -15,11 +16,13 @@ - (void)testSdkNameIsNil { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnonnull" - SentrySdkInfo *actual = [[SentrySdkInfo alloc] initWithName:nil - version:@"" - integrations:@[] - features:@[] - packages:@[]]; + SentrySdkInfo *actual = + [[SentrySdkInfo alloc] initWithName:nil + version:@"" + integrations:@[] + features:@[] + packages:@[] + settings:[[SentrySDKSettings alloc] initWithDict:@{}]]; #pragma clang diagnostic pop [self assertSdkInfoIsEmtpy:actual]; @@ -29,11 +32,13 @@ - (void)testVersinStringIsNil { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnonnull" - SentrySdkInfo *actual = [[SentrySdkInfo alloc] initWithName:@"" - version:nil - integrations:@[] - features:@[] - packages:@[]]; + SentrySdkInfo *actual = + [[SentrySdkInfo alloc] initWithName:@"" + version:nil + integrations:@[] + features:@[] + packages:@[] + settings:[[SentrySDKSettings alloc] initWithDict:@{}]]; #pragma clang diagnostic pop [self assertSdkInfoIsEmtpy:actual]; @@ -43,11 +48,13 @@ - (void)testIntegrationsAreNil { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnonnull" - SentrySdkInfo *actual = [[SentrySdkInfo alloc] initWithName:@"" - version:@"" - integrations:nil - features:@[] - packages:@[]]; + SentrySdkInfo *actual = + [[SentrySdkInfo alloc] initWithName:@"" + version:@"" + integrations:nil + features:@[] + packages:@[] + settings:[[SentrySDKSettings alloc] initWithDict:@{}]]; #pragma clang diagnostic pop [self assertSdkInfoIsEmtpy:actual]; @@ -57,11 +64,13 @@ - (void)testFeaturesAreNil { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnonnull" - SentrySdkInfo *actual = [[SentrySdkInfo alloc] initWithName:@"" - version:@"" - integrations:@[] - features:nil - packages:@[]]; + SentrySdkInfo *actual = + [[SentrySdkInfo alloc] initWithName:@"" + version:@"" + integrations:@[] + features:nil + packages:@[] + settings:[[SentrySDKSettings alloc] initWithDict:@{}]]; #pragma clang diagnostic pop [self assertSdkInfoIsEmtpy:actual]; @@ -71,11 +80,13 @@ - (void)testPackagesAreNil { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wnonnull" - SentrySdkInfo *actual = [[SentrySdkInfo alloc] initWithName:@"" - version:@"" - integrations:@[] - features:@[] - packages:nil]; + SentrySdkInfo *actual = + [[SentrySdkInfo alloc] initWithName:@"" + version:@"" + integrations:@[] + features:@[] + packages:nil + settings:[[SentrySDKSettings alloc] initWithDict:@{}]]; #pragma clang diagnostic pop [self assertSdkInfoIsEmtpy:actual]; @@ -108,6 +119,8 @@ - (void)assertSdkInfoIsEmtpy:(SentrySdkInfo *)sdkInfo XCTAssertEqualObjects(@"", sdkInfo.version); XCTAssertEqualObjects(@[], sdkInfo.integrations); XCTAssertEqualObjects(@[], sdkInfo.features); + // Default value for autoInferIP is false + XCTAssertEqual(sdkInfo.settings.autoInferIP, NO); } @end diff --git a/Tests/SentryTests/Protocol/SentrySdkInfoTests.swift b/Tests/SentryTests/Protocol/SentrySdkInfoTests.swift index d4bb1c7bdc2..622319d4abf 100644 --- a/Tests/SentryTests/Protocol/SentrySdkInfoTests.swift +++ b/Tests/SentryTests/Protocol/SentrySdkInfoTests.swift @@ -21,12 +21,14 @@ class SentrySdkInfoTests: XCTestCase { func testWithPatchLevelSuffix() { let version = "50.10.20-beta1" + let settings = SentrySDKSettings(dict: [:]) let actual = SentrySdkInfo( name: sdkName, version: version, integrations: [], features: [], - packages: [] + packages: [], + settings: settings ) XCTAssertEqual(sdkName, actual.name) @@ -35,12 +37,14 @@ class SentrySdkInfoTests: XCTestCase { func testWithAnyVersion() { let version = "anyVersion" + let settings = SentrySDKSettings(dict: [:]) let actual = SentrySdkInfo( name: sdkName, version: version, integrations: [], features: [], - packages: [] + packages: [], + settings: settings ) XCTAssertEqual(sdkName, actual.name) @@ -49,12 +53,14 @@ class SentrySdkInfoTests: XCTestCase { func testSerialization() { let version = "5.2.0" + let settings = SentrySDKSettings(dict: [:]) let sdkInfo = SentrySdkInfo( name: sdkName, version: version, integrations: ["a"], features: ["b"], - packages: [] + packages: [], + settings: settings ).serialize() XCTAssertEqual(sdkName, sdkInfo["name"] as? String) @@ -64,29 +70,34 @@ class SentrySdkInfoTests: XCTestCase { } func testSerializationValidIntegrations() { + let settings = SentrySDKSettings(dict: [:]) let sdkInfo = SentrySdkInfo( name: "", version: "", integrations: ["a", "b"], features: [], - packages: [] + packages: [], + settings: settings ).serialize() XCTAssertEqual(["a", "b"], sdkInfo["integrations"] as? [String]) } func testSerializationValidFeatures() { + let settings = SentrySDKSettings(dict: [:]) let sdkInfo = SentrySdkInfo( name: "", version: "", integrations: [], features: ["c", "d"], - packages: [] + packages: [], + settings: settings ).serialize() XCTAssertEqual(["c", "d"], sdkInfo["features"] as? [String]) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testSPM_packageInfo() throws { SentrySdkPackage.setPackageManager(0) let actual = SentrySdkInfo.global() @@ -98,6 +109,7 @@ class SentrySdkInfoTests: XCTestCase { XCTAssertEqual(packages[0]["version"] as? String, SentryMeta.versionString) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCarthage_packageInfo() throws { SentrySdkPackage.setPackageManager(2) let actual = SentrySdkInfo.global() @@ -109,6 +121,7 @@ class SentrySdkInfoTests: XCTestCase { XCTAssertEqual(packages[0]["version"] as? String, SentryMeta.versionString) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testcocoapods_packageInfo() throws { SentrySdkPackage.setPackageManager(1) let actual = SentrySdkInfo.global() @@ -120,7 +133,8 @@ class SentrySdkInfoTests: XCTestCase { XCTAssertEqual(packages[0]["version"] as? String, SentryMeta.versionString) } - func testNoPackageNames () { + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + func testNoPackageNames() { SentrySdkPackage.setPackageManager(3) let actual = SentrySdkInfo.global() @@ -129,6 +143,8 @@ class SentrySdkInfoTests: XCTestCase { func testInitWithDict_SdkInfo() { let version = "10.3.1" + let settings = SentrySDKSettings() + settings.autoInferIP = true let expected = SentrySdkInfo( name: sdkName, version: version, @@ -137,7 +153,8 @@ class SentrySdkInfoTests: XCTestCase { packages: [ ["name": "a", "version": "1"], ["name": "b", "version": "2"] - ] + ], + settings: settings ) let dict = [ @@ -148,6 +165,9 @@ class SentrySdkInfoTests: XCTestCase { "packages": [ ["name": "a", "version": "1"], ["name": "b", "version": "2"] + ], + "settings": [ + "infer_ip": "auto" ] ] as [String: Any] @@ -156,6 +176,7 @@ class SentrySdkInfoTests: XCTestCase { func testInitWithDict_SdkInfo_RemovesDuplicates() { let version = "10.3.1" + let settings = SentrySDKSettings(dict: ["infer_ip": "auto"]) let expected = SentrySdkInfo( name: sdkName, version: version, @@ -163,7 +184,8 @@ class SentrySdkInfoTests: XCTestCase { features: ["c"], packages: [ ["name": "a", "version": "1"] - ] + ], + settings: settings ) let dict = [ @@ -174,6 +196,9 @@ class SentrySdkInfoTests: XCTestCase { "packages": [ ["name": "a", "version": "1"], ["name": "a", "version": "1"] + ], + "settings": [ + "infer_ip": "auto" ] ] as [String: Any] @@ -182,6 +207,7 @@ class SentrySdkInfoTests: XCTestCase { func testInitWithDict_SdkInfo_IgnoresOrder() { let version = "10.3.1" + let settings = SentrySDKSettings(dict: ["infer_ip": "never"]) let expected = SentrySdkInfo( name: sdkName, version: version, @@ -190,7 +216,8 @@ class SentrySdkInfoTests: XCTestCase { packages: [ ["name": "a", "version": "1"], ["name": "b", "version": "2"] - ] + ], + settings: settings ) let dict = [ @@ -202,6 +229,10 @@ class SentrySdkInfoTests: XCTestCase { ["name": "b", "version": "2"], ["name": "a", "version": "1"] ] + , + "settings": [ + "infer_ip": "never" + ] ] as [String: Any] XCTAssertEqual(expected, SentrySdkInfo(dict: dict)) @@ -233,6 +264,8 @@ class SentrySdkInfoTests: XCTestCase { func testInitWithDict_WrongTypesInArrays() { let version = "10.3.1" + let settings = SentrySDKSettings(dict: [:]) + settings.autoInferIP = false let expected = SentrySdkInfo( name: sdkName, version: version, @@ -240,7 +273,8 @@ class SentrySdkInfoTests: XCTestCase { features: ["b"], packages: [ ["name": "a", "version": "1"] - ] + ], + settings: settings ) let dict = [ @@ -265,7 +299,10 @@ class SentrySdkInfoTests: XCTestCase { "b", [:] as [String: Any], ["name": "a", "version": "1", "invalid": -1] as [String: Any] - ] as [Any] + ] as [Any], + "settings": [ + "infer_ip": "false" + ] ] as [String: Any] XCTAssertEqual(expected, SentrySdkInfo(dict: dict)) @@ -277,6 +314,7 @@ class SentrySdkInfoTests: XCTestCase { assertEmptySdkInfo(actual: SentrySdkInfo(dict: dict)) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testglobal() throws { SentrySDK.start(options: Options()) let actual = SentrySdkInfo.global() @@ -286,6 +324,7 @@ class SentrySdkInfoTests: XCTestCase { XCTAssertTrue(actual.features.count > 0) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testFromGlobalsWithExtraPackage() throws { let extraPackage = ["name": "test-package", "version": "1.0.0"] SentryExtraPackages.addPackageName(extraPackage["name"]!, version: extraPackage["version"]!) @@ -295,6 +334,7 @@ class SentrySdkInfoTests: XCTestCase { XCTAssertTrue(actual.packages.contains(extraPackage)) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testFromGlobalsWithExtraPackageAndPackageManager() throws { let extraPackage = ["name": "test-package", "version": "1.0.0"] SentryExtraPackages.addPackageName(extraPackage["name"]!, version: extraPackage["version"]!) @@ -306,13 +346,141 @@ class SentrySdkInfoTests: XCTestCase { XCTAssertTrue(actual.packages.contains(["name": "cocoapods:getsentry/\(SentryMeta.sdkName)", "version": SentryMeta.versionString])) } + func testSerializationIncludesSettings() { + let version = "5.2.0" + let settings = SentrySDKSettings(dict: ["infer_ip": "auto"]) + let sdkInfo = SentrySdkInfo( + name: sdkName, + version: version, + integrations: ["a"], + features: ["b"], + packages: [], + settings: settings + ).serialize() + + XCTAssertEqual(sdkName, sdkInfo["name"] as? String) + XCTAssertEqual(version, sdkInfo["version"] as? String) + XCTAssertEqual(["a"], sdkInfo["integrations"] as? [String]) + XCTAssertEqual(["b"], sdkInfo["features"] as? [String]) + + // Test that settings are included in serialization + let serializedSettings = sdkInfo["settings"] as? [String: Any] + XCTAssertNotNil(serializedSettings) + XCTAssertEqual("auto", serializedSettings?["infer_ip"] as? String) + } + + func testInitWithDict_IncludesSettings() { + let version = "10.3.1" + let dict = [ + "name": sdkName, + "version": version, + "integrations": ["a", "b"], + "features": ["c", "d"], + "packages": [ + ["name": "a", "version": "1"], + ["name": "b", "version": "2"] + ], + "settings": [ + "infer_ip": "auto" + ] + ] as [String: Any] + + let actual = SentrySdkInfo(dict: dict) + + XCTAssertEqual(sdkName, actual.name) + XCTAssertEqual(version, actual.version) + XCTAssertEqual(Set(["a", "b"]), Set(actual.integrations)) + XCTAssertEqual(Set(["c", "d"]), Set(actual.features)) + XCTAssertEqual(2, actual.packages.count) + + // Test that settings are properly initialized + XCTAssertTrue(actual.settings.autoInferIP) + } + + func testInitWithDict_SettingsNil_DefaultsToEmptySettings() { + let dict = [ + "name": sdkName, + "version": "1.0.0", + "settings": nil + ] as [String: Any?] + + let actual = SentrySdkInfo(dict: dict as [AnyHashable: Any]) + + XCTAssertNotNil(actual.settings) + XCTAssertFalse(actual.settings.autoInferIP) + } + + func testInitWithDict_SettingsMissing_DefaultsToEmptySettings() { + let dict = [ + "name": sdkName, + "version": "1.0.0" + ] as [String: Any] + + let actual = SentrySdkInfo(dict: dict) + + XCTAssertNotNil(actual.settings) + XCTAssertFalse(actual.settings.autoInferIP) + } + + func testInitWithDict_SettingsWrongType_DefaultsToEmptySettings() { + let dict = [ + "name": sdkName, + "version": "1.0.0", + "settings": "not_a_dict" + ] as [String: Any] + + let actual = SentrySdkInfo(dict: dict) + + XCTAssertNotNil(actual.settings) + XCTAssertFalse(actual.settings.autoInferIP) + } + + func testEquality_IncludesSettings() { + let settings1 = SentrySDKSettings(dict: ["infer_ip": "auto"]) + let settings2 = SentrySDKSettings(dict: ["infer_ip": "never"]) + + let sdkInfo1 = SentrySdkInfo( + name: sdkName, + version: "1.0.0", + integrations: [], + features: [], + packages: [], + settings: settings1 + ) + + let sdkInfo2 = SentrySdkInfo( + name: sdkName, + version: "1.0.0", + integrations: [], + features: [], + packages: [], + settings: settings2 + ) + + // Should not be equal when settings differ + XCTAssertNotEqual(sdkInfo1, sdkInfo2) + + let sdkInfo3 = SentrySdkInfo( + name: sdkName, + version: "1.0.0", + integrations: [], + features: [], + packages: [], + settings: settings1 + ) + + // Should be equal when settings are the same + XCTAssertEqual(sdkInfo1, sdkInfo3) + } + private func assertEmptySdkInfo(actual: SentrySdkInfo) { XCTAssertEqual(SentrySdkInfo( name: "", version: "", integrations: [], features: [], - packages: [] + packages: [], + settings: SentrySDKSettings(dict: [:]) ), actual) } } diff --git a/Tests/SentryTests/Protocol/SentrySession+Equality.h b/Tests/SentryTests/Protocol/SentrySession+Equality.h index 07e3bbf766f..54ae3ea9fed 100644 --- a/Tests/SentryTests/Protocol/SentrySession+Equality.h +++ b/Tests/SentryTests/Protocol/SentrySession+Equality.h @@ -1,4 +1,4 @@ -#import "SentrySession.h" +@import Sentry; NS_ASSUME_NONNULL_BEGIN diff --git a/Tests/SentryTests/Protocol/SentryThreadTests.swift b/Tests/SentryTests/Protocol/SentryThreadTests.swift index db7f6bddf85..f8722e9fbad 100644 --- a/Tests/SentryTests/Protocol/SentryThreadTests.swift +++ b/Tests/SentryTests/Protocol/SentryThreadTests.swift @@ -77,7 +77,7 @@ class SentryThreadTests: XCTestCase { XCTAssertNil(decoded.isMain) } - func testDecode_WithWrongThreadId_ReturnsNil () throws { + func testDecode_WithWrongThreadId_ReturnsNil() throws { // Arrange let thread = SentryThread(threadId: 10) var actual = thread.serialize() diff --git a/Tests/SentryTests/Protocol/SentryUserTests.swift b/Tests/SentryTests/Protocol/SentryUserTests.swift index 604e9bf2581..e8e68d7ad59 100644 --- a/Tests/SentryTests/Protocol/SentryUserTests.swift +++ b/Tests/SentryTests/Protocol/SentryUserTests.swift @@ -157,12 +157,15 @@ class SentryUserTests: XCTestCase { func testModifyingFromMultipleThreads() throws { let queue = DispatchQueue(label: "SentryUserTests", qos: .userInteractive, attributes: [.concurrent, .initiallyInactive]) - let group = DispatchGroup() + + let loopCount = 20 + let expectation = XCTestExpectation(description: "ModifyingFromMultipleThreads") + expectation.expectedFulfillmentCount = loopCount + expectation.assertForOverFulfill = true let user = try XCTUnwrap(TestData.user.copy() as? User) - for i in 0...20 { - group.enter() + for i in 0.. *cache; - -- (void)binaryImageAdded:(const SentryCrashBinaryImage *)image; - -- (void)binaryImageRemoved:(const SentryCrashBinaryImage *)image; - -@end diff --git a/Tests/SentryTests/SentryBinaryImageCacheTests.swift b/Tests/SentryTests/SentryBinaryImageCacheTests.swift index 724bdbdbf2c..277a63d5c47 100644 --- a/Tests/SentryTests/SentryBinaryImageCacheTests.swift +++ b/Tests/SentryTests/SentryBinaryImageCacheTests.swift @@ -1,4 +1,5 @@ -import SentryTestUtils +@_spi(Private) @testable import Sentry +@_spi(Private) import SentryTestUtils import XCTest class SentryBinaryImageCacheTests: XCTestCase { @@ -8,119 +9,131 @@ class SentryBinaryImageCacheTests: XCTestCase { override func setUp() { super.setUp() - sut.start() + sut.start(false) } override func tearDown() { sut.stop() super.tearDown() } + + private func addBinaryImageToSut(_ binaryImage: SentryCrashBinaryImage) { + sut.binaryImageAdded(imageName: binaryImage.name, + vmAddress: binaryImage.vmAddress, + address: binaryImage.address, + size: binaryImage.size, + uuid: binaryImage.uuid) + } func testBinaryImageAdded() { - var binaryImage0 = createCrashBinaryImage(0, vmAddress: 0) - var binaryImage1 = createCrashBinaryImage(100, vmAddress: 100) - var binaryImage2 = createCrashBinaryImage(200, vmAddress: 200) - var binaryImage3 = createCrashBinaryImage(400, vmAddress: 400) - sut.binaryImageAdded(&binaryImage1) - - XCTAssertEqual(sut.cache.count, 1) - XCTAssertEqual(sut.cache.first?.name, "Expected Name at 100") - XCTAssertEqual(sut.cache.first?.uuid, "84BAEBDA-AD1A-33F4-B35D-8A45F5DAF322") - XCTAssertEqual(sut.cache.first?.vmAddress, 100) - - sut.binaryImageAdded(&binaryImage3) - XCTAssertEqual(sut.cache.count, 2) - XCTAssertEqual(sut.cache.last?.name, "Expected Name at 400") - XCTAssertEqual(sut.cache.last?.uuid, "84BAEBDA-AD1A-33F4-B35D-8A45F5DAF322") - XCTAssertEqual(sut.cache.last?.vmAddress, 400) - - sut.binaryImageAdded(&binaryImage2) - XCTAssertEqual(sut.cache.count, 3) - XCTAssertEqual(sut.cache.first?.name, "Expected Name at 100") - XCTAssertEqual(try XCTUnwrap(sut.cache.element(at: 1)).name, "Expected Name at 200") - XCTAssertEqual(sut.cache.last?.name, "Expected Name at 400") - - sut.binaryImageAdded(&binaryImage0) - XCTAssertEqual(sut.cache.count, 4) - XCTAssertEqual(sut.cache.first?.name, "Expected Name at 0") - XCTAssertEqual(try XCTUnwrap(sut.cache.element(at: 1)).name, "Expected Name at 100") + let binaryImage0 = createCrashBinaryImage(0, vmAddress: 0) + let binaryImage1 = createCrashBinaryImage(100, vmAddress: 100) + let binaryImage2 = createCrashBinaryImage(200, vmAddress: 200) + let binaryImage3 = createCrashBinaryImage(400, vmAddress: 400) + addBinaryImageToSut(binaryImage1) + + XCTAssertEqual(sut.cache?.count, 1) + XCTAssertEqual(sut.cache?.first?.name, "Expected Name at 100") + XCTAssertEqual(sut.cache?.first?.uuid, "84BAEBDA-AD1A-33F4-B35D-8A45F5DAF322") + XCTAssertEqual(sut.cache?.first?.vmAddress, 100) + + addBinaryImageToSut(binaryImage3) + XCTAssertEqual(sut.cache?.count, 2) + XCTAssertEqual(sut.cache?.last?.name, "Expected Name at 400") + XCTAssertEqual(sut.cache?.last?.uuid, "84BAEBDA-AD1A-33F4-B35D-8A45F5DAF322") + XCTAssertEqual(sut.cache?.last?.vmAddress, 400) + + addBinaryImageToSut(binaryImage2) + XCTAssertEqual(sut.cache?.count, 3) + XCTAssertEqual(sut.cache?.first?.name, "Expected Name at 100") + XCTAssertEqual(try XCTUnwrap(sut.cache?.element(at: 1)).name, "Expected Name at 200") + XCTAssertEqual(sut.cache?.last?.name, "Expected Name at 400") + + addBinaryImageToSut(binaryImage0) + XCTAssertEqual(sut.cache?.count, 4) + XCTAssertEqual(sut.cache?.first?.name, "Expected Name at 0") + XCTAssertEqual(try XCTUnwrap(sut.cache?.element(at: 1)).name, "Expected Name at 100") } - func testBinaryImageAdded_IsNull() { - sut.binaryImageAdded(nil) + func testBinaryImageAdded_WithNilName() { + sut.binaryImageAdded(imageName: nil, + vmAddress: 100, + address: 1_000, + size: 100, + uuid: nil) - XCTAssertEqual(self.sut.cache.count, 0) + XCTAssertEqual(self.sut.cache?.count, 0) } func testBinaryImageRemoved() { - var binaryImage0 = createCrashBinaryImage(0) - var binaryImage1 = createCrashBinaryImage(100) - var binaryImage2 = createCrashBinaryImage(200) - var binaryImage3 = createCrashBinaryImage(400) - - sut.binaryImageAdded(&binaryImage1) - sut.binaryImageAdded(&binaryImage3) - sut.binaryImageAdded(&binaryImage2) - sut.binaryImageAdded(&binaryImage0) - XCTAssertEqual(sut.cache.count, 4) - - XCTAssertEqual(sut.image(byAddress: 150)?.name, "Expected Name at 100") - sut.binaryImageRemoved(&binaryImage1) - XCTAssertEqual(sut.cache.count, 3) - XCTAssertNil(sut.image(byAddress: 100)) - - XCTAssertEqual(sut.image(byAddress: 450)?.name, "Expected Name at 400") - sut.binaryImageRemoved(&binaryImage3) - XCTAssertEqual(sut.cache.count, 2) - XCTAssertNil(sut.image(byAddress: 400)) - - XCTAssertEqual(sut.image(byAddress: 0)?.name, "Expected Name at 0") - sut.binaryImageRemoved(&binaryImage0) - XCTAssertEqual(sut.cache.count, 1) - XCTAssertNil(sut.image(byAddress: 0)) - - XCTAssertEqual(sut.image(byAddress: 200)?.name, "Expected Name at 200") - sut.binaryImageRemoved(&binaryImage2) - XCTAssertEqual(sut.cache.count, 0) - XCTAssertNil(sut.image(byAddress: 240)) + let binaryImage0 = createCrashBinaryImage(0) + let binaryImage1 = createCrashBinaryImage(100) + let binaryImage2 = createCrashBinaryImage(200) + let binaryImage3 = createCrashBinaryImage(400) + + addBinaryImageToSut(binaryImage1) + addBinaryImageToSut(binaryImage3) + addBinaryImageToSut(binaryImage2) + addBinaryImageToSut(binaryImage0) + XCTAssertEqual(sut.cache?.count, 4) + + XCTAssertEqual(sut.imageByAddress(150)?.name, "Expected Name at 100") + sut.binaryImageRemoved(binaryImage1.address) + XCTAssertEqual(sut.cache?.count, 3) + XCTAssertNil(sut.imageByAddress(100)) + + XCTAssertEqual(sut.imageByAddress(450)?.name, "Expected Name at 400") + sut.binaryImageRemoved(binaryImage3.address) + XCTAssertEqual(sut.cache?.count, 2) + XCTAssertNil(sut.imageByAddress(400)) + + XCTAssertEqual(sut.imageByAddress(0)?.name, "Expected Name at 0") + sut.binaryImageRemoved(binaryImage0.address) + XCTAssertEqual(sut.cache?.count, 1) + XCTAssertNil(sut.imageByAddress(0)) + + XCTAssertEqual(sut.imageByAddress(200)?.name, "Expected Name at 200") + sut.binaryImageRemoved(binaryImage2.address) + XCTAssertEqual(sut.cache?.count, 0) + XCTAssertNil(sut.imageByAddress(240)) } - func testBinaryImageRemoved_IsNull() { - var binaryImage = createCrashBinaryImage(0) - sut.binaryImageAdded(&binaryImage) + func testBinaryImageRemoved_InvalidAddress() { + let binaryImage = createCrashBinaryImage(0) + addBinaryImageToSut(binaryImage) - sut.binaryImageRemoved(nil) + sut.binaryImageRemoved(1_000_000) - XCTAssertEqual(self.sut.cache.count, 1) + XCTAssertEqual(self.sut.cache?.count, 1) } func testImageNameByAddress() { - var binaryImage0 = createCrashBinaryImage(0) - var binaryImage1 = createCrashBinaryImage(100) - var binaryImage2 = createCrashBinaryImage(200) - var binaryImage3 = createCrashBinaryImage(400) - - sut.binaryImageAdded(&binaryImage1) - sut.binaryImageAdded(&binaryImage3) - sut.binaryImageAdded(&binaryImage2) - sut.binaryImageAdded(&binaryImage0) - - XCTAssertEqual(sut.image(byAddress: 150)?.name, "Expected Name at 100") - XCTAssertEqual(sut.image(byAddress: 0)?.name, "Expected Name at 0") - XCTAssertEqual(sut.image(byAddress: 10)?.name, "Expected Name at 0") - XCTAssertEqual(sut.image(byAddress: 99)?.name, "Expected Name at 0") - XCTAssertEqual(sut.image(byAddress: 200)?.name, "Expected Name at 200") - XCTAssertEqual(sut.image(byAddress: 299)?.name, "Expected Name at 200") - XCTAssertEqual(sut.image(byAddress: 400)?.name, "Expected Name at 400") - XCTAssertNil(sut.image(byAddress: 300)) - XCTAssertNil(sut.image(byAddress: 399)) + let binaryImage0 = createCrashBinaryImage(0) + let binaryImage1 = createCrashBinaryImage(100) + let binaryImage2 = createCrashBinaryImage(200) + let binaryImage3 = createCrashBinaryImage(400) + + addBinaryImageToSut(binaryImage1) + addBinaryImageToSut(binaryImage3) + addBinaryImageToSut(binaryImage2) + addBinaryImageToSut(binaryImage0) + + XCTAssertEqual(sut.imageByAddress(150)?.name, "Expected Name at 100") + XCTAssertEqual(sut.imageByAddress(0)?.name, "Expected Name at 0") + XCTAssertEqual(sut.imageByAddress(10)?.name, "Expected Name at 0") + XCTAssertEqual(sut.imageByAddress(99)?.name, "Expected Name at 0") + XCTAssertEqual(sut.imageByAddress(200)?.name, "Expected Name at 200") + XCTAssertEqual(sut.imageByAddress(299)?.name, "Expected Name at 200") + XCTAssertEqual(sut.imageByAddress(400)?.name, "Expected Name at 400") + XCTAssertNil(sut.imageByAddress(300)) + XCTAssertNil(sut.imageByAddress(399)) } func testImagePathByName() { - var binaryImage = createCrashBinaryImage(0) - var binaryImage2 = createCrashBinaryImage(1) - sut.binaryImageAdded(&binaryImage) - sut.binaryImageAdded(&binaryImage2) + let binaryImage = createCrashBinaryImage(0) + let binaryImage2 = createCrashBinaryImage(1) + addBinaryImageToSut(binaryImage) + addBinaryImageToSut(binaryImage2) let paths = sut.imagePathsFor(inAppInclude: "Expected Name at 0") XCTAssertEqual(paths.first, "Expected Name at 0") @@ -138,7 +151,7 @@ class SentryBinaryImageCacheTests: XCTestCase { func testBinaryImageWithNULLName_DoesNotAddImage() { let address = UInt64(100) - var binaryImage = SentryCrashBinaryImage( + let binaryImage = SentryCrashBinaryImage( address: address, vmAddress: 0, size: 100, @@ -150,9 +163,9 @@ class SentryBinaryImageCacheTests: XCTestCase { crashInfoMessage2: nil ) - sut.binaryImageAdded(&binaryImage) - XCTAssertNil(self.sut.image(byAddress: address)) - XCTAssertEqual(self.sut.cache.count, 0) + addBinaryImageToSut(binaryImage) + XCTAssertNil(self.sut.imageByAddress(address)) + XCTAssertEqual(self.sut.cache?.count, 0) } func testBinaryImageNameDifferentEncoding_DoesNotAddImage() { @@ -162,7 +175,7 @@ class SentryBinaryImageCacheTests: XCTestCase { let nameCString = name.cString(using: UInt(8)) let address = UInt64(100) - var binaryImage = SentryCrashBinaryImage( + let binaryImage = SentryCrashBinaryImage( address: address, vmAddress: 0, size: 100, @@ -174,9 +187,9 @@ class SentryBinaryImageCacheTests: XCTestCase { crashInfoMessage2: nil ) - sut.binaryImageAdded(&binaryImage) - XCTAssertNil(self.sut.image(byAddress: address)) - XCTAssertEqual(self.sut.cache.count, 0) + addBinaryImageToSut(binaryImage) + XCTAssertNil(self.sut.imageByAddress(address)) + XCTAssertEqual(self.sut.cache?.count, 0) } func testAddingImagesWhileStoppingAndStartingOnDifferentThread() { @@ -187,17 +200,17 @@ class SentryBinaryImageCacheTests: XCTestCase { for i in 0.. SentryCrashBinaryImage { - let imageName = name ?? "Expected Name at \(address)" - let nameCString = imageName.withCString { strdup($0) } - - var uuidPointer = UnsafeMutablePointer(nil) - let uuidAsCharArray: [UInt8] = [132, 186, 235, 218, 173, 26, 51, 244, 179, 93, 138, 69, 245, 218, 243, 34] - uuidPointer = UnsafeMutablePointer.allocate(capacity: uuidAsCharArray.count) - uuidPointer?.initialize(from: uuidAsCharArray, count: uuidAsCharArray.count) - - let binaryImage = SentryCrashBinaryImage( - address: UInt64(address), - vmAddress: vmAddress, - size: 100, - name: nameCString, - uuid: uuidPointer, - cpuType: 1, - cpuSubType: 1, - crashInfoMessage: nil, - crashInfoMessage2: nil - ) - - return binaryImage + let imageName = name ?? "Expected Name at \(address)" + let nameCString = imageName.withCString { strdup($0) } + + var uuidPointer = UnsafeMutablePointer(nil) + let uuidAsCharArray: [UInt8] = [132, 186, 235, 218, 173, 26, 51, 244, 179, 93, 138, 69, 245, 218, 243, 34] + uuidPointer = UnsafeMutablePointer.allocate(capacity: uuidAsCharArray.count) + uuidPointer?.initialize(from: uuidAsCharArray, count: uuidAsCharArray.count) + + let binaryImage = SentryCrashBinaryImage( + address: UInt64(address), + vmAddress: vmAddress, + size: 100, + name: nameCString, + uuid: uuidPointer, + cpuType: 1, + cpuSubType: 1, + crashInfoMessage: nil, + crashInfoMessage2: nil + ) + + return binaryImage } diff --git a/Tests/SentryTests/SentryClient+TestInit.h b/Tests/SentryTests/SentryClient+TestInit.h index 4d5fe2c6e1a..fc88889c609 100644 --- a/Tests/SentryTests/SentryClient+TestInit.h +++ b/Tests/SentryTests/SentryClient+TestInit.h @@ -1,6 +1,6 @@ #import "SentryTransport.h" -@protocol SentryRandom; +@protocol SentryRandomProtocol; @class SentryCrashWrapper; @class SentryDispatchQueueWrapper; @@ -13,6 +13,7 @@ NS_ASSUME_NONNULL_BEGIN @interface SentryClient () - (_Nullable instancetype)initWithOptions:(SentryOptions *)options + dateProvider:(id)dateProvider dispatchQueue:(SentryDispatchQueueWrapper *)dispatchQueue deleteOldEnvelopeItems:(BOOL)deleteOldEnvelopeItems; @@ -31,7 +32,7 @@ NS_ASSUME_NONNULL_BEGIN deleteOldEnvelopeItems:(BOOL)deleteOldEnvelopeItems threadInspector:(SentryThreadInspector *)threadInspector debugImageProvider:(SentryDebugImageProvider *)debugImageProvider - random:(id)random + random:(id)random locale:(NSLocale *)locale timezone:(NSTimeZone *)timezone; diff --git a/Tests/SentryTests/SentryClientTests.swift b/Tests/SentryTests/SentryClientTests.swift index f9bb6285370..727116f754f 100644 --- a/Tests/SentryTests/SentryClientTests.swift +++ b/Tests/SentryTests/SentryClientTests.swift @@ -5,14 +5,16 @@ import XCTest // swiftlint:disable file_length // We are aware that the client has a lot of logic and we should maybe // move some of it to other classes. -class SentryClientTest: XCTestCase { +@available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") +class SentryClientTests: XCTestCase { private static let dsn = TestConstants.dsnAsString(username: "SentryClientTest") private class Fixture { let transport: TestTransport let transportAdapter: TestTransportAdapter - + + let dateProvider = TestCurrentDateProvider() let debugImageProvider = TestDebugImageProvider() let threadInspector = TestThreadInspector.instance @@ -23,16 +25,16 @@ class SentryClientTest: XCTestCase { let message: SentryMessage let user: User - let fileManager: SentryFileManager + let fileManager: TestFileManager let random = TestRandom(value: 1.0) let trace = SentryTracer(transactionContext: TransactionContext(name: "SomeTransaction", operation: "SomeOperation"), hub: nil) let transaction: Transaction - let crashWrapper = TestSentryCrashWrapper.sharedInstance() + let crashWrapper = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo) #if os(iOS) || targetEnvironment(macCatalyst) let deviceWrapper = TestSentryUIDeviceWrapper() #endif // os(iOS) || targetEnvironment(macCatalyst) - let processWrapper = TestSentryNSProcessInfoWrapper() + let processWrapper = MockSentryProcessInfo() let extraContentProvider: SentryExtraContextProvider let locale = Locale(identifier: "en_US") let timezone = TimeZone(identifier: "Europe/Vienna")! @@ -55,9 +57,15 @@ class SentryClientTest: XCTestCase { user.ipAddress = "127.0.0.1" let options = Options() - options.dsn = SentryClientTest.dsn - fileManager = try XCTUnwrap(SentryFileManager(options: options, dispatchQueueWrapper: TestSentryDispatchQueueWrapper())) - + options.dsn = SentryClientTests.dsn + fileManager = try XCTUnwrap( + TestFileManager( + options: options, + dateProvider: self.dateProvider, + dispatchQueueWrapper: self.dispatchQueue + ) + ) + transaction = Transaction(trace: trace, children: []) transport = TestTransport() @@ -79,8 +87,8 @@ class SentryClientTest: XCTestCase { func getSut(configureOptions: (Options) -> Void = { _ in }) -> SentryClient { var client: SentryClient! do { - let options = try Options(dict: [ - "dsn": SentryClientTest.dsn + let options = try SentryOptionsInternal.initWithDict([ + "dsn": SentryClientTests.dsn ]) options.removeAllIntegrations() configureOptions(options) @@ -154,25 +162,26 @@ class SentryClientTest: XCTestCase { } func testInit_CallsDeleteOldEnvelopeItemsInvocations() throws { - let fileManager = try TestFileManager(options: Options()) - - _ = SentryClient(options: Options(), fileManager: fileManager, deleteOldEnvelopeItems: true) - - XCTAssertEqual(1, fileManager.deleteOldEnvelopeItemsInvocations.count) + _ = SentryClient(options: Options(), fileManager: fixture.fileManager, deleteOldEnvelopeItems: true) + + XCTAssertEqual(1, fixture.fileManager.deleteOldEnvelopeItemsInvocations.count) } func testInitCachesInstallationIDAsync() throws { let dispatchQueue = fixture.dispatchQueue SentryDependencyContainer.sharedInstance().dispatchQueueWrapper = fixture.dispatchQueue - + let options = Options() - options.dsn = SentryClientTest.dsn + options.dsn = SentryClientTests.dsn // We have to put our cache into a subfolder of the default path, because on macOS we can't delete the default cache folder options.cacheDirectoryPath = "\(options.cacheDirectoryPath)/cache" _ = SentryClient(options: options) - - XCTAssertEqual(dispatchQueue.dispatchAsyncInvocations.count, 1) - + + // The invocations count must be two: + // - SentryFileManager.deleteOldEnvelopeItems() + // - SentryInstallation.cacheIDAsyncWithCacheDirectoryPath(cacheDirectoryPath:) + XCTAssertEqual(dispatchQueue.dispatchAsyncInvocations.count, 2) + let nonCachedID = SentryInstallation.id(withCacheDirectoryPathNonCached: options.cacheDirectoryPath) // We remove the file containing the installation ID, but the cached ID is still in memory @@ -258,7 +267,7 @@ class SentryClientTest: XCTestCase { func testCaptureEventTypeTransactionDoesNotIncludeThreadAndDebugMeta() throws { let event = Event(level: SentryLevel.warning) event.message = fixture.message - event.type = SentryEnvelopeItemTypeTransaction + event.type = SentryEnvelopeItemTypes.transaction let scope = Scope() let expectedTags = ["tagKey": "tagValue"] scope.setTags(expectedTags) @@ -301,7 +310,9 @@ class SentryClientTest: XCTestCase { #if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) func testCaptureEventWithCurrentScreen() throws { - SentryDependencyContainer.sharedInstance().application = TestSentryUIApplication() + let testApplication = TestSentryUIApplication() + SentryDependencyContainer.sharedInstance().application = testApplication + testApplication._relevantViewControllerNames = ["ClientTestViewController"] let event = Event() event.exceptions = [ Exception(value: "", type: "")] @@ -314,7 +325,9 @@ class SentryClientTest: XCTestCase { } func testCaptureEventWithCurrentScreenInTheScope() throws { - SentryDependencyContainer.sharedInstance().application = TestSentryUIApplication() + let testApplication = TestSentryUIApplication() + SentryDependencyContainer.sharedInstance().application = testApplication + testApplication._relevantViewControllerNames = ["ClientTestViewController"] let event = Event() event.exceptions = [ Exception(value: "", type: "")] @@ -328,7 +341,10 @@ class SentryClientTest: XCTestCase { let viewName = sentEvent.context?["app"]?["view_names"] as? [String] XCTAssertEqual(viewName?.first, "TestScreen") } - + + // We want the DispatchGroup to timeout and block the main thread. Therefore, we can't use a + // XCTestExpectation here. + // swiftlint:disable avoid_dispatch_groups_in_tests func testCaptureEventWithNoCurrentScreenMainIsLocked() throws { SentryDependencyContainer.sharedInstance().application = TestSentryUIApplication() @@ -341,16 +357,23 @@ class SentryClientTest: XCTestCase { self.fixture.getSut().capture(event: event, scope: self.fixture.scope) group.leave() } + + // Call group.enter a second time to ensure the main thread is blocked and the call to + // the main thread for getting the relevantViewControllersNames times out. group.enter() + let _ = group.wait(timeout: .now() + 1) let sentEvent = try lastSentEventWithAttachment() let viewName = sentEvent.context?["app"]?["view_names"] as? [String] XCTAssertNil(viewName) } + // swiftlint:enable avoid_dispatch_groups_in_tests func testCaptureTransactionWithScreen() throws { - SentryDependencyContainer.sharedInstance().application = TestSentryUIApplication() + let testApplication = TestSentryUIApplication() + SentryDependencyContainer.sharedInstance().application = testApplication + testApplication._relevantViewControllerNames = ["ClientTestViewController"] let tracer = SentryTracer(transactionContext: TransactionContext(operation: "Operation"), hub: nil) let event = try XCTUnwrap(Dynamic(tracer).toTransaction() as Transaction?) fixture.getSut().capture(event: event, scope: fixture.scope) @@ -388,7 +411,9 @@ class SentryClientTest: XCTestCase { } func testCaptureTransactionWithoutScreen() throws { - SentryDependencyContainer.sharedInstance().application = TestSentryUIApplication() + let testApplication = TestSentryUIApplication() + SentryDependencyContainer.sharedInstance().application = testApplication + testApplication._relevantViewControllerNames = ["ClientTestViewController"] let event = Transaction(trace: SentryTracer(context: SpanContext(operation: "test"), framesTracker: nil), children: []) fixture.getSut().capture(event: event, scope: fixture.scope) @@ -466,6 +491,74 @@ class SentryClientTest: XCTestCase { XCTAssertEqual(sentAttachments.count, 1) XCTAssertEqual(extraAttachment, sentAttachments.first) } + + func test_AttachmentProcessors_Chained_Additive() { + // -- Arrange -- + let sut = fixture.getSut() + let event = Event() + let att1 = Attachment(data: Data("one".utf8), filename: "AttachmentOne") + let att2 = Attachment(data: Data("two".utf8), filename: "AttachmentTwo") + + let p1 = TestAttachmentProcessor { atts, _ in + var out = atts + out.append(att1) + return out + } + + let p2 = TestAttachmentProcessor { atts, _ in + var out = atts + out.append(att2) + return out + } + + // Order matters; second sees the output of the first. + sut.add(p1) + sut.add(p2) + + // -- Act -- + sut.capture(event: event) + + // -- Assert -- + let sentAttachments = fixture.transportAdapter.sendEventWithTraceStateInvocations.first?.attachments ?? [] + XCTAssertEqual(sentAttachments.count, 2) + XCTAssertEqual(sentAttachments.element(at: 0), att1) + XCTAssertEqual(sentAttachments.element(at: 1), att2) + } + + func test_AttachmentProcessors_Chained_RemovalThenAdd() { + // -- Arrange -- + let sut = fixture.getSut() + let event = Event() + + // Start with one attachment from the scope so the removal has an effect. + let initial = Attachment(data: Data("init".utf8), filename: "Initial") + let scope = Scope() + scope.addAttachment(initial) + + // First processor removes everything. + let remover = TestAttachmentProcessor { _, _ in + return [] + } + + // Second processor appends a new one; should not see the removed initial. + let added = Attachment(data: Data("new".utf8), filename: "AddedAfterRemoval") + let adder = TestAttachmentProcessor { atts, _ in + var out = atts + out.append(added) + return out + } + + sut.add(remover) + sut.add(adder) + + // -- Act -- + sut.capture(event: event, scope: scope) + + // -- Assert -- + let sentAttachments = fixture.transportAdapter.sendEventWithTraceStateInvocations.first?.attachments ?? [] + XCTAssertEqual(sentAttachments.count, 1) + XCTAssertEqual(sentAttachments.first, added) + } func testCaptureEventWithDsnSetAfterwards() { let event = Event() @@ -474,7 +567,7 @@ class SentryClientTest: XCTestCase { options.dsn = nil }) - sut.options.dsn = SentryClientTest.dsn + sut.options.dsn = SentryClientTests.dsn let eventId = sut.capture(event: event) eventId.assertIsNotEmpty() @@ -905,7 +998,7 @@ class SentryClientTest: XCTestCase { let eventAppMemory = actual.context?["app"]?["app_memory"] as? Int XCTAssertEqual(eventAppMemory, 234_567) - let cpuCoreCount = actual.context?["device"]?["processor_count"] as? UInt + let cpuCoreCount = actual.context?["device"]?["processor_count"] as? Int XCTAssertEqual(fixture.processWrapper.processorCount, cpuCoreCount) } @@ -975,7 +1068,7 @@ class SentryClientTest: XCTestCase { #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) func testCaptureExceptionWithAppStateInForegroudWhenAppIsInForeground() throws { let app = TestSentryUIApplication() - app.applicationState = .active + app.unsafeApplicationState = .active SentryDependencyContainer.sharedInstance().application = app let event = TestData.event @@ -987,7 +1080,7 @@ class SentryClientTest: XCTestCase { func testCaptureTransaction_WithAppStateInForegroudWhenAppIsInForeground() throws { let app = TestSentryUIApplication() - app.applicationState = .active + app.unsafeApplicationState = .active SentryDependencyContainer.sharedInstance().application = app let event = fixture.transaction @@ -998,9 +1091,7 @@ class SentryClientTest: XCTestCase { } func testCaptureExceptionWithAppStateInForegroudWhenAppIsInBackground() throws { - let app = TestSentryUIApplication() - app.applicationState = .background - SentryDependencyContainer.sharedInstance().application = app + SentryDependencyContainer.sharedInstance().threadsafeApplication = SentryThreadsafeApplication(initialState: .background, notificationCenter: NotificationCenter.default) let event = TestData.event fixture.getSut().capture(event: event) @@ -1010,9 +1101,7 @@ class SentryClientTest: XCTestCase { } func testCaptureExceptionWithAppStateInForegroudWhenAppIsInactive() throws { - let app = TestSentryUIApplication() - app.applicationState = .inactive - SentryDependencyContainer.sharedInstance().application = app + SentryDependencyContainer.sharedInstance().threadsafeApplication = SentryThreadsafeApplication(initialState: .inactive, notificationCenter: NotificationCenter.default) let event = TestData.event fixture.getSut().capture(event: event) @@ -1022,9 +1111,7 @@ class SentryClientTest: XCTestCase { } func testCaptureExceptionWithAppStateInForegroundDoNotOverwriteExistingValue() throws { - let app = TestSentryUIApplication() - app.applicationState = .active - SentryDependencyContainer.sharedInstance().application = app + SentryDependencyContainer.sharedInstance().threadsafeApplication = SentryThreadsafeApplication(initialState: .active, notificationCenter: NotificationCenter.default) let event = TestData.event event.context?["app"] = ["in_foreground": "keep-value"] @@ -1235,40 +1322,35 @@ class SentryClientTest: XCTestCase { let serializedSpans = try XCTUnwrap(serialized["spans"] as? [[String: Any]]) XCTAssertEqual(1, serializedSpans.count) } - - @available(*, deprecated, message: "This is only marked as deprecated because assertNothingSent is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, these deprecation annotations can go away.") + func testNoDsn_MessageNotSent() { let sut = fixture.getSutWithNoDsn() let eventId = sut.capture(message: fixture.messageAsString) eventId.assertIsEmpty() assertNothingSent() } - - @available(*, deprecated, message: "This is only marked as deprecated because assertNothingSent is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, these deprecation annotations can go away.") + func testDisabled_MessageNotSent() { let sut = fixture.getSutDisabledSdk() let eventId = sut.capture(message: fixture.messageAsString) eventId.assertIsEmpty() assertNothingSent() } - - @available(*, deprecated, message: "This is only marked as deprecated because assertNothingSent is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, these deprecation annotations can go away.") + func testNoDsn_ExceptionNotSent() { let sut = fixture.getSutWithNoDsn() let eventId = sut.capture(exception: exception) eventId.assertIsEmpty() assertNothingSent() } - - @available(*, deprecated, message: "This is only marked as deprecated because assertNothingSent is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, these deprecation annotations can go away.") + func testNoDsn_ErrorNotSent() { let sut = fixture.getSutWithNoDsn() let eventId = sut.capture(error: error) eventId.assertIsEmpty() assertNothingSent() } - - @available(*, deprecated, message: "This is only marked as deprecated because assertNothingSent is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, these deprecation annotations can go away.") + func testNoDsn_SessionsNotSent() { _ = SentryEnvelope(event: Event()) fixture.getSut(configureOptions: { options in @@ -1277,8 +1359,7 @@ class SentryClientTest: XCTestCase { assertNothingSent() } - - @available(*, deprecated, message: "This is only marked as deprecated because assertNothingSent is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, these deprecation annotations can go away.") + func testNoDsn_EventWithSessionsNotSent() { _ = SentryEnvelope(event: Event()) let eventId = fixture.getSut(configureOptions: { options in @@ -1288,8 +1369,7 @@ class SentryClientTest: XCTestCase { eventId.assertIsEmpty() assertNothingSent() } - - @available(*, deprecated, message: "This is only marked as deprecated because assertNothingSent is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, these deprecation annotations can go away.") + func testNoDsn_ExceptionWithSessionsNotSent() { _ = SentryEnvelope(event: Event()) let eventId = fixture.getSut(configureOptions: { options in @@ -1301,8 +1381,7 @@ class SentryClientTest: XCTestCase { eventId.assertIsEmpty() assertNothingSent() } - - @available(*, deprecated, message: "This is only marked as deprecated because assertNothingSent is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, these deprecation annotations can go away.") + func testNoDsn_ErrorWithSessionsNotSent() { _ = SentryEnvelope(event: Event()) let eventId = fixture.getSut(configureOptions: { options in @@ -1314,23 +1393,19 @@ class SentryClientTest: XCTestCase { eventId.assertIsEmpty() assertNothingSent() } - - @available(*, deprecated, message: "This is only marked as deprecated because assertSampleRate is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, these deprecation annotations can go away.") + func testSampleRateNil_EventNotSampled() throws { try assertSampleRate(sampleRate: nil, randomValue: 0, isSampled: false) } - - @available(*, deprecated, message: "This is only marked as deprecated because assertSampleRate is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, these deprecation annotations can go away.") + func testSampleRateBiggerRandom_EventNotSampled() throws { try assertSampleRate(sampleRate: 0.5, randomValue: 0.49, isSampled: false) } - - @available(*, deprecated, message: "This is only marked as deprecated because assertSampleRate is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, these deprecation annotations can go away.") + func testSampleRateEqualsRandom_EventNotSampled() throws { try assertSampleRate(sampleRate: 0.5, randomValue: 0.5, isSampled: false) } - - @available(*, deprecated, message: "This is only marked as deprecated because assertSampleRate is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, these deprecation annotations can go away.") + func testSampleRateSmallerRandom_EventSampled() throws { try assertSampleRate(sampleRate: 0.50, randomValue: 0.51, isSampled: true) } @@ -1358,7 +1433,7 @@ class SentryClientTest: XCTestCase { func testEventDroppedByEventProcessor_RecordsLostEvent() { SentryDependencyContainer.sharedInstance().globalEventProcessor.add { _ in return nil } - beforeSendReturnsNil { $0.capture(message: fixture.messageAsString) } + fixture.getSut().capture(message: fixture.messageAsString) assertLostEventRecorded(category: .error, reason: .eventProcessor) } @@ -1366,7 +1441,7 @@ class SentryClientTest: XCTestCase { func testTransactionDroppedByEventProcessor_RecordsLostEvent() { SentryDependencyContainer.sharedInstance().globalEventProcessor.add { _ in return nil } - beforeSendReturnsNil { $0.capture(event: fixture.transaction) } + fixture.getSut().capture(event: fixture.transaction) assertLostEventRecorded(category: .transaction, reason: .eventProcessor) } @@ -1529,50 +1604,46 @@ class SentryClientTest: XCTestCase { XCTAssertEqual(3, fixture.transport.recordLostEventsWithCount.count) - // span dropped by event processor + // span dropped by beforeSendSpan XCTAssertEqual(fixture.transport.recordLostEventsWithCount.get(0)?.category, SentryDataCategory.span) - XCTAssertEqual(fixture.transport.recordLostEventsWithCount.get(0)?.reason, SentryDiscardReason.eventProcessor) + XCTAssertEqual(fixture.transport.recordLostEventsWithCount.get(0)?.reason, SentryDiscardReason.beforeSend) XCTAssertEqual(fixture.transport.recordLostEventsWithCount.get(0)?.quantity, 1) - // span dropped by beforeSendSpan + // span dropped by beforeSend XCTAssertEqual(fixture.transport.recordLostEventsWithCount.get(1)?.category, SentryDataCategory.span) XCTAssertEqual(fixture.transport.recordLostEventsWithCount.get(1)?.reason, SentryDiscardReason.beforeSend) XCTAssertEqual(fixture.transport.recordLostEventsWithCount.get(1)?.quantity, 1) - // span dropped by beforeSend + // span dropped by event processor XCTAssertEqual(fixture.transport.recordLostEventsWithCount.get(2)?.category, SentryDataCategory.span) - XCTAssertEqual(fixture.transport.recordLostEventsWithCount.get(2)?.reason, SentryDiscardReason.beforeSend) + XCTAssertEqual(fixture.transport.recordLostEventsWithCount.get(2)?.reason, SentryDiscardReason.eventProcessor) XCTAssertEqual(fixture.transport.recordLostEventsWithCount.get(2)?.quantity, 1) } - @available(*, deprecated, message: "-[SentryClient captureUserFeedback:] is deprecated. -[SentryClient captureFeedback:withScope:] is the new way. This test case can be removed in favor of testNoDsn_FeedbackNotSent when -[SentryClient captureUserFeedback:] is removed.") + func testNoDsn_UserFeedbackNotSent() { let sut = fixture.getSutWithNoDsn() sut.capture(userFeedback: UserFeedback(eventId: SentryId())) assertNothingSent() } - - @available(*, deprecated, message: "-[SentryClient captureUserFeedback:] is deprecated. -[SentryClient captureFeedback:withScope:] is the new way. This test case can be removed in favor of testDisabled_FeedbackNotSent when -[SentryClient captureUserFeedback:] is removed.") + func testDisabled_UserFeedbackNotSent() { let sut = fixture.getSutDisabledSdk() sut.capture(userFeedback: UserFeedback(eventId: SentryId())) assertNothingSent() } - - @available(*, deprecated, message: "-[SentryClient captureUserFeedback:] is deprecated. -[SentryClient captureFeedback:withScope:] is the new way. This test case can be removed in favor of testCaptureFeedback_WithEmptyEventId when -[SentryClient captureUserFeedback:] is removed.") + func testCaptureUserFeedback_WithEmptyEventId() { let sut = fixture.getSut() sut.capture(userFeedback: UserFeedback(eventId: SentryId.empty)) assertNothingSent() } - - @available(*, deprecated, message: "This is only marked as deprecated because assertNothingSent is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, this deprecation annotation can go away.") + func testNoDsn_FeedbackNotSent() { let sut = fixture.getSutWithNoDsn() sut.capture(feedback: fixture.feedback, scope: fixture.scope) assertNothingSent() } - - @available(*, deprecated, message: "This is only marked as deprecated because assertNothingSent is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, this deprecation annotation can go away.") + func testDisabled_FeedbackNotSent() { let sut = fixture.getSutDisabledSdk() sut.capture(feedback: fixture.feedback, scope: fixture.scope) @@ -1660,7 +1731,7 @@ class SentryClientTest: XCTestCase { eventId.assertIsNotEmpty() var expectedIntegrations = ["AutoBreadcrumbTracking", "AutoSessionTracking", "Crash", "NetworkTracking"] - if !SentryDependencyContainer.sharedInstance().crashWrapper.isBeingTraced() { + if !SentryDependencyContainer.sharedInstance().crashWrapper.isBeingTraced { expectedIntegrations = ["ANRTracking"] + expectedIntegrations } @@ -1702,7 +1773,7 @@ class SentryClientTest: XCTestCase { eventId.assertIsNotEmpty() let actual = try lastSentEvent() var expectedIntegrations = ["AutoBreadcrumbTracking", "AutoSessionTracking", "Crash", "NetworkTracking", integrationName] - if !SentryDependencyContainer.sharedInstance().crashWrapper.isBeingTraced() { + if !SentryDependencyContainer.sharedInstance().crashWrapper.isBeingTraced { expectedIntegrations = ["ANRTracking"] + expectedIntegrations } @@ -1724,16 +1795,27 @@ class SentryClientTest: XCTestCase { assertArrayEquals(expected: expected, actual: actual.sdk?["integrations"] as? [String]) } - func testFileManagerCantBeInit() { - SentryFileManager.prepareInitError() + func testFileManagerCantBeInit() throws { + try SentryFileManager.prepareInitError() + defer { + // We can not directly throw in a defer-block, so we catch the error and fail the test manually + do { + try SentryFileManager.tearDownInitError() + } catch { + XCTFail("Failed to tear down SentryFileManager error: \(error)") + } + } let options = Options() - options.dsn = SentryClientTest.dsn - let client = SentryClient(options: options, dispatchQueue: TestSentryDispatchQueueWrapper(), deleteOldEnvelopeItems: false) + options.dsn = SentryClientTests.dsn + let client = SentryClient( + options: options, + dateProvider: fixture.dateProvider, + dispatchQueue: fixture.dispatchQueue, + deleteOldEnvelopeItems: false + ) XCTAssertNil(client) - - SentryFileManager.tearDownInitError() } func testInstallationIdSetWhenNoUserId() throws { @@ -1765,13 +1847,17 @@ class SentryClientTest: XCTestCase { XCTAssertEqual(fixture.user.email, actual.user?.email) } - func testSendDefaultPiiEnabled_GivenNoIP_AutoIsSet() throws { + func testSendDefaultPiiEnabled_GivenNoIP_sdkIPIsAuto() throws { fixture.getSut(configureOptions: { options in options.sendDefaultPii = true }).capture(message: "any") let actual = try lastSentEvent() - XCTAssertEqual("{{auto}}", actual.user?.ipAddress) + XCTAssertNotNil(actual.sdk) + let sdk = try XCTUnwrap(actual.sdk) + XCTAssertNotNil(sdk["settings"]) + let settings = try XCTUnwrap(sdk["settings"] as? [String: Any]) + XCTAssertEqual(settings["infer_ip"] as? String, "auto") } func testSendDefaultPiiEnabled_GivenIP_IPAddressNotChanged() throws { @@ -1955,7 +2041,7 @@ class SentryClientTest: XCTestCase { let sut = fixture.getSut() let hub = SentryHub(client: sut, andScope: nil) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) func addIntegrations(amount: Int) { let emptyIntegration = EmptyIntegration() @@ -1968,19 +2054,18 @@ class SentryClientTest: XCTestCase { addIntegrations(amount: 1_000) let queue = fixture.queue - let group = DispatchGroup() // Run this in a loop to ensure that add while iterating over the integrations // Running it once doesn't guaranty failure - for _ in 0..<10 { - group.enter() + for i in 0..<10 { + let expectation = XCTestExpectation(description: "Add integrations completed \(i)") queue.async { addIntegrations(amount: 1_000) - group.leave() + expectation.fulfill() } sut.capture(event: Event()) - group.waitWithTimeout() + wait(for: [expectation], timeout: 1) hub.removeAllIntegrations() } } @@ -1995,7 +2080,7 @@ class SentryClientTest: XCTestCase { sut.capture(replayEvent, replayRecording: replayRecording, video: movieUrl!, with: Scope()) let envelope = fixture.transport.sentEnvelopes.first - XCTAssertEqual(try XCTUnwrap(envelope?.items.first).header.type, SentryEnvelopeItemTypeReplayVideo) + XCTAssertEqual(try XCTUnwrap(envelope?.items.first).header.type, SentryEnvelopeItemTypes.replayVideo) } func testCaptureReplayEvent_WrongEventFromEventProcessor() { @@ -2069,21 +2154,59 @@ class SentryClientTest: XCTestCase { let replayEvent = SentryReplayEvent(eventId: SentryId(), replayStartTimestamp: Date(), replayType: .session, segmentId: 2) replayEvent.sdk = ["name": "Test SDK", "version": "1.0.0"] let replayRecording = SentryReplayRecording(segmentId: 2, size: 200, start: Date(timeIntervalSince1970: 2), duration: 5_000, frameCount: 5, frameRate: 1, height: 930, width: 390, extraEvents: []) - + //Not a video url, but its ok for test the envelope let movieUrl = try XCTUnwrap(Bundle(for: self.classForCoder).url(forResource: "Resources/raw", withExtension: "json")) - + let scope = Scope() scope.addBreadcrumb(Breadcrumb(level: .debug, category: "Test Breadcrumb")) - + sut.capture(replayEvent, replayRecording: replayRecording, video: movieUrl, with: scope) - + let header = try XCTUnwrap(self.fixture.transport.sentEnvelopes.first?.header) - + XCTAssertEqual(header.sdkInfo?.name, "Test SDK") XCTAssertEqual(header.sdkInfo?.version, "1.0.0") } - + + func testCaptureReplayEvent_preparingEventFails_shouldNotCaptureAndRecordLostEvent() throws { + // -- Arrange -- + let sut = fixture.getSut() + let replayEvent = SentryReplayEvent(eventId: SentryId(), replayStartTimestamp: Date(), replayType: .session, segmentId: 2) + replayEvent.sdk = ["name": "Test SDK", "version": "1.0.0"] + let replayRecording = SentryReplayRecording( + segmentId: 2, + size: 200, + start: Date(timeIntervalSince1970: 2), + duration: 5_000, + frameCount: 5, + frameRate: 1, + height: 930, + width: 390, + extraEvents: [ + SentryRRWebEvent( + type: .custom, + timestamp: Date(timeIntervalSince1970: 0), + data: ["KEY": NSObject()] // There is a non-serializable object in the extra events, which will cause the event preparation to fail + ) + ] + ) + let movieUrl = try XCTUnwrap(URL(string: "https://example.com/movie.mp4")) + let scope = Scope() + + // -- Act -- + sut.capture(replayEvent, replayRecording: replayRecording, video: movieUrl, with: scope) + + // -- Assert -- + XCTAssertEqual(fixture.transport.sentEnvelopes.count, 0) + + XCTAssertEqual(fixture.transport.recordLostEventsWithCount.count, 1) + let lostEvent = try XCTUnwrap(fixture.transport.recordLostEventsWithCount.first) + XCTAssertEqual(lostEvent.category, .replay) + XCTAssertEqual(lostEvent.reason, SentryDiscardReason.insufficientData) + XCTAssertEqual(lostEvent.quantity, 1) + } + func testCaptureFatalEventSetReplayInScope() { let sut = fixture.getSut() let event = Event() @@ -2094,8 +2217,44 @@ class SentryClientTest: XCTestCase { XCTAssertEqual(scope.replayId, "someReplay") } -#if os(macOS) + func testCaptureLogsData() throws { + let sut = fixture.getSut() + let logData = Data("{\"items\":[{\"timestamp\":1627846801,\"level\":\"info\",\"body\":\"Test log message\"}]}".utf8) + + sut.captureLogsData(logData, with: NSNumber(value: 1)) + + // Verify that an envelope was sent + XCTAssertEqual(1, fixture.transport.sentEnvelopes.count) + + let envelope = try XCTUnwrap(fixture.transport.sentEnvelopes.first) + + // Verify envelope has one item + XCTAssertEqual(1, envelope.items.count) + + let item = try XCTUnwrap(envelope.items.first) + + // Verify the envelope item header + XCTAssertEqual("log", item.header.type) + XCTAssertEqual(UInt(logData.count), item.header.length) + XCTAssertEqual("application/vnd.sentry.items.log+json", item.header.contentType) + XCTAssertEqual(NSNumber(value: 1), item.header.itemCount) + + // Verify the envelope item data + XCTAssertEqual(logData, item.data) + } + + func testCaptureLogsData_WithDisabledClient() { + let sut = fixture.getSutDisabledSdk() + let logData = Data("{\"items\":[{\"timestamp\":1627846801,\"level\":\"info\",\"body\":\"Test log message\"}]}".utf8) + + sut.captureLogsData(logData, with: NSNumber(value: 1)) + + // Verify that no envelope was sent when client is disabled + XCTAssertEqual(0, fixture.transport.sentEnvelopes.count) + } + func testCaptureSentryWrappedException() throws { +#if os(macOS) let exception = NSException(name: NSExceptionName("exception"), reason: "reason", userInfo: nil) // If we don't raise the exception, it won't have the callStack data let raisedException = ExceptionCatcher.try { @@ -2116,7 +2275,7 @@ class SentryClientTest: XCTestCase { // Make sure the stacktrace is not empty XCTAssertGreaterThan(actual.threads?[0].stacktrace?.frames.count ?? 0, 1) // We will need to update it if the test class / module changes - let testMangledName = "$s11SentryTests0A10ClientTestC011testCaptureA16WrappedExceptionyyKF" + let testMangledName = "$s11SentryTests0a6ClientB0C011testCaptureA16WrappedExceptionyyKF" let frameWithTestFunction = actual.threads?[0].stacktrace?.frames.first { frame in frame.function == testMangledName } @@ -2124,11 +2283,14 @@ class SentryClientTest: XCTestCase { // Last frame should always be `__exceptionPreprocess` XCTAssertEqual(actual.threads?[0].stacktrace?.frames.last?.function, "__exceptionPreprocess") + #else + throw XCTSkip("Test is disabled for this OS version") + #endif // os(macOS) } -#endif // os(macOS) } -private extension SentryClientTest { +@available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") +private extension SentryClientTests { private func givenEventWithDebugMeta() -> Event { let event = Event(level: SentryLevel.fatal) let debugMeta = DebugMeta() @@ -2238,8 +2400,7 @@ private extension SentryClientTest { private func shortenIntegrations(_ integrations: [String]?) -> [String]? { return integrations?.map { $0.replacingOccurrences(of: "Sentry", with: "").replacingOccurrences(of: "Integration", with: "") } } - - @available(*, deprecated, message: "Remove check on transportAdapter.userFeedbackInvocations when SentryUserFeedback is removed in favor of SentryFeedback. Then this deprecation annotation can be removed.") + private func assertNothingSent() { XCTAssertTrue(fixture.transport.sentEnvelopes.isEmpty) XCTAssertEqual(0, fixture.transportAdapter.sentEventsWithSessionTraceState.count) @@ -2281,29 +2442,6 @@ private extension SentryClientTest { } } -#if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) - class TestSentryUIApplication: SentryUIApplication { - init() { - super.init(notificationCenterWrapper: TestNSNotificationCenterWrapper(), dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) - } - - override func relevantViewControllers() -> [UIViewController] { - return [ClientTestViewController()] - } - - private var _underlyingAppState: UIApplication.State = .active - override var applicationState: UIApplication.State { - get { _underlyingAppState } - set { _underlyingAppState = newValue } - } - } - - class ClientTestViewController: UIViewController { - - } -#endif - - @available(*, deprecated, message: "This is only marked as deprecated because assertNothingSent is marked as deprecated, due to it using a deprecated property inside it. When that property usage is removed, this deprecation annotations can be removed.") func assertSampleRate( sampleRate: NSNumber?, randomValue: Double, isSampled: Bool) throws { fixture.random.value = randomValue diff --git a/Tests/SentryTests/SentryCrash/SentryBinaryImageCacheTests.m b/Tests/SentryTests/SentryCrash/SentryCrashBinaryImageCacheTests.m similarity index 91% rename from Tests/SentryTests/SentryCrash/SentryBinaryImageCacheTests.m rename to Tests/SentryTests/SentryCrash/SentryCrashBinaryImageCacheTests.m index 1150b24dfca..f6da30e90f0 100644 --- a/Tests/SentryTests/SentryCrash/SentryBinaryImageCacheTests.m +++ b/Tests/SentryTests/SentryCrash/SentryCrashBinaryImageCacheTests.m @@ -1,7 +1,7 @@ -#import "SentryBinaryImageCache+Private.h" #import "SentryCrashBinaryImageCache.h" -#import "SentryCrashWrapper.h" +#import "SentryCrashDynamicLinker+Test.h" #import "SentryDependencyContainer.h" +#import "SentrySwift.h" #import #include @@ -85,6 +85,7 @@ + (void)setUp mach_headers_test_cache = [NSMutableArray array]; // Manually include dyld + sentrycrashdl_initialize(); [mach_headers_test_cache addObject:[NSValue valueWithPointer:sentryDyldHeader]]; _dyld_register_func_for_add_image(&cacheMachHeaders); } @@ -102,6 +103,7 @@ - (void)setUp - (void)tearDown { + sentrycrashdl_clearDyld(); sentry_resetFuncForAddRemoveImage(); sentrycrashbic_stopCache(); sentry_setFuncForBeforeAdd(NULL); @@ -110,7 +112,7 @@ - (void)tearDown - (void)testStartCache { - [[SentryCrashWrapper sharedInstance] startBinaryImageCache]; + [SentryDependencyContainer.sharedInstance.crashWrapper startBinaryImageCache]; [self assertBinaryImageCacheLength:5]; } @@ -233,16 +235,27 @@ - (void)testAddBinaryImageInParallel { sentrycrashbic_startCache(); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - dispatch_group_t group = dispatch_group_create(); + + // Guard against underflow when mach_headers_test_cache.count < 5 + // because otherwise the expectedFulfillmentCount for the test expectation will be negative. + NSInteger taskCount = mach_headers_test_cache.count - 5; + if (taskCount <= 0) { + XCTFail(@"Expected a positive task count, but got %ld", taskCount); + return; + } + + XCTestExpectation *expectation = + [self expectationWithDescription:@"Add binary images in parallel"]; + expectation.expectedFulfillmentCount = taskCount; for (NSUInteger i = 5; i < mach_headers_test_cache.count; i++) { - dispatch_group_enter(group); - dispatch_group_async(group, queue, ^{ + dispatch_async(queue, ^{ addBinaryImage([mach_headers_test_cache[i] pointerValue], 0); - dispatch_group_leave(group); + [expectation fulfill]; }); } - dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC)); + + [self waitForExpectations:@[ expectation ] timeout:5.0]; [self assertBinaryImageCacheLength:(int)mach_headers_test_cache.count]; } @@ -273,7 +286,7 @@ - (void)testSentryBinaryImageCacheIntegration sentrycrashbic_startCache(); SentryBinaryImageCache *imageCache = SentryDependencyContainer.sharedInstance.binaryImageCache; - [imageCache start]; + [imageCache start:false]; // by calling start, SentryBinaryImageCache will register a callback with // `SentryCrashBinaryImageCache` that should be called for every image already cached. XCTAssertEqual(5, imageCache.cache.count); diff --git a/Tests/SentryTests/SentryCrash/SentryCrashInstallationReporterTests.swift b/Tests/SentryTests/SentryCrash/SentryCrashInstallationReporterTests.swift index 03717b1f70f..10e71aaa692 100644 --- a/Tests/SentryTests/SentryCrash/SentryCrashInstallationReporterTests.swift +++ b/Tests/SentryTests/SentryCrash/SentryCrashInstallationReporterTests.swift @@ -14,6 +14,7 @@ class SentryCrashInstallationReporterTests: XCTestCase { sut.uninstall() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testReportIsSentAndDeleted() throws { givenSutWithStartedSDK() @@ -30,6 +31,7 @@ class SentryCrashInstallationReporterTests: XCTestCase { /** * Validates that handling a crash report with the removed fields total_storage and free_storage works. */ + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testShouldCaptureCrashReportWithLegacyStorageInfo() throws { givenSutWithStartedSDK() @@ -48,6 +50,7 @@ class SentryCrashInstallationReporterTests: XCTestCase { XCTAssertEqual(event?.context?["device"]?["storage_size"] as? Int, 994_662_584_320) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testShouldCaptureCrashReportWithoutDeviceContext() throws { givenSutWithStartedSDK() @@ -65,6 +68,7 @@ class SentryCrashInstallationReporterTests: XCTestCase { XCTAssertEqual(event?.context?["app"]?["app_name"] as? String, "iOS-Swift") } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testFaultyReportIsNotSentAndDeleted() throws { givenSutWithStartedSDK() @@ -78,6 +82,7 @@ class SentryCrashInstallationReporterTests: XCTestCase { XCTAssertEqual(sentrycrash_getReportCount(), 0) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") private func givenSutWithStartedSDK() { let options = Options() options.dsn = TestConstants.dsnAsString(username: "SentryCrashInstallationReporterTests") @@ -86,9 +91,9 @@ class SentryCrashInstallationReporterTests: XCTestCase { testClient = TestClient(options: options) let hub = SentryHub(client: testClient, andScope: nil) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) - sut = SentryCrashInstallationReporter(inAppLogic: SentryInAppLogic(inAppIncludes: [], inAppExcludes: []), crashWrapper: TestSentryCrashWrapper.sharedInstance(), dispatchQueue: TestSentryDispatchQueueWrapper()) + sut = SentryCrashInstallationReporter(inAppLogic: SentryInAppLogic(inAppIncludes: [], inAppExcludes: []), crashWrapper: TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo), dispatchQueue: TestSentryDispatchQueueWrapper()) sut.install(options.cacheDirectoryPath) // Works only if SentryCrash is installed sentrycrash_deleteAllReports() diff --git a/Tests/SentryTests/SentryCrash/SentryCrashInstallationTests.swift b/Tests/SentryTests/SentryCrash/SentryCrashInstallationTests.swift index fb7d9efe848..47327404a15 100644 --- a/Tests/SentryTests/SentryCrash/SentryCrashInstallationTests.swift +++ b/Tests/SentryTests/SentryCrash/SentryCrashInstallationTests.swift @@ -69,7 +69,7 @@ class SentryCrashInstallationTests: XCTestCase { crashHandlerDataAfterInstall: crashHandlerDataAfterInstall) #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) - XCTAssertEqual(55, notificationCenter.removeObserverWithNameInvocations.invocations.count) + XCTAssertEqual(55, notificationCenter.removeObserverWithNameAndObjectInvocations.invocations.count) #endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) } diff --git a/Tests/SentryTests/SentryCrash/SentryCrashReportSinkTests.swift b/Tests/SentryTests/SentryCrash/SentryCrashReportSinkTests.swift index 750e9c514c8..5f9fdff8f61 100644 --- a/Tests/SentryTests/SentryCrash/SentryCrashReportSinkTests.swift +++ b/Tests/SentryTests/SentryCrash/SentryCrashReportSinkTests.swift @@ -1,10 +1,11 @@ -@_spi(Private) import SentryTestUtils +@_spi(Private) import Sentry +@_spi(Private) @testable import SentryTestUtils import XCTest class SentryCrashReportSinkTests: SentrySDKIntegrationTestsBase { private class Fixture { - let crashWrapper = TestSentryCrashWrapper.sharedInstance() + let crashWrapper = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo) let dispatchQueue = TestSentryDispatchQueueWrapper() var sut: SentryCrashReportSink { @@ -32,7 +33,7 @@ class SentryCrashReportSinkTests: SentrySDKIntegrationTestsBase { } func testFilterReports_CopyHubScope() { - SentrySDK.currentHub().scope.setEnvironment("testFilterReports_CopyHubScope") + SentrySDKInternal.currentHub().scope.setEnvironment("testFilterReports_CopyHubScope") let expect = expectation(description: "Callback Called") @@ -122,7 +123,7 @@ class SentryCrashReportSinkTests: SentrySDKIntegrationTestsBase { } private func getTestClient() -> TestClient { - let client = SentrySDK.currentHub().getClient() as? TestClient + let client = SentrySDKInternal.currentHub().getClient() as? TestClient if client == nil { XCTFail("Hub Client is not a `TestClient`") diff --git a/Tests/SentryTests/SentryCrash/SentryCrashStackEntryMapperTests.swift b/Tests/SentryTests/SentryCrash/SentryCrashStackEntryMapperTests.swift index a6c6c575a60..c0d5a9b51c7 100644 --- a/Tests/SentryTests/SentryCrash/SentryCrashStackEntryMapperTests.swift +++ b/Tests/SentryTests/SentryCrash/SentryCrashStackEntryMapperTests.swift @@ -1,5 +1,5 @@ -@testable import Sentry -import SentryTestUtils +@_spi(Private) @testable import Sentry +@_spi(Private) import SentryTestUtils import XCTest /** Some of the test parameters are copied during debbuging a working implementation. @@ -71,7 +71,7 @@ class SentryCrashStackEntryMapperTests: XCTestCase { XCTAssertEqual(imageName, frame.package) } - func testImageAddress () { + func testImageAddress() { var cursor = SentryCrashStackCursor() cursor.stackEntry.imageAddress = 2_488_998_912 @@ -86,9 +86,13 @@ class SentryCrashStackEntryMapperTests: XCTestCase { } func testImageFromCache() { - var image = createCrashBinaryImage(2_488_998_912) - SentryDependencyContainer.sharedInstance().binaryImageCache.start() - SentryDependencyContainer.sharedInstance().binaryImageCache.binaryImageAdded(&image) + let image = createCrashBinaryImage(2_488_998_912) + SentryDependencyContainer.sharedInstance().binaryImageCache.start(false) + SentryDependencyContainer.sharedInstance().binaryImageCache.binaryImageAdded(imageName: image.name, + vmAddress: image.vmAddress, + address: image.address, + size: image.size, + uuid: image.uuid) var cursor = SentryCrashStackCursor() cursor.stackEntry.address = 2_488_998_950 diff --git a/Tests/SentryTests/SentryCrash/SentryCrashWrapperTests.swift b/Tests/SentryTests/SentryCrash/SentryCrashWrapperTests.swift new file mode 100644 index 00000000000..679797f2f16 --- /dev/null +++ b/Tests/SentryTests/SentryCrash/SentryCrashWrapperTests.swift @@ -0,0 +1,137 @@ +@_spi(Private) @testable import Sentry +import XCTest + +final class SentryCrashWrapperTests: XCTestCase { + + private var crashWrapper: SentryCrashWrapper! + private var scope: Scope! + + override func setUp() { + super.setUp() + crashWrapper = SentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo, + systemInfo: [ + "osVersion": "23A344", + "kernelVersion": "23.0.0", + "isJailbroken": false, + "systemName": "iOS", + "cpuArchitecture": "arm64", + "machine": "iPhone14,2", + "model": "iPhone 13 Pro", + "freeMemorySize": UInt64(1_073_741_824), // 1 GB + "usableMemorySize": UInt64(4_294_967_296), // 4 GB + "memorySize": UInt64(6_442_450_944), // 6 GB + "appStartTime": "2023-01-01T12:00:00Z", + "deviceAppHash": "abc123", + "appID": "12345", + "buildType": "debug", + "CFBundleIdentifier": "io.sentry.crashTest", + "CFBundleName": "CrashSentry", + "CFBundleVersion": "201702072010", + "CFBundleShortVersionString": "1.4.1" + ]) + scope = Scope() + +#if (os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !targetEnvironment(macCatalyst) + // Ensure DeviceWrapper info is initialized + // This is done at SentrySDKInteral, but during tests that might not be the case + Dependencies.uiDeviceWrapper.start() +#endif + } + + override func tearDown() { + crashWrapper = nil + scope = nil + super.tearDown() + } + + func testEnrichScope_WithSystemInfo_SetsOSContext() throws { + crashWrapper.enrichScope(scope) + + let osContext = try XCTUnwrap(scope.contextDictionary["os"] as? [String: Any]) + XCTAssertNotNil(osContext["name"]) + +#if os(macOS) || targetEnvironment(macCatalyst) + let version = ProcessInfo.processInfo.operatingSystemVersion + let expectedVersion = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)" + XCTAssertEqual(osContext["version"] as? String, expectedVersion) +#else + let expectedVersion = try XCTUnwrap(Dependencies.uiDeviceWrapper.getSystemVersion()) + XCTAssertFalse(expectedVersion.isEmpty) + XCTAssertEqual(osContext["version"] as? String, expectedVersion) +#endif + + XCTAssertEqual(osContext["build"] as? String, "23A344") + XCTAssertEqual(osContext["kernel_version"] as? String, "23.0.0") + XCTAssertEqual(osContext["rooted"] as? Bool, false) + } + + func testEnrichScope_WithSystemInfo_SetsDeviceContext() throws { + crashWrapper.enrichScope(scope) + + let deviceContext = try XCTUnwrap(scope.contextDictionary["device"] as? [String: Any]) + XCTAssertEqual(deviceContext["arch"] as? String, "arm64") + XCTAssertEqual(deviceContext["model"] as? String, "iPhone14,2") + XCTAssertEqual(deviceContext["model_id"] as? String, "iPhone 13 Pro") + XCTAssertEqual(deviceContext["free_memory"] as? UInt64, 1_073_741_824) + XCTAssertEqual(deviceContext["usable_memory"] as? UInt64, 4_294_967_296) + XCTAssertEqual(deviceContext["memory_size"] as? UInt64, 6_442_450_944) + XCTAssertNotNil(deviceContext["locale"]) + } + + func testEnrichScope_WithSystemInfo_SetsAppContext() throws { + crashWrapper.enrichScope(scope) + + let appContext = try XCTUnwrap(scope.contextDictionary["app"] as? [String: Any]) + XCTAssertEqual(appContext["app_start_time"] as? String, "2023-01-01T12:00:00Z") + XCTAssertEqual(appContext["device_app_hash"] as? String, "abc123") + XCTAssertEqual(appContext["app_id"] as? String, "12345") + XCTAssertEqual(appContext["build_type"] as? String, "debug") + + // App info from Bundle should also be present + let infoDict = Bundle.main.infoDictionary ?? [:] + XCTAssertEqual(appContext["app_identifier"] as? String, infoDict["CFBundleIdentifier"] as? String) + XCTAssertEqual(appContext["app_name"] as? String, infoDict["CFBundleName"] as? String) + XCTAssertEqual(appContext["app_build"] as? String, infoDict["CFBundleVersion"] as? String) + XCTAssertEqual(appContext["app_version"] as? String, infoDict["CFBundleShortVersionString"] as? String) + } + + func testEnrichScope_DeviceContext_ContainsSimulatorFlag() throws { + crashWrapper.enrichScope(scope) + + let deviceContext = try XCTUnwrap(scope.contextDictionary["device"] as? [String: Any]) + let simulator = deviceContext["simulator"] as? Bool + + XCTAssertNotNil(simulator) + // Should be true for simulator builds, false for device builds + #if targetEnvironment(simulator) + XCTAssertTrue(simulator!) + #else + XCTAssertFalse(simulator!) + #endif + } + + func testEnrichScope_DeviceContext_ContainsDeviceFamily() throws { + crashWrapper.enrichScope(scope) + + let deviceContext = try XCTUnwrap(scope.contextDictionary["device"] as? [String: Any]) + let family = deviceContext["family"] as? String + + #if targetEnvironment(macCatalyst) + XCTAssertEqual(family, "macOS") + #else + XCTAssertEqual(family, "iOS") + #endif + } + + func testEnrichScope_RuntimeContext_MacCatalyst() throws { + if #available(iOS 13.0, macOS 10.15, watchOS 6.0, tvOS 13.0, *) { + #if targetEnvironment(macCatalyst) + crashWrapper.enrichScope(scope) + + let runtimeContext = try XCTUnwrap(scope.contextDictionary["runtime"] as? [String: Any]) + XCTAssertEqual(runtimeContext["name"] as? String, "Mac Catalyst App") + XCTAssertEqual(runtimeContext["raw_description"] as? String, "raw_description") + #endif + } + } +} diff --git a/Tests/SentryTests/SentryCrash/SentryDebugImageProviderTests.swift b/Tests/SentryTests/SentryCrash/SentryDebugImageProviderTests.swift index 9c8d33eb0b7..631f9a4a463 100644 --- a/Tests/SentryTests/SentryCrash/SentryDebugImageProviderTests.swift +++ b/Tests/SentryTests/SentryCrash/SentryDebugImageProviderTests.swift @@ -1,4 +1,5 @@ -@testable import Sentry +@_spi(Private) @testable import Sentry +@_spi(Private) @testable import SentryTestUtils import XCTest /** @@ -20,10 +21,13 @@ class SentryDebugImageProviderTests: XCTestCase { imageProvider.imageCount = images.count imageProvider.binaryImage = images - cache.start() + cache.start(false) for image in images { - var i = image - cache.binaryImageAdded(&i) + cache.binaryImageAdded(imageName: image.name, + vmAddress: image.vmAddress, + address: image.address, + size: image.size, + uuid: image.uuid) } return SentryDebugImageProvider(binaryImageProvider: imageProvider, binaryImageCache: cache) diff --git a/Tests/SentryTests/SentryCrash/SentryInAppLogicTests.swift b/Tests/SentryTests/SentryCrash/SentryInAppLogicTests.swift index c760c6840c0..1631c6697d3 100644 --- a/Tests/SentryTests/SentryCrash/SentryInAppLogicTests.swift +++ b/Tests/SentryTests/SentryCrash/SentryInAppLogicTests.swift @@ -1,3 +1,4 @@ +@_spi(Private) import Sentry import XCTest class SentryInAppLogicTests: XCTestCase { diff --git a/Tests/SentryTests/SentryCrash/SentryStacktraceBuilderTests.swift b/Tests/SentryTests/SentryCrash/SentryStacktraceBuilderTests.swift index c102ac6da7b..b4e938002b6 100644 --- a/Tests/SentryTests/SentryCrash/SentryStacktraceBuilderTests.swift +++ b/Tests/SentryTests/SentryCrash/SentryStacktraceBuilderTests.swift @@ -1,4 +1,4 @@ -@testable import Sentry +@_spi(Private) @testable import Sentry import SentryTestUtils import XCTest @@ -78,6 +78,7 @@ class SentryStacktraceBuilderTests: XCTestCase { XCTAssertTrue(filteredFrames.count == 1, "The frames must be ordered from caller to callee, or oldest to youngest.") } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testConcurrentStacktraces() throws { guard #available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) else { throw XCTSkip("Not available for earlier platform versions") @@ -97,17 +98,11 @@ class SentryStacktraceBuilderTests: XCTestCase { waitForAsyncToRun.fulfill() XCTAssertGreaterThanOrEqual(filteredFrames, 3, "The Stacktrace must include the async callers.") } - - var timeout: TimeInterval = 1 - #if !os(watchOS) && !os(tvOS) - // observed the async task taking a long time to finish if TSAN is attached - if sentry_threadSanitizerIsPresent() { - timeout = 10 - } - #endif // !os(watchOS) || !os(tvOS) - wait(for: [waitForAsyncToRun], timeout: timeout) + + wait(for: [waitForAsyncToRun], timeout: 10) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testConcurrentStacktraces_noStitching() throws { guard #available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) else { throw XCTSkip("Not available for earlier platform versions") @@ -127,15 +122,8 @@ class SentryStacktraceBuilderTests: XCTestCase { waitForAsyncToRun.fulfill() XCTAssertGreaterThanOrEqual(filteredFrames, 1, "The Stacktrace must have only one function.") } - - var timeout: TimeInterval = 1 - #if !os(watchOS) && !os(tvOS) - // observed the async task taking a long time to finish if TSAN is attached - if sentry_threadSanitizerIsPresent() { - timeout = 10 - } - #endif // !os(watchOS) || !os(tvOS) - wait(for: [waitForAsyncToRun], timeout: timeout) + + wait(for: [waitForAsyncToRun], timeout: 10) } @available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *) diff --git a/Tests/SentryTests/SentryCrash/SentryThreadInspectorTests.swift b/Tests/SentryTests/SentryCrash/SentryThreadInspectorTests.swift index 3bc91d1059d..34ddd503f69 100644 --- a/Tests/SentryTests/SentryCrash/SentryThreadInspectorTests.swift +++ b/Tests/SentryTests/SentryCrash/SentryThreadInspectorTests.swift @@ -1,3 +1,4 @@ +@_spi(Private) @testable import Sentry import SentryTestUtils import XCTest @@ -54,32 +55,55 @@ class SentryThreadInspectorTests: XCTestCase { expect.expectedFulfillmentCount = 10 let sut = self.fixture.getSut(testWithRealMachineContextWrapper: true) + for _ in 0..<10 { - + queue.async { - let actual = sut.getCurrentThreadsWithStackTrace() - - // Sometimes during tests its possible to have one thread without frames - // We just need to make sure we retrieve frame information for at least one other thread than the main thread - var threadsWithFrames = 0 - - for thr in actual { - if (thr.stacktrace?.frames.count ?? 0) >= 1 { - threadsWithFrames += 1 + let threads = sut.getCurrentThreadsWithStackTrace() + + if threads.count == 0 { + // If there are more than 70 threads getCurrentThreadsWithStackTrace + // returns an empty list because it can't handle so many threads. + // This is a known limitation SentryThreadInspector and should be + // addressed in https://github.com/getsentry/sentry-cocoa/issues/2825. + // We see this sometimes happening in CI. + expect.fulfill() + return + } + + var threadsWithStackTraceFrames = 0 + + for thread in threads { + + guard let frames = thread.stacktrace?.frames else { + continue } - - for frame in thr.stacktrace?.frames ?? [] { + + if frames.count == 0 { + continue + } + + for frame in frames { XCTAssertNotNil(frame.instructionAddress) XCTAssertNotNil(frame.imageAddress) + } + + threadsWithStackTraceFrames += 1 } - - XCTAssertTrue(threadsWithFrames > 1, "Not enough threads with frames") - + + let percantageWithStacktraceFrames = Double(threadsWithStackTraceFrames) / Double(threads.count) + + // During testing we usually have around 90% to 100% + // We choose a bit lower threshold to avoid flaky tests in CI + // Especially during the test when launching multiple threads for the concurrent DispatchQueue + // it can occur that more than one thread have no stacktrace frames yet, because they just started. + XCTAssertGreaterThan(percantageWithStacktraceFrames, 0.6, "More than 60% of threads should have stacktrace frames, but got \(percantageWithStacktraceFrames * 100)%") + expect.fulfill() } } - + queue.activate() wait(for: [expect], timeout: 10) } @@ -91,34 +115,55 @@ class SentryThreadInspectorTests: XCTestCase { expect.expectedFulfillmentCount = 10 let sut = self.fixture.getSut(testWithRealMachineContextWrapper: true, symbolicate: false) - + for _ in 0..<10 { queue.async { - let actual = sut.getCurrentThreadsWithStackTrace() - - // Sometimes during tests its possible to have one thread without frames - // We just need to make sure we retrieve frame information for at least one other thread than the main thread - var threadsWithFrames = 0 - - for thr in actual { - if (thr.stacktrace?.frames.count ?? 0) >= 1 { - threadsWithFrames += 1 + let threads = sut.getCurrentThreadsWithStackTrace() + + if threads.count == 0 { + // If there are more than 70 threads getCurrentThreadsWithStackTrace + // returns an empty list because it can't handle so many threads. + // This is a known limitation SentryThreadInspector and should be + // addressed in https://github.com/getsentry/sentry-cocoa/issues/2825. + // We see this sometimes happening in CI. + expect.fulfill() + return + } + + var threadsWithStackTraceFrames = 0 + + for thread in threads { + + guard let frames = thread.stacktrace?.frames else { + continue } - - for frame in thr.stacktrace?.frames ?? [] { + + if frames.count == 0 { + continue + } + + for frame in frames { XCTAssertNotNil(frame.instructionAddress) XCTAssertNotNil(frame.imageAddress) XCTAssertNil(frame.symbolAddress) } + + threadsWithStackTraceFrames += 1 } - - XCTAssertTrue(threadsWithFrames > 1, "Not enough threads with frames") - + + let percantageWithStacktraceFrames = Double(threadsWithStackTraceFrames) / Double(threads.count) + + // During testing we usually have around 90% to 100% + // We choose a bit lower threshold to avoid flaky tests in CI + // Especially during the test when launching multiple threads for the concurrent DispatchQueue + // it can occur that more than one thread have no stacktrace frames yet, because they just started. + XCTAssertGreaterThan(percantageWithStacktraceFrames, 0.6, "More than 60% of threads should have stacktrace frames, but got \(percantageWithStacktraceFrames * 100)%") + expect.fulfill() } } - + queue.activate() wait(for: [expect], timeout: 10) } diff --git a/Tests/SentryTests/SentryCrash/SentryUIDeviceWrapperTests.swift b/Tests/SentryTests/SentryCrash/SentryUIDeviceWrapperTests.swift index 1aaf1b2ea29..fdb841ecc2e 100644 --- a/Tests/SentryTests/SentryCrash/SentryUIDeviceWrapperTests.swift +++ b/Tests/SentryTests/SentryCrash/SentryUIDeviceWrapperTests.swift @@ -1,3 +1,4 @@ +@_spi(Private) @testable import Sentry @_spi(Private) import SentryTestUtils import XCTest @@ -10,13 +11,40 @@ class SentryUIDeviceWrapperTests: XCTestCase { func testExecutesLogicViaDispatchQueue() { let dispatchQueue = TestSentryDispatchQueueWrapper() - SentryDependencyContainer.sharedInstance().dispatchQueueWrapper = dispatchQueue - let sut = SentryUIDeviceWrapper() + let sut = SentryDefaultUIDeviceWrapper(queueWrapper: dispatchQueue) sut.start() XCTAssertEqual(dispatchQueue.blockOnMainInvocations.count, 1) sut.stop() XCTAssertEqual(dispatchQueue.blockOnMainInvocations.count, 2) } + + func testGetsSystemVersion() { + let dispatchQueue = TestSentryDispatchQueueWrapper() + let sut = SentryDefaultUIDeviceWrapper(queueWrapper: dispatchQueue) + XCTAssertNotNil(sut.getSystemVersion()) + } + + func testBatteryLevel() { + let dispatchQueue = TestSentryDispatchQueueWrapper() + let sut = SentryDefaultUIDeviceWrapper(queueWrapper: dispatchQueue) + XCTAssertNotNil(sut.batteryLevel) + } + + func testBatteryState() { + let dispatchQueue = TestSentryDispatchQueueWrapper() + let sut = SentryDefaultUIDeviceWrapper(queueWrapper: dispatchQueue) + XCTAssertNotNil(sut.batteryState) + } + + func testCleansUp() { + let dispatchQueue = TestSentryDispatchQueueWrapper() + autoreleasepool { + let sut = SentryDefaultUIDeviceWrapper(queueWrapper: dispatchQueue) + sut.start() + XCTAssertEqual(dispatchQueue.blockOnMainInvocations.count, 1) + } + XCTAssertEqual(dispatchQueue.blockOnMainInvocations.count, 2) + } } #endif diff --git a/Tests/SentryTests/SentryCrash/TestSentryCrashWrapper.h b/Tests/SentryTests/SentryCrash/TestSentryCrashWrapper.h deleted file mode 100644 index 499ba9822ea..00000000000 --- a/Tests/SentryTests/SentryCrash/TestSentryCrashWrapper.h +++ /dev/null @@ -1,42 +0,0 @@ -#import "SentryCrashWrapper.h" -#import "SentryDefines.h" -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - * Written in Objective-C because Swift doesn't allow you to call the constructor of - * TestSentryCrashAdapter. We override sharedInstance in the implementation file to make it work. - */ -@interface TestSentryCrashWrapper : SentryCrashWrapper -SENTRY_NO_INIT - -@property (nonatomic, assign) BOOL internalCrashedLastLaunch; - -@property (nonatomic, assign) NSTimeInterval internalDurationFromCrashStateInitToLastCrash; - -@property (nonatomic, assign) NSTimeInterval internalActiveDurationSinceLastCrash; - -@property (nonatomic, assign) BOOL internalIsBeingTraced; - -@property (nonatomic, assign) BOOL internalIsSimulatorBuild; - -@property (nonatomic, assign) BOOL internalIsApplicationInForeground; - -@property (nonatomic, assign) BOOL installAsyncHooksCalled; - -@property (nonatomic, assign) BOOL uninstallAsyncHooksCalled; - -@property (nonatomic, assign) uint64_t internalFreeMemorySize; - -@property (nonatomic, assign) uint64_t internalAppMemorySize; - -@property (nonatomic) BOOL binaryCacheStarted; - -@property (nonatomic) BOOL binaryCacheStopped; - -@property (nonatomic) BOOL enrichScopeCalled; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tests/SentryTests/SentryCrash/TestSentryCrashWrapper.m b/Tests/SentryTests/SentryCrash/TestSentryCrashWrapper.m deleted file mode 100644 index a8a1db92188..00000000000 --- a/Tests/SentryTests/SentryCrash/TestSentryCrashWrapper.m +++ /dev/null @@ -1,97 +0,0 @@ -#import "TestSentryCrashWrapper.h" -#import "SentryCrash.h" -#import - -@implementation TestSentryCrashWrapper - -+ (instancetype)sharedInstance -{ - TestSentryCrashWrapper *instance = [[self alloc] init]; - instance.internalActiveDurationSinceLastCrash = NO; - instance.internalDurationFromCrashStateInitToLastCrash = 0; - instance.internalActiveDurationSinceLastCrash = 0; - instance.internalIsBeingTraced = NO; - instance.internalIsSimulatorBuild = NO; - instance.internalIsApplicationInForeground = YES; - instance.installAsyncHooksCalled = NO; - instance.uninstallAsyncHooksCalled = NO; - instance.internalFreeMemorySize = 0; - instance.internalAppMemorySize = 0; - instance.enrichScopeCalled = NO; - return instance; -} - -- (void)startBinaryImageCache -{ - _binaryCacheStarted = YES; - [super startBinaryImageCache]; -} - -- (void)stopBinaryImageCache -{ - [super stopBinaryImageCache]; - _binaryCacheStopped = YES; -} - -- (BOOL)crashedLastLaunch -{ - return self.internalCrashedLastLaunch; -} - -- (NSTimeInterval)durationFromCrashStateInitToLastCrash -{ - return self.internalDurationFromCrashStateInitToLastCrash; -} - -- (NSTimeInterval)activeDurationSinceLastCrash -{ - return self.internalActiveDurationSinceLastCrash; -} - -- (BOOL)isBeingTraced -{ - return self.internalIsBeingTraced; -} - -- (BOOL)isSimulatorBuild -{ - return self.internalIsSimulatorBuild; -} - -- (BOOL)isApplicationInForeground -{ - return self.internalIsApplicationInForeground; -} - -- (void)installAsyncHooks -{ - self.installAsyncHooksCalled = YES; -} - -- (void)uninstallAsyncHooks -{ - self.uninstallAsyncHooksCalled = YES; -} - -- (NSDictionary *)systemInfo -{ - return @{}; -} - -- (bytes)freeMemorySize -{ - return self.internalFreeMemorySize; -} - -- (bytes)appMemorySize -{ - return self.internalAppMemorySize; -} - -- (void)enrichScope:(SentryScope *)scope -{ - self.enrichScopeCalled = YES; - [super enrichScope:scope]; -} - -@end diff --git a/Tests/SentryTests/SentryCrash/TestSentryCrashWrapper.swift b/Tests/SentryTests/SentryCrash/TestSentryCrashWrapper.swift index 8cf93ac639f..e3f02b983b1 100644 --- a/Tests/SentryTests/SentryCrash/TestSentryCrashWrapper.swift +++ b/Tests/SentryTests/SentryCrash/TestSentryCrashWrapper.swift @@ -1,19 +1,75 @@ import Foundation +@_spi(Private) @testable import Sentry -class TestSentryCrashWrapper: SentryCrashAdapter { +/** + * This is a test wrapper around SentryCrashWrapper for testing purposes. + */ +class TestSentryCrashWrapper: SentryCrashWrapper { + + // MARK: - Test Properties var internalCrashedLastLaunch = false - override func crashedLastLaunch() -> Bool { + var internalDurationFromCrashStateInitToLastCrash: TimeInterval = 0 + var internalActiveDurationSinceLastCrash: TimeInterval = 0 + var internalIsBeingTraced = false + var internalIsSimulatorBuild = false + var internalIsApplicationInForeground = true + var internalFreeMemorySize: UInt64 = 0 + var internalAppMemorySize: UInt64 = 0 + var binaryCacheStarted = false + var binaryCacheStopped = false + var enrichScopeCalled = false + + // MARK: - Overridden Methods + + override func startBinaryImageCache() { + binaryCacheStarted = true + super.startBinaryImageCache() + } + + override func stopBinaryImageCache() { + super.stopBinaryImageCache() + binaryCacheStopped = true + } + + override var crashedLastLaunch: Bool { return internalCrashedLastLaunch } - var internalActiveDurationSinceLastCrash: TimeInterval = 0 - override func activeDurationSinceLastCrash() -> TimeInterval { + override var durationFromCrashStateInitToLastCrash: TimeInterval { + return internalDurationFromCrashStateInitToLastCrash + } + + override var activeDurationSinceLastCrash: TimeInterval { return internalActiveDurationSinceLastCrash } - var internalIsBeingTraced = false - override func isBeingTraced() -> Bool { + override var isBeingTraced: Bool { return internalIsBeingTraced } + + override var isSimulatorBuild: Bool { + return internalIsSimulatorBuild + } + + override var isApplicationInForeground: Bool { + return internalIsApplicationInForeground + } + + override var systemInfo: [String: Any] { + return [:] + } + + override var freeMemorySize: UInt64 { + return internalFreeMemorySize + } + + override var appMemorySize: UInt64 { + return internalAppMemorySize + } + + override func enrichScope(_ scope: Scope) { + enrichScopeCalled = true + super.enrichScope(scope) + } } diff --git a/Tests/SentryTests/SentryCrash/TestSentryUIDeviceWrapper.swift b/Tests/SentryTests/SentryCrash/TestSentryUIDeviceWrapper.swift index d834a593299..c80908cfbb1 100644 --- a/Tests/SentryTests/SentryCrash/TestSentryUIDeviceWrapper.swift +++ b/Tests/SentryTests/SentryCrash/TestSentryUIDeviceWrapper.swift @@ -2,33 +2,38 @@ import Sentry #if os(iOS) || targetEnvironment(macCatalyst) class TestSentryUIDeviceWrapper: SentryUIDeviceWrapper { + var internalOrientation = UIDeviceOrientation.portrait var internalIsBatteryMonitoringEnabled = true var internalBatteryLevel: Float = 0.6 var internalBatteryState = UIDevice.BatteryState.charging var started = false - override func start() { + func start() { started = true } - override func stop() { + func stop() { started = false } - override func orientation() -> UIDeviceOrientation { + var orientation: UIDeviceOrientation { return internalOrientation } - override func isBatteryMonitoringEnabled() -> Bool { + var isBatteryMonitoringEnabled: Bool { return internalIsBatteryMonitoringEnabled } - override func batteryLevel() -> Float { + var batteryLevel: Float { return internalBatteryLevel } - override func batteryState() -> UIDevice.BatteryState { + var batteryState: UIDevice.BatteryState { return internalBatteryState } + + func getSystemVersion() -> String { + "" + } } #endif // os(iOS) || targetEnvironment(macCatalyst) diff --git a/Tests/SentryTests/SentryCrash/TestThreadInspector.swift b/Tests/SentryTests/SentryCrash/TestThreadInspector.swift index f177d7feef0..81edc91df55 100644 --- a/Tests/SentryTests/SentryCrash/TestThreadInspector.swift +++ b/Tests/SentryTests/SentryCrash/TestThreadInspector.swift @@ -1,4 +1,5 @@ import Foundation +@_spi(Private) import Sentry class TestThreadInspector: SentryThreadInspector { diff --git a/Tests/SentryTests/SentryCrashExceptionApplicationTests.swift b/Tests/SentryTests/SentryCrashExceptionApplicationTests.swift index f7f8cae79bf..74ceeccfaad 100644 --- a/Tests/SentryTests/SentryCrashExceptionApplicationTests.swift +++ b/Tests/SentryTests/SentryCrashExceptionApplicationTests.swift @@ -18,14 +18,14 @@ class SentryCrashExceptionApplicationHelperTests: XCTestCase { // Arrange let client = TestClient(options: Options()) let hub = TestHub(client: client, andScope: nil) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setCurrentHub(hub) let exception = NSException(name: NSExceptionName("TestException"), reason: "Test Reason", userInfo: nil) // Act SentryCrashExceptionApplicationHelper._crash(on: exception) // Assert - let testClient = try XCTUnwrap(SentrySDK.currentHub().getClient() as? TestClient) + let testClient = try XCTUnwrap(SentrySDKInternal.currentHub().getClient() as? TestClient) XCTAssertEqual(1, testClient.captureExceptionWithScopeInvocations.count) XCTAssertEqual(exception.name, testClient.captureExceptionWithScopeInvocations.first?.exception.name) XCTAssertEqual(exception.reason, testClient.captureExceptionWithScopeInvocations.first?.exception.reason) diff --git a/Tests/SentryTests/SentryHubTests.swift b/Tests/SentryTests/SentryHubTests.swift index aa1e9cbb652..69020030b5a 100644 --- a/Tests/SentryTests/SentryHubTests.swift +++ b/Tests/SentryTests/SentryHubTests.swift @@ -17,7 +17,7 @@ class SentryHubTests: XCTestCase { let message = "some message" let event: Event let currentDateProvider = TestCurrentDateProvider() - let sentryCrashWrapper = TestSentryCrashWrapper.sharedInstance() + let sentryCrashWrapper = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo) let fileManager: SentryFileManager let crashedSession: SentrySession let abnormalSession: SentrySession @@ -37,11 +37,15 @@ class SentryHubTests: XCTestCase { event = Event() event.message = SentryMessage(formatted: message) - fileManager = try! SentryFileManager(options: options, dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) - + fileManager = try! TestFileManager( + options: options, + dateProvider: currentDateProvider, + dispatchQueueWrapper: TestSentryDispatchQueueWrapper() + ) + SentryDependencyContainer.sharedInstance().dateProvider = currentDateProvider SentryDependencyContainer.sharedInstance().random = random - + crashedSession = SentrySession(releaseName: "1.0.0", distinctId: "") crashedSession.endCrashed(withTimestamp: currentDateProvider.date()) crashedSession.environment = options.environment @@ -187,7 +191,56 @@ class SentryHubTests: XCTestCase { XCTAssertNotNil(hub.scope.contextDictionary["device"]) XCTAssertNotNil(hub.scope.contextDictionary["app"]) } - + + func testScopeEnriched_WithNoRuntime() throws { + // Arrange + let processInfoWrapper = MockSentryProcessInfo() + processInfoWrapper.overrides.isiOSAppOnMac = false + processInfoWrapper.overrides.isMacCatalystApp = false + let crashWrapper = SentryCrashWrapper(processInfoWrapper: processInfoWrapper) + + // Act + let hub = SentryHub(client: nil, andScope: Scope(), andCrashWrapper: crashWrapper, andDispatchQueue: TestSentryDispatchQueueWrapper()) + + // Assert + XCTAssertNil(hub.scope.contextDictionary["runtime"]) + } + + func testScopeEnriched_WithRuntime_isiOSAppOnMac() throws { + // Arrange + let processInfoWrapper = MockSentryProcessInfo() + processInfoWrapper.overrides.isiOSAppOnMac = true + processInfoWrapper.overrides.isMacCatalystApp = false + SentryDependencyContainer.sharedInstance().processInfoWrapper = processInfoWrapper + let crashWrapper = SentryCrashWrapper(processInfoWrapper: processInfoWrapper) + + // Act + let hub = SentryHub(client: nil, andScope: Scope(), andCrashWrapper: crashWrapper, andDispatchQueue: TestSentryDispatchQueueWrapper()) + + // Assert + let runtimeContext = try XCTUnwrap (hub.scope.contextDictionary["runtime"] as? [String: String]) + + XCTAssertEqual(runtimeContext["name"], "iOS App on Mac") + XCTAssertEqual(runtimeContext["raw_description"], "ios-app-on-mac") + } + + func testScopeEnriched_WithRuntime_isMacCatalystApp() throws { + // Arrange + let processInfoWrapper = MockSentryProcessInfo() + processInfoWrapper.overrides.isiOSAppOnMac = false + processInfoWrapper.overrides.isMacCatalystApp = true + SentryDependencyContainer.sharedInstance().processInfoWrapper = processInfoWrapper + let crashWrapper = SentryCrashWrapper(processInfoWrapper: processInfoWrapper) + + // Act + let hub = SentryHub(client: nil, andScope: Scope(), andCrashWrapper: crashWrapper, andDispatchQueue: TestSentryDispatchQueueWrapper()) + + // Assert + let runtimeContext = try XCTUnwrap (hub.scope.contextDictionary["runtime"] as? [String: String]) + XCTAssertEqual(runtimeContext["name"], "Mac Catalyst App") + XCTAssertEqual(runtimeContext["raw_description"], "raw_description") + } + func testScopeNotEnriched_WhenScopeIsNil() { _ = fixture.getSut() @@ -222,7 +275,11 @@ class SentryHubTests: XCTestCase { } func testAddUserToTheScope() throws { - let client = SentryClient(options: fixture.options, fileManager: try TestFileManager(options: fixture.options), deleteOldEnvelopeItems: false) + let client = SentryClient( + options: fixture.options, + fileManager: fixture.fileManager, + deleteOldEnvelopeItems: false + ) let hub = SentryHub(client: client, andScope: Scope()) let user = User() @@ -1008,6 +1065,7 @@ class SentryHubTests: XCTestCase { } #endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCaptureEnvelope_WithEventWithError() throws { sut.startSession() @@ -1016,6 +1074,7 @@ class SentryHubTests: XCTestCase { try assertSessionWithIncrementedErrorCountedAdded() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCaptureEnvelope_WithEventWithoutExceptionMechanism() throws { sut.startSession() @@ -1024,6 +1083,7 @@ class SentryHubTests: XCTestCase { try assertSessionWithIncrementedErrorCountedAdded() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCaptureEnvelope_WithEventWithFatal() throws { sut.startSession() @@ -1032,6 +1092,7 @@ class SentryHubTests: XCTestCase { try assertSessionWithIncrementedErrorCountedAdded() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCaptureEnvelope_WithEventWithNoLevel() throws { sut.startSession() @@ -1043,6 +1104,7 @@ class SentryHubTests: XCTestCase { try assertSessionWithIncrementedErrorCountedAdded() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCaptureEnvelope_WithEventWithGarbageLevel() throws { sut.startSession() @@ -1054,12 +1116,14 @@ class SentryHubTests: XCTestCase { try assertSessionWithIncrementedErrorCountedAdded() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCaptureEnvelope_WithEventWithFatal_SessionNotStarted() { captureEventEnvelope(level: SentryLevel.fatal) assertNoSessionAddedToCapturedEnvelope() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCaptureEnvelope_WithEventWithWarning() { sut.startSession() @@ -1068,6 +1132,7 @@ class SentryHubTests: XCTestCase { assertNoSessionAddedToCapturedEnvelope() } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCaptureEnvelope_WithClientNil() { sut.bindClient(nil) captureEventEnvelope(level: SentryLevel.warning) @@ -1103,6 +1168,7 @@ class SentryHubTests: XCTestCase { XCTAssertEqual(mockClient?.scope, sut.scope) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCaptureEnvelope_WithSession() { let envelope = SentryEnvelope(session: SentrySession(releaseName: "", distinctId: "")) sut.capture(envelope) @@ -1111,6 +1177,7 @@ class SentryHubTests: XCTestCase { XCTAssertEqual(envelope, fixture.client.captureEnvelopeInvocations.first) } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCaptureEnvelope_WithUnhandledException() throws { sut.startSession() @@ -1126,12 +1193,13 @@ class SentryHubTests: XCTestCase { let envelope = fixture.client.captureEnvelopeInvocations.first let sessionEnvelopeItem = envelope?.items.first(where: { $0.header.type == "session" }) - let json = try XCTUnwrap((try! JSONSerialization.jsonObject(with: sessionEnvelopeItem!.data)) as? [String: Any]) + let json = try XCTUnwrap((try! JSONSerialization.jsonObject(with: XCTUnwrap(sessionEnvelopeItem?.data))) as? [String: Any]) XCTAssertEqual(json["timestamp"] as? String, "1970-01-01T00:00:02.000Z") XCTAssertEqual(json["status"] as? String, "crashed") } + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") func testCaptureEnvelope_WithHandledException() { sut.startSession() @@ -1206,16 +1274,19 @@ class SentryHubTests: XCTestCase { sut.startSession() let queue = fixture.queue - let group = DispatchGroup() + + let expectation = XCTestExpectation(description: "Capture should be called \(count) times") + expectation.expectedFulfillmentCount = count + for _ in 0.. Void) throws -> SentryEnvelope { let event = TestData.event let envelopeItem = SentryEnvelopeItem(event: event) - var eventDict = try XCTUnwrap(JSONSerialization.jsonObject(with: envelopeItem.data) as? [String: Any]) + var eventDict = try XCTUnwrap(JSONSerialization.jsonObject(with: XCTUnwrap(envelopeItem.data)) as? [String: Any]) modifyEventDict(&eventDict) @@ -1434,7 +1512,7 @@ class SentryHubTests: XCTestCase { XCTAssertEqual(1, fixture.client.captureEnvelopeInvocations.count) let envelope = fixture.client.captureEnvelopeInvocations.first! XCTAssertEqual(2, envelope.items.count) - let session = SentrySerialization.session(with: try XCTUnwrap(envelope.items.element(at: 1)).data) + let session = SentrySerialization.session(with: try XCTUnwrap(XCTUnwrap(envelope.items.element(at: 1)).data)) XCTAssertEqual(1, session?.errors) } diff --git a/Tests/SentryTests/SentryKSCrashReportConverterTests.m b/Tests/SentryTests/SentryKSCrashReportConverterTests.m index 15f93db8349..9e9a2c251ce 100644 --- a/Tests/SentryTests/SentryKSCrashReportConverterTests.m +++ b/Tests/SentryTests/SentryKSCrashReportConverterTests.m @@ -5,10 +5,10 @@ #import "SentryEvent.h" #import "SentryException.h" #import "SentryFrame.h" -#import "SentryInAppLogic.h" #import "SentryMechanism.h" #import "SentryMechanismMeta.h" #import "SentryStacktrace.h" +#import "SentrySwift.h" #import "SentryThread.h" #import "SentryUser.h" #import diff --git a/Tests/SentryTests/SentryLogBatcherTests.swift b/Tests/SentryTests/SentryLogBatcherTests.swift new file mode 100644 index 00000000000..ec1ad446bd9 --- /dev/null +++ b/Tests/SentryTests/SentryLogBatcherTests.swift @@ -0,0 +1,330 @@ +@_spi(Private) @testable import Sentry +@_spi(Private) import SentryTestUtils +import XCTest + +final class SentryLogBatcherTests: XCTestCase { + + private var options: Options! + private var testClient: TestClient! + private var testDispatchQueue: TestSentryDispatchQueueWrapper! + private var sut: SentryLogBatcher! + private var scope: Scope! + + override func setUp() { + super.setUp() + + options = Options() + options.experimental.enableLogs = true + + testClient = TestClient(options: options) + testDispatchQueue = TestSentryDispatchQueueWrapper() + testDispatchQueue.dispatchAsyncExecutesBlock = true // Execute encoding immediately + + sut = SentryLogBatcher( + client: testClient, + flushTimeout: 0.1, // Very small timeout for testing + maxBufferSizeBytes: 500, // Small byte limit for testing + dispatchQueue: testDispatchQueue + ) + scope = Scope() + } + + override func tearDown() { + super.tearDown() + testClient = nil + testDispatchQueue = nil + sut = nil + scope = nil + } + + // MARK: - Basic Functionality Tests + + func testAddMultipleLogs_BatchesTogether() throws { + // Given + let log1 = createTestLog(body: "Log 1") + let log2 = createTestLog(body: "Log 2") + + // When + sut.add(log1) + sut.add(log2) + + // Then - no immediate flush since buffer not full + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 0) + + // Trigger flush manually + sut.captureLogs() + + // Verify both logs are batched together + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 1) + let sentData = try XCTUnwrap(testClient.captureLogsDataInvocations.first).data + let jsonObject = try XCTUnwrap(JSONSerialization.jsonObject(with: sentData) as? [String: Any]) + let items = try XCTUnwrap(jsonObject["items"] as? [[String: Any]]) + XCTAssertEqual(2, items.count) + } + + // MARK: - Buffer Size Tests + + func testBufferReachesMaxSize_FlushesImmediately() throws { + // Given - create a log that will exceed the 500 byte limit + let largeLogBody = String(repeating: "A", count: 600) // Larger than 500 byte limit + let largeLog = createTestLog(body: largeLogBody) + + // When - add a log that exceeds buffer size + sut.add(largeLog) + + // Then - should trigger immediate flush + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 1) + + // Verify the large log is sent + let sentData = try XCTUnwrap(testClient.captureLogsDataInvocations.first).data + let jsonObject = try XCTUnwrap(JSONSerialization.jsonObject(with: sentData) as? [String: Any]) + let items = try XCTUnwrap(jsonObject["items"] as? [[String: Any]]) + XCTAssertEqual(1, items.count) + XCTAssertEqual(largeLogBody, items[0]["body"] as? String) + } + + // MARK: - Timeout Tests + + func testTimeout_FlushesAfterDelay() throws { + // Given + let log = createTestLog() + + // When + sut.add(log) + + // Then - no immediate flush but timer should be started + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 0) + XCTAssertEqual(testDispatchQueue.dispatchAfterWorkItemInvocations.count, 1) + XCTAssertEqual(testDispatchQueue.dispatchAfterWorkItemInvocations.first?.interval, 0.1) + + // Manually trigger the timer to simulate timeout + testDispatchQueue.invokeLastDispatchAfterWorkItem() + + // Verify flush occurred + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 1) + let sentData = try XCTUnwrap(testClient.captureLogsDataInvocations.first).data + let jsonObject = try XCTUnwrap(JSONSerialization.jsonObject(with: sentData) as? [String: Any]) + let items = try XCTUnwrap(jsonObject["items"] as? [[String: Any]]) + XCTAssertEqual(1, items.count) + } + + func testAddingLogToEmptyBuffer_StartsTimer() throws { + // Given + let log1 = createTestLog(body: "Log 1") + let log2 = createTestLog(body: "Log 2") + + // When - add first log to empty buffer + sut.add(log1) + + // Then - timer should be started for first log + XCTAssertEqual(testDispatchQueue.dispatchAfterWorkItemInvocations.count, 1) + XCTAssertEqual(testDispatchQueue.dispatchAfterWorkItemInvocations.first?.interval, 0.1) + + // When - add second log to non-empty buffer + sut.add(log2) + + // Then - no additional timer should be started + XCTAssertEqual(testDispatchQueue.dispatchAfterWorkItemInvocations.count, 1) + + // Should not flush immediately + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 0) + + // Manually trigger the timer + testDispatchQueue.invokeLastDispatchAfterWorkItem() + + // Verify both logs are flushed together + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 1) + let sentData = try XCTUnwrap(testClient.captureLogsDataInvocations.first).data + let jsonObject = try XCTUnwrap(JSONSerialization.jsonObject(with: sentData) as? [String: Any]) + let items = try XCTUnwrap(jsonObject["items"] as? [[String: Any]]) + XCTAssertEqual(2, items.count) + } + + // MARK: - Manual Capture Logs Tests + + func testManualCaptureLogs_CapturesImmediately() throws { + // Given + let log1 = createTestLog(body: "Log 1") + let log2 = createTestLog(body: "Log 2") + + // When + sut.add(log1) + sut.add(log2) + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 0) + + sut.captureLogs() + + // Then + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 1) + + let sentData = try XCTUnwrap(testClient.captureLogsDataInvocations.first).data + let jsonObject = try XCTUnwrap(JSONSerialization.jsonObject(with: sentData) as? [String: Any]) + let items = try XCTUnwrap(jsonObject["items"] as? [[String: Any]]) + XCTAssertEqual(2, items.count) + } + + func testManualCaptureLogs_CancelsScheduledCapture() throws { + // Given + let log = createTestLog() + + // When + sut.add(log) + + // Then - timer should be started + XCTAssertEqual(testDispatchQueue.dispatchAfterWorkItemInvocations.count, 1) + let timerWorkItem = try XCTUnwrap(testDispatchQueue.dispatchAfterWorkItemInvocations.first?.workItem) + + // Manual flush immediately + sut.captureLogs() + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 1, "Manual flush should work") + + // Try to trigger the timer work item (should not flush again since timer was cancelled) + timerWorkItem.perform() + + // Then - no additional flush should occur (timer was cancelled by performFlush) + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 1, "Timer should be cancelled") + } + + func testManualCaptureLogs_WithEmptyBuffer_DoesNothing() { + // When + sut.captureLogs() + + // Then + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 0) + } + + // MARK: - Edge Cases Tests + + func testScheduledFlushAfterBufferAlreadyFlushed_DoesNothing() throws { + // Given - create logs that will trigger size-based flush + let largeLogBody = String(repeating: "B", count: 300) + let log1 = createTestLog(body: largeLogBody) + let log2 = createTestLog(body: largeLogBody) // Together > 500 bytes + + // When - add first log (starts timer) + sut.add(log1) + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 0) + XCTAssertEqual(testDispatchQueue.dispatchAfterWorkItemInvocations.count, 1) + let timerWorkItem = try XCTUnwrap(testDispatchQueue.dispatchAfterWorkItemInvocations.first?.workItem) + + // Add second log that triggers size-based flush + sut.add(log2) + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 1) + + // Try to trigger the original timer work item (should not flush again) + timerWorkItem.perform() + + // Then - no additional flush should occur + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 1) + } + + func testAddLogAfterFlush_StartsNewBatch() throws { + // Given + let log1 = createTestLog(body: "Log 1") + let log2 = createTestLog(body: "Log 2") + + // When + sut.add(log1) + sut.captureLogs() + + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 1) + + sut.add(log2) + sut.captureLogs() + + // Then - should have two separate flush calls + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 2) + + // Verify each flush contains only one log + for (index, invocation) in testClient.captureLogsDataInvocations.invocations.enumerated() { + let jsonObject = try XCTUnwrap(JSONSerialization.jsonObject(with: invocation.data) as? [String: Any]) + let items = try XCTUnwrap(jsonObject["items"] as? [[String: Any]]) + XCTAssertEqual(1, items.count) + XCTAssertEqual("Log \(index + 1)", items[0]["body"] as? String) + } + } + + // MARK: - IntegrationTests + + func testConcurrentAdds_ThreadSafe() throws { + // Given + let sutWithRealQueue = SentryLogBatcher( + client: testClient, + flushTimeout: 5, + maxBufferSizeBytes: 10_000, // Large buffer to avoid immediate flushes + dispatchQueue: SentryDispatchQueueWrapper() // Real dispatch queue + ) + + let expectation = XCTestExpectation(description: "Concurrent adds") + expectation.expectedFulfillmentCount = 10 + + // When - add logs concurrently from multiple threads + for i in 0..<10 { + DispatchQueue.global().async { + let log = self.createTestLog(body: "Log \(i)") + sutWithRealQueue.add(log) + expectation.fulfill() + } + } + wait(for: [expectation], timeout: 1.0) + + sutWithRealQueue.captureLogs() + + // Verify all 10 logs were included in the single batch + let sentData = try XCTUnwrap(testClient.captureLogsDataInvocations.first).data + let jsonObject = try XCTUnwrap(JSONSerialization.jsonObject(with: sentData) as? [String: Any]) + let items = try XCTUnwrap(jsonObject["items"] as? [[String: Any]]) + XCTAssertEqual(10, items.count, "All 10 concurrently added logs should be in the batch") + // Note: We can't verify exact order due to concurrency, but count should be correct + } + + func testDispatchAfterTimeoutWithRealDispatchQueue() throws { + // Given - create batcher with real dispatch queue and short timeout + let sutWithRealQueue = SentryLogBatcher( + client: testClient, + flushTimeout: 0.2, // Short but realistic timeout + maxBufferSizeBytes: 10_000, // Large buffer to avoid size-based flush + dispatchQueue: SentryDispatchQueueWrapper() // Real dispatch queue + ) + + let log = createTestLog(body: "Real timeout test log") + let expectation = XCTestExpectation(description: "Real timeout flush") + + // When - add log and wait for real timeout + sutWithRealQueue.add(log) + + // Initially no flush should have occurred + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 0) + + // Wait for timeout to trigger flush + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { // Wait longer than timeout + expectation.fulfill() + } + wait(for: [expectation], timeout: 1.0) + + // Then - verify flush occurred due to timeout + XCTAssertEqual(testClient.captureLogsDataInvocations.count, 1, "Timeout should trigger flush") + + let sentData = try XCTUnwrap(testClient.captureLogsDataInvocations.first).data + let jsonObject = try XCTUnwrap(JSONSerialization.jsonObject(with: sentData) as? [String: Any]) + let items = try XCTUnwrap(jsonObject["items"] as? [[String: Any]]) + XCTAssertEqual(1, items.count, "Should contain exactly one log") + XCTAssertEqual("Real timeout test log", items[0]["body"] as? String) + } + + // MARK: - Helper Methods + + private func createTestLog( + level: SentryLog.Level = .info, + body: String = "Test log message", + attributes: [String: SentryLog.Attribute] = [:] + ) -> SentryLog { + return SentryLog( + timestamp: Date(timeIntervalSince1970: 1_627_846_801), + traceId: SentryId.empty, + level: level, + body: body, + attributes: attributes + ) + } +} diff --git a/Tests/SentryTests/SentryLoggerTests.swift b/Tests/SentryTests/SentryLoggerTests.swift new file mode 100644 index 00000000000..1539dd3246e --- /dev/null +++ b/Tests/SentryTests/SentryLoggerTests.swift @@ -0,0 +1,874 @@ +@_spi(Private) @testable import Sentry +@_spi(Private) import SentryTestUtils +import XCTest + +// swiftlint:disable cyclomatic_complexity + +final class SentryLoggerTests: XCTestCase { + + private class Fixture { + let hub: TestHub + let client: TestClient + let dateProvider: TestCurrentDateProvider + let options: Options + let scope: Scope + let batcher: TestLogBatcher + + init() { + options = Options() + options.dsn = TestConstants.dsnAsString(username: "SentryLoggerTests") + + client = TestClient(options: options)! + scope = Scope() + hub = TestHub(client: client, andScope: scope) + dateProvider = TestCurrentDateProvider() + batcher = TestLogBatcher(client: client, dispatchQueue: TestSentryDispatchQueueWrapper()) + + dateProvider.setDate(date: Date(timeIntervalSince1970: 1_627_846_800.123456)) + } + + func getSut() -> SentryLogger { + return SentryLogger(hub: hub, dateProvider: dateProvider, batcher: batcher) + } + } + + private var fixture: Fixture! + private var sut: SentryLogger! + + override func setUp() { + super.setUp() + fixture = Fixture() + sut = fixture.getSut() + } + + override func tearDown() { + super.tearDown() + clearTestState() + } + + // MARK: - Trace Level Tests + + func testTrace_WithBodyOnly() { + sut.trace("Test trace message") + + assertLogCaptured( + .trace, + "Test trace message", + [:] + ) + } + + func testTrace_WithBodyAndAttributes() { + let attributes: [String: Any] = [ + "user_id": "12345", + "is_debug": true, + "count": 42, + "score": 3.14159 + ] + + sut.trace("Test trace with attributes", attributes: attributes) + + assertLogCaptured( + .trace, + "Test trace with attributes", + [ + "user_id": SentryLog.Attribute(string: "12345"), + "is_debug": SentryLog.Attribute(boolean: true), + "count": SentryLog.Attribute(integer: 42), + "score": SentryLog.Attribute(double: 3.14159) + ] + ) + } + + // MARK: - Debug Level Tests + + func testDebug_WithBodyOnly() { + sut.debug("Test debug message") + + assertLogCaptured( + .debug, + "Test debug message", + [:] + ) + } + + func testDebug_WithBodyAndAttributes() { + let attributes: [String: Any] = [ + "module": "networking", + "enabled": false + ] + + sut.debug("Debug networking", attributes: attributes) + + assertLogCaptured( + .debug, + "Debug networking", + [ + "module": SentryLog.Attribute(string: "networking"), + "enabled": SentryLog.Attribute(boolean: false) + ] + ) + } + + // MARK: - Info Level Tests + + func testInfo_WithBodyOnly() { + sut.info("Test info message") + + assertLogCaptured( + .info, + "Test info message", + [:] + ) + } + + func testInfo_WithBodyAndAttributes() { + let attributes: [String: Any] = [ + "request_id": "req-123", + "duration": 1.5 + ] + + sut.info("Request completed", attributes: attributes) + + assertLogCaptured( + .info, + "Request completed", + [ + "request_id": SentryLog.Attribute(string: "req-123"), + "duration": SentryLog.Attribute(double: 1.5) + ] + ) + } + + // MARK: - Warn Level Tests + + func testWarn_WithBodyOnly() { + sut.warn("Test warning message") + + assertLogCaptured( + .warn, + "Test warning message", + [:] + ) + } + + func testWarn_WithBodyAndAttributes() { + let attributes: [String: Any] = [ + "retry_count": 3, + "will_retry": true + ] + + sut.warn("Connection failed", attributes: attributes) + + assertLogCaptured( + .warn, + "Connection failed", + [ + "retry_count": SentryLog.Attribute(integer: 3), + "will_retry": SentryLog.Attribute(boolean: true) + ] + ) + } + + // MARK: - Error Level Tests + + func testError_WithBodyOnly() { + sut.error("Test error message") + + assertLogCaptured( + .error, + "Test error message", + [:] + ) + } + + func testError_WithBodyAndAttributes() { + let attributes: [String: Any] = [ + "error_code": 500, + "recoverable": false + ] + + sut.error("Server error occurred", attributes: attributes) + + assertLogCaptured( + .error, + "Server error occurred", + [ + "error_code": SentryLog.Attribute(integer: 500), + "recoverable": SentryLog.Attribute(boolean: false) + ] + ) + } + + // MARK: - Fatal Level Tests + + func testFatal_WithBodyOnly() { + sut.fatal("Test fatal message") + + assertLogCaptured( + .fatal, + "Test fatal message", + [:] + ) + } + + func testFatal_WithBodyAndAttributes() { + let attributes: [String: Any] = [ + "exit_code": -1, + "critical": true + ] + + sut.fatal("Application crashed", attributes: attributes) + + assertLogCaptured( + .fatal, + "Application crashed", + [ + "exit_code": SentryLog.Attribute(integer: -1), + "critical": SentryLog.Attribute(boolean: true) + ] + ) + } + + func testEmptyAttributes() { + sut.info("Empty attributes", attributes: [:]) + + assertLogCaptured( + .info, + "Empty attributes", + [:] + ) + } + + // MARK: - Date Provider Tests + + func testUsesDateProviderForTimestamp() { + let expectedDate = Date(timeIntervalSince1970: 1_234_567_890.123456) + fixture.dateProvider.setDate(date: expectedDate) + + sut.info("Test timestamp") + + let capturedLog = getLastCapturedLog() + XCTAssertEqual(capturedLog.timestamp, expectedDate) + } + + // MARK: - Multiple Logs Tests + + func testMultipleLogsCaptured() { + sut.trace("Trace message") + sut.debug("Debug message") + sut.info("Info message") + sut.warn("Warn message") + sut.error("Error message") + sut.fatal("Fatal message") + + let logs = fixture.batcher.addInvocations.invocations + XCTAssertEqual(logs.count, 6) + + XCTAssertEqual(logs[0].level, .trace) + XCTAssertEqual(logs[1].level, .debug) + XCTAssertEqual(logs[2].level, .info) + XCTAssertEqual(logs[3].level, .warn) + XCTAssertEqual(logs[4].level, .error) + XCTAssertEqual(logs[5].level, .fatal) + } + + // MARK: - Default Attributes Tests + + func testCaptureLog_AddsDefaultAttributes() { + fixture.options.environment = "test-environment" + fixture.options.releaseName = "1.0.0" + + let span = fixture.hub.startTransaction(name: "Test Transaction", operation: "test-operation") + fixture.hub.scope.span = span + + sut.info("Test log message") + + let capturedLog = getLastCapturedLog() + + // Verify default attributes were added to the log + XCTAssertEqual(capturedLog.attributes["sentry.sdk.name"]?.value as? String, SentryMeta.sdkName) + XCTAssertEqual(capturedLog.attributes["sentry.sdk.version"]?.value as? String, SentryMeta.versionString) + XCTAssertEqual(capturedLog.attributes["sentry.environment"]?.value as? String, "test-environment") + XCTAssertEqual(capturedLog.attributes["sentry.release"]?.value as? String, "1.0.0") + XCTAssertEqual(capturedLog.attributes["sentry.trace.parent_span_id"]?.value as? String, span.spanId.sentrySpanIdString) + } + + func testCaptureLog_DoesNotAddNilDefaultAttributes() { + fixture.options.releaseName = nil + + sut.info("Test log message") + + let capturedLog = getLastCapturedLog() + + XCTAssertNil(capturedLog.attributes["sentry.release"]) + XCTAssertNil(capturedLog.attributes["sentry.trace.parent_span_id"]) + + // But should still have the non-nil defaults + XCTAssertEqual(capturedLog.attributes["sentry.sdk.name"]?.value as? String, SentryMeta.sdkName) + XCTAssertEqual(capturedLog.attributes["sentry.sdk.version"]?.value as? String, SentryMeta.versionString) + XCTAssertEqual(capturedLog.attributes["sentry.environment"]?.value as? String, fixture.options.environment) + } + + func testCaptureLog_SetsTraceIdFromPropagationContext() { + fixture.options.experimental.enableLogs = true + + let expectedTraceId = SentryId() + let propagationContext = SentryPropagationContext(trace: expectedTraceId, spanId: SpanId()) + + fixture.hub.scope.propagationContext = propagationContext + + sut.info("Test log message with trace ID") + + let capturedLog = getLastCapturedLog() + + // Verify that the log's trace ID matches the one from the propagation context + XCTAssertEqual(capturedLog.traceId, expectedTraceId) + } + + // MARK: - Formatted String Tests + + func testTrace_WithFormattedString() { + let user = "john" + let count = 42 + let active = true + let score = 95.5 + + let logString: SentryLogMessage = "User \(user) processed \(count) items, active: \(active), score: \(score)" + sut.trace(logString) + + assertLogCaptured( + .trace, + "User john processed 42 items, active: true, score: 95.5", + [ + "sentry.message.template": .init(string: "User {0} processed {1} items, active: {2}, score: {3}"), + "sentry.message.parameter.0": .init(string: "john"), + "sentry.message.parameter.1": .init(integer: 42), + "sentry.message.parameter.2": .init(boolean: true), + "sentry.message.parameter.3": .init(double: 95.5) + ] + ) + } + + func testTrace_WithFormattedStringAndAttributes() { + let userId = "user123" + let logString: SentryLogMessage = "Processing user \(userId)" + + sut.trace(logString, attributes: ["extra": "data", "count": 10]) + + assertLogCaptured( + .trace, + "Processing user user123", + [ + "sentry.message.template": .init(string: "Processing user {0}"), + "sentry.message.parameter.0": .init(string: "user123"), + "extra": .init(string: "data"), + "count": .init(integer: 10) + ] + ) + } + + func testDebug_WithFormattedString() { + let value: Float = 3.14 + let enabled = false + + let logString: SentryLogMessage = "Float value: \(value), enabled: \(enabled)" + sut.debug(logString) + + assertLogCaptured( + .debug, + "Float value: 3.14, enabled: false", + [ + "sentry.message.template": .init(string: "Float value: {0}, enabled: {1}"), + "sentry.message.parameter.0": .init(double: Double(value)), // Float is converted to Double + "sentry.message.parameter.1": .init(boolean: false) + ] + ) + } + + func testInfo_WithFormattedString() { + let temperature = 98.6 + let unit = "F" + + let logString: SentryLogMessage = "Temperature: \(temperature)°\(unit)" + sut.info(logString) + + assertLogCaptured( + .info, + "Temperature: 98.6°F", + [ + "sentry.message.template": .init(string: "Temperature: {0}°{1}"), + "sentry.message.parameter.0": .init(double: 98.6), + "sentry.message.parameter.1": .init(string: "F") + ] + ) + } + + func testWarn_WithFormattedString() { + let attempts = 3 + let maxAttempts = 5 + + let logString: SentryLogMessage = "Retry \(attempts) of \(maxAttempts)" + sut.warn(logString, attributes: ["retry_policy": "exponential"]) + + assertLogCaptured( + .warn, + "Retry 3 of 5", + [ + "sentry.message.template": .init(string: "Retry {0} of {1}"), + "sentry.message.parameter.0": .init(integer: 3), + "sentry.message.parameter.1": .init(integer: 5), + "retry_policy": .init(string: "exponential") + ] + ) + } + + func testError_WithFormattedString() { + let errorCode = 500 + let service = "payment" + + let logString: SentryLogMessage = "Service \(service) failed with code \(errorCode)" + sut.error(logString) + + assertLogCaptured( + .error, + "Service payment failed with code 500", + [ + "sentry.message.template": .init(string: "Service {0} failed with code {1}"), + "sentry.message.parameter.0": .init(string: "payment"), + "sentry.message.parameter.1": .init(integer: 500) + ] + ) + } + + func testFatal_WithFormattedString() { + let component = "database" + let critical = true + + let logString: SentryLogMessage = "Critical failure in \(component): \(critical)" + sut.fatal(logString, attributes: ["shutdown": true]) + + assertLogCaptured( + .fatal, + "Critical failure in database: true", + [ + "sentry.message.template": .init(string: "Critical failure in {0}: {1}"), + "sentry.message.parameter.0": .init(string: "database"), + "sentry.message.parameter.1": .init(boolean: true), + "shutdown": .init(boolean: true) + ] + ) + } + + func testFormattedString_WithMixedTypes() { + let name = "test" + let count = 0 + let percentage = 0.0 + let success = false + let value: Float = -1.5 + + let logString: SentryLogMessage = "Test \(name): \(count) items, \(percentage)% complete, success: \(success), float: \(value)" + sut.debug(logString) + + assertLogCaptured( + .debug, + "Test test: 0 items, 0.0% complete, success: false, float: -1.5", + [ + "sentry.message.template": .init(string: "Test {0}: {1} items, {2}% complete, success: {3}, float: {4}"), + "sentry.message.parameter.0": .init(string: "test"), + "sentry.message.parameter.1": .init(integer: 0), + "sentry.message.parameter.2": .init(double: 0.0), + "sentry.message.parameter.3": .init(boolean: false), + "sentry.message.parameter.4": .init(double: Double(-1.5)) + ] + ) + } + + func testFormattedString_EmptyAttributes() { + let logString: SentryLogMessage = "Simple message" + sut.info(logString, attributes: [:]) + + assertLogCaptured( + .info, + "Simple message", + [:] // No template should be added for string literals without interpolations + ) + } + + // MARK: - User Attributes Tests + + func testCaptureLog_AddsUserAttributes() { + let user = User() + user.userId = "123" + user.email = "test@test.com" + user.name = "test-name" + + // Set the user on the scope + fixture.hub.scope.setUser(user) + + sut.info("Test log message with user") + + let capturedLog = getLastCapturedLog() + + // Verify user attributes were added to the log + XCTAssertEqual(capturedLog.attributes["user.id"]?.value as? String, "123") + XCTAssertEqual(capturedLog.attributes["user.id"]?.type, "string") + + XCTAssertEqual(capturedLog.attributes["user.name"]?.value as? String, "test-name") + XCTAssertEqual(capturedLog.attributes["user.name"]?.type, "string") + + XCTAssertEqual(capturedLog.attributes["user.email"]?.value as? String, "test@test.com") + XCTAssertEqual(capturedLog.attributes["user.email"]?.type, "string") + } + + func testCaptureLog_DoesNotAddNilUserAttributes() { + let user = User() + user.userId = "123" + // email and name are nil + + fixture.hub.scope.setUser(user) + + sut.info("Test log message with partial user") + + let capturedLog = getLastCapturedLog() + + // Should only have user.id + XCTAssertEqual(capturedLog.attributes["user.id"]?.value as? String, "123") + XCTAssertNil(capturedLog.attributes["user.name"]) + XCTAssertNil(capturedLog.attributes["user.email"]) + } + + func testCaptureLog_DoesNotAddUserAttributesWhenNoUser() { + // No user set on scope + + sut.info("Test log message without user") + + let capturedLog = getLastCapturedLog() + + // Should not have any user attributes + XCTAssertNil(capturedLog.attributes["user.id"]) + XCTAssertNil(capturedLog.attributes["user.name"]) + XCTAssertNil(capturedLog.attributes["user.email"]) + } + + func testCaptureLog_AddsOSAndDeviceAttributes() { + // Set up OS context + let osContext = [ + "name": "iOS", + "version": "16.0.1" + ] + + // Set up device context + let deviceContext = [ + "family": "iOS", + "model": "iPhone14,4" + ] + + // Set up scope context + fixture.hub.scope.setContext(value: osContext, key: "os") + fixture.hub.scope.setContext(value: deviceContext, key: "device") + + sut.info("Test log message") + + let capturedLog = getLastCapturedLog() + + // Verify OS attributes + XCTAssertEqual(capturedLog.attributes["os.name"]?.value as? String, "iOS") + XCTAssertEqual(capturedLog.attributes["os.version"]?.value as? String, "16.0.1") + + // Verify device attributes + XCTAssertEqual(capturedLog.attributes["device.brand"]?.value as? String, "Apple") + XCTAssertEqual(capturedLog.attributes["device.model"]?.value as? String, "iPhone14,4") + XCTAssertEqual(capturedLog.attributes["device.family"]?.value as? String, "iOS") + } + + func testCaptureLog_HandlesPartialOSAndDeviceAttributes() { + // Set up partial OS context (missing version) + let osContext = [ + "name": "macOS" + ] + + // Set up partial device context (missing model) + let deviceContext = [ + "family": "macOS" + ] + + // Set up scope context + fixture.hub.scope.setContext(value: osContext, key: "os") + fixture.hub.scope.setContext(value: deviceContext, key: "device") + + sut.info("Test log message") + + let capturedLog = getLastCapturedLog() + + // Verify only available OS attributes are added + XCTAssertEqual(capturedLog.attributes["os.name"]?.value as? String, "macOS") + XCTAssertNil(capturedLog.attributes["os.version"]) + + // Verify only available device attributes are added + XCTAssertEqual(capturedLog.attributes["device.brand"]?.value as? String, "Apple") + XCTAssertNil(capturedLog.attributes["device.model"]) + XCTAssertEqual(capturedLog.attributes["device.family"]?.value as? String, "macOS") + } + + func testCaptureLog_HandlesMissingOSAndDeviceContext() { + // Clear any OS and device context that might be automatically populated + fixture.hub.scope.removeContext(key: "os") + fixture.hub.scope.removeContext(key: "device") + + sut.info("Test log message") + + let capturedLog = getLastCapturedLog() + + // Verify no OS or device attributes are added when context is missing + XCTAssertNil(capturedLog.attributes["os.name"]) + XCTAssertNil(capturedLog.attributes["os.version"]) + XCTAssertNil(capturedLog.attributes["device.brand"]) + XCTAssertNil(capturedLog.attributes["device.model"]) + XCTAssertNil(capturedLog.attributes["device.family"]) + } + + // MARK: - BeforeSendLog Callback Tests + + func testBeforeSendLogCallback_ReturnsModifiedLog() { + var beforeSendCalled = false + fixture.options.beforeSendLog = { log in + beforeSendCalled = true + + // Verify the mutable log has expected properties + XCTAssertEqual(log.level, .info) + XCTAssertEqual(log.body, "Original message") + + // Modify the log + log.body = "Modified by callback" + log.level = .warn + log.attributes["callback_modified"] = SentryLog.Attribute(boolean: true) + + return log + } + + sut.info("Original message") + + XCTAssertTrue(beforeSendCalled, "beforeSendLog callback should be called") + + let logs = fixture.batcher.addInvocations.invocations + XCTAssertEqual(logs.count, 1) + + let capturedLog = logs[0] + XCTAssertEqual(capturedLog.level, .warn) + XCTAssertEqual(capturedLog.body, "Modified by callback") + XCTAssertEqual(capturedLog.attributes["callback_modified"]?.value as? Bool, true) + } + + func testBeforeSendLogCallback_ReturnsNil_LogNotCaptured() { + var beforeSendCalled = false + fixture.options.beforeSendLog = { _ in + beforeSendCalled = true + return nil // Drop the log + } + + sut.error("This log should be dropped") + + XCTAssertTrue(beforeSendCalled, "beforeSendLog callback should be called") + + let logs = fixture.batcher.addInvocations.invocations + XCTAssertEqual(logs.count, 0, "Log should be dropped when callback returns nil") + } + + func testBeforeSendLogCallback_NotSet_LogCapturedUnmodified() { + // No beforeSendLog callback set + fixture.options.beforeSendLog = nil + + sut.debug("Debug message") + + let logs = fixture.batcher.addInvocations.invocations + XCTAssertEqual(logs.count, 1) + + let capturedLog = logs[0] + XCTAssertEqual(capturedLog.level, .debug) + XCTAssertEqual(capturedLog.body, "Debug message") + } + + func testBeforeSendLogCallback_MultipleLogLevels() { + var callbackInvocations: [(SentryLog.Level, String)] = [] + + fixture.options.beforeSendLog = { log in + callbackInvocations.append((log.level, log.body)) + log.attributes["processed"] = SentryLog.Attribute(boolean: true) + return log + } + + sut.trace("Trace message") + sut.debug("Debug message") + sut.info("Info message") + sut.warn("Warn message") + sut.error("Error message") + sut.fatal("Fatal message") + + XCTAssertEqual(callbackInvocations.count, 6) + XCTAssertEqual(callbackInvocations[0].0, .trace) + XCTAssertEqual(callbackInvocations[0].1, "Trace message") + XCTAssertEqual(callbackInvocations[1].0, .debug) + XCTAssertEqual(callbackInvocations[1].1, "Debug message") + XCTAssertEqual(callbackInvocations[2].0, .info) + XCTAssertEqual(callbackInvocations[2].1, "Info message") + XCTAssertEqual(callbackInvocations[3].0, .warn) + XCTAssertEqual(callbackInvocations[3].1, "Warn message") + XCTAssertEqual(callbackInvocations[4].0, .error) + XCTAssertEqual(callbackInvocations[4].1, "Error message") + XCTAssertEqual(callbackInvocations[5].0, .fatal) + XCTAssertEqual(callbackInvocations[5].1, "Fatal message") + + // Verify all logs were processed + let logs = fixture.batcher.addInvocations.invocations + XCTAssertEqual(logs.count, 6) + for log in logs { + XCTAssertEqual(log.attributes["processed"]?.value as? Bool, true) + } + } + + func testBeforeSendLogCallback_PreservesOriginalLogAttributes() { + fixture.options.beforeSendLog = { log in + // Add new attributes without removing existing ones + log.attributes["added_by_callback"] = SentryLog.Attribute(string: "callback_value") + return log + } + + sut.info("Test message", attributes: [ + "original_key": "original_value", + "user_id": 12_345 + ]) + + let logs = fixture.batcher.addInvocations.invocations + XCTAssertEqual(logs.count, 1) + + let capturedLog = logs[0] + // Original attributes should be preserved + XCTAssertEqual(capturedLog.attributes["original_key"]?.value as? String, "original_value") + XCTAssertEqual(capturedLog.attributes["user_id"]?.value as? Int, 12_345) + // New attribute should be added + XCTAssertEqual(capturedLog.attributes["added_by_callback"]?.value as? String, "callback_value") + } + + func testBeforeSendLogCallback_DynamicAccessGetAndSet() { + // Test dynamic access can both set and get the callback + let originalCallback: (SentryLog) -> SentryLog? = { log in + log.body = "Modified by original callback" + return log + } + + // Set using dynamic access + fixture.options.setValue(originalCallback, forKey: "beforeSendLogDynamic") + + // Get using dynamic access and verify it's the same callback + let retrievedCallback = fixture.options.value(forKey: "beforeSendLogDynamic") as? (SentryLog) -> SentryLog? + XCTAssertNotNil(retrievedCallback, "Dynamic access should retrieve the callback") + + let log = SentryLog(timestamp: Date(), traceId: .empty, level: .info, body: "foo", attributes: [:]) + let modifiedLog = retrievedCallback?(log) + + XCTAssertEqual(modifiedLog?.body, "Modified by original callback") + + // Test setting to nil using dynamic access + fixture.options.setValue(nil, forKey: "beforeSendLogDynamic") + let nilCallback = fixture.options.value(forKey: "beforeSendLogDynamic") + XCTAssertNil(nilCallback, "Dynamic access should allow setting to nil") + } + + // MARK: - Helper Methods + + private func assertLogCaptured( + _ expectedLevel: SentryLog.Level, + _ expectedBody: String, + _ expectedAttributes: [String: SentryLog.Attribute], + file: StaticString = #file, + line: UInt = #line + ) { + let logs = fixture.batcher.addInvocations.invocations + XCTAssertEqual(logs.count, 1, "Expected exactly one log to be captured", file: file, line: line) + + guard let capturedLog = logs.first else { + XCTFail("No log captured", file: file, line: line) + return + } + + XCTAssertEqual(capturedLog.level, expectedLevel, "Log level mismatch", file: file, line: line) + XCTAssertEqual(capturedLog.body, expectedBody, "Log body mismatch", file: file, line: line) + XCTAssertEqual(capturedLog.timestamp, fixture.dateProvider.date(), "Log timestamp mismatch", file: file, line: line) + + // Count expected default attributes dynamically + var expectedDefaultAttributeCount = 3 // sdk.name, sdk.version, environment are always present + if fixture.options.releaseName != nil { + expectedDefaultAttributeCount += 1 // sentry.release + } + if fixture.hub.scope.span != nil { + expectedDefaultAttributeCount += 1 // sentry.trace.parent_span_id + } + // OS and device attributes (up to 5 more if context is available) + if let contextDictionary = fixture.hub.scope.serialize()["context"] as? [String: [String: Any]] { + if let osContext = contextDictionary["os"] { + if osContext["name"] != nil { expectedDefaultAttributeCount += 1 } + if osContext["version"] != nil { expectedDefaultAttributeCount += 1 } + } + if contextDictionary["device"] != nil { + expectedDefaultAttributeCount += 1 // device.brand (always "Apple") + if let deviceContext = contextDictionary["device"] { + if deviceContext["model"] != nil { expectedDefaultAttributeCount += 1 } + if deviceContext["family"] != nil { expectedDefaultAttributeCount += 1 } + } + } + } + + // Compare attributes + XCTAssertEqual(capturedLog.attributes.count, expectedAttributes.count + expectedDefaultAttributeCount, "Attribute count mismatch", file: file, line: line) + + for (key, expectedAttribute) in expectedAttributes { + guard let actualAttribute = capturedLog.attributes[key] else { + XCTFail("Missing attribute key: \(key)", file: file, line: line) + continue + } + + XCTAssertEqual(actualAttribute.type, expectedAttribute.type, "Attribute type mismatch for key: \(key)", file: file, line: line) + + // Compare values based on type + switch expectedAttribute.type { + case "string": + let expectedValue = expectedAttribute.value as! String + let actualValue = actualAttribute.value as! String + XCTAssertEqual(actualValue, expectedValue, "String attribute value mismatch for key: \(key)", file: file, line: line) + case "boolean": + let expectedValue = expectedAttribute.value as! Bool + let actualValue = actualAttribute.value as! Bool + XCTAssertEqual(actualValue, expectedValue, "Boolean attribute value mismatch for key: \(key)", file: file, line: line) + case "integer": + let expectedValue = expectedAttribute.value as! Int + let actualValue = actualAttribute.value as! Int + XCTAssertEqual(actualValue, expectedValue, "Integer attribute value mismatch for key: \(key)", file: file, line: line) + case "double": + let expectedValue = expectedAttribute.value as! Double + let actualValue = actualAttribute.value as! Double + XCTAssertEqual(actualValue, expectedValue, accuracy: 0.000001, "Double attribute value mismatch for key: \(key)", file: file, line: line) + default: + XCTFail("Unknown attribute type for key: \(key). Type: \(expectedAttribute.type)", file: file, line: line) + } + } + } + + private func getLastCapturedLog() -> SentryLog { + let logs = fixture.batcher.addInvocations.invocations + guard let lastLog = logs.last else { + XCTFail("No logs captured") + return SentryLog(timestamp: Date(), traceId: .empty, level: .info, body: "", attributes: [:]) + } + return lastLog + } +} + +final class TestLogBatcher: SentryLogBatcher { + + var addInvocations = Invocations() + + override func add(_ log: SentryLog) { + addInvocations.record(log) + } +} diff --git a/Tests/SentryTests/SentryOptionsTest.m b/Tests/SentryTests/SentryOptionsTest.m index 2788f10dc05..93740008697 100644 --- a/Tests/SentryTests/SentryOptionsTest.m +++ b/Tests/SentryTests/SentryOptionsTest.m @@ -1,7 +1,7 @@ #import "SentryOptions.h" #import "SentryError.h" -#import "SentryOptions+HybridSDKs.h" -#import "SentrySDK.h" +#import "SentryOptionsInternal.h" +#import "SentrySDKInternal.h" #import "SentrySpan.h" #import "SentryTests-Swift.h" #import @@ -15,7 +15,7 @@ @implementation SentryOptionsTest - (void)testEmptyDsn { NSError *error = nil; - SentryOptions *options = [[SentryOptions alloc] initWithDict:@{} didFailWithError:&error]; + SentryOptions *options = [SentryOptionsInternal initWithDict:@{} didFailWithError:&error]; XCTAssertNil(options.parsedDsn); XCTAssertEqual(NO, options.debug); @@ -27,7 +27,7 @@ - (void)testEmptyDsn - (void)testInvalidDsnBoolean { NSError *error = nil; - SentryOptions *options = [[SentryOptions alloc] initWithDict:@{ @"dsn" : @YES } + SentryOptions *options = [SentryOptionsInternal initWithDict:@{ @"dsn" : @YES } didFailWithError:&error]; [self assertDsnNil:options andError:error]; @@ -43,7 +43,7 @@ - (void)assertDsnNil:(SentryOptions *)options andError:(NSError *)error - (void)testInvalidDsn { NSError *error = nil; - SentryOptions *options = [[SentryOptions alloc] initWithDict:@{ @"dsn" : @"https://sentry.io" } + SentryOptions *options = [SentryOptionsInternal initWithDict:@{ @"dsn" : @"https://sentry.io" } didFailWithError:&error]; XCTAssertEqual(kSentryErrorInvalidDsnError, error.code); XCTAssertNil(options); @@ -51,7 +51,7 @@ - (void)testInvalidDsn - (void)testInvalidDsnWithNoErrorArgument { - SentryOptions *options = [[SentryOptions alloc] initWithDict:@{ @"dsn" : @"https://sentry.io" } + SentryOptions *options = [SentryOptionsInternal initWithDict:@{ @"dsn" : @"https://sentry.io" } didFailWithError:nil]; XCTAssertNil(options); } @@ -129,7 +129,7 @@ - (void)testInvalidDebug - (void)testDebugWith:(NSObject *)debugValue expected:(BOOL)expectedDebugValue { NSError *error = nil; - SentryOptions *options = [[SentryOptions alloc] initWithDict:@{ + SentryOptions *options = [SentryOptionsInternal initWithDict:@{ @"dsn" : @"https://username:password@sentry.io/1", @"debug" : debugValue } @@ -476,15 +476,21 @@ - (void)testIntegrations NSArray *integrations = @[ @"integration1", @"integration2" ]; SentryOptions *options = [self getValidOptions:@{ @"integrations" : integrations }]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" [self assertArrayEquals:integrations actual:options.integrations]; +#pragma clang diagnostic pop } - (void)testDefaultIntegrations { SentryOptions *options = [self getValidOptions:@{}]; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" XCTAssertTrue([[SentryOptions defaultIntegrations] isEqualToArray:options.integrations], @"Default integrations are not set correctly"); +#pragma clang diagnostic pop } #if SENTRY_HAS_UIKIT @@ -595,7 +601,7 @@ - (void)testEmptyConstructorSetsDefaultValues - (void)testNSNull_SetsDefaultValue { - SentryOptions *options = [[SentryOptions alloc] initWithDict:@{ + SentryOptions *options = [SentryOptionsInternal initWithDict:@{ @"urlSession" : [NSNull null], @"dsn" : [NSNull null], @"enabled" : [NSNull null], @@ -671,8 +677,11 @@ - (void)assertDefaultValues:(SentryOptions *)options XCTAssertNil(options.beforeSend); XCTAssertNil(options.beforeBreadcrumb); XCTAssertNil(options.onCrashedLastRun); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" XCTAssertTrue([[SentryOptions defaultIntegrations] isEqualToArray:options.integrations], @"Default integrations are not set correctly"); +#pragma clang diagnostic pop XCTAssertEqual(@1, options.sampleRate); XCTAssertEqual(YES, options.enableAutoSessionTracking); XCTAssertEqual(YES, options.enableWatchdogTerminationTracking); @@ -736,9 +745,9 @@ - (void)assertDefaultValues:(SentryOptions *)options # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wdeprecated-declarations" XCTAssertEqual(NO, options.enableProfiling); -# pragma clang diagnostic pop XCTAssertNil(options.profilesSampleRate); XCTAssertNil(options.profilesSampler); +# pragma clang diagnostic pop XCTAssertTrue([options isContinuousProfilingEnabled]); #endif // SENTRY_TARGET_PROFILING_SUPPORTED @@ -1155,6 +1164,8 @@ - (void)testEnableProfiling [self testBooleanField:@"enableProfiling" defaultValue:NO]; } +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" - (void)testProfilesSampleRate { SentryOptions *options = [self getValidOptions:@{ @"profilesSampleRate" : @0.1 }]; @@ -1344,6 +1355,7 @@ - (void)testGarbageProfilesSampler_ReturnsNil XCTAssertNil(options.profilesSampler); XCTAssertTrue([options isContinuousProfilingEnabled]); } +# pragma clang diagnostic pop #endif // SENTRY_TARGET_PROFILING_SUPPORTED @@ -1426,11 +1438,14 @@ - (void)testInitialScope } #if SENTRY_TARGET_PROFILING_SUPPORTED +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" - (void)testEnableAppLaunchProfilingDefaultValue { SentryOptions *options = [self getValidOptions:@{}]; XCTAssertFalse(options.enableAppLaunchProfiling); } +# pragma clang diagnostic pop #endif // SENTRY_TARGET_PROFILING_SUPPORTED - (SentryOptions *)getValidOptions:(NSDictionary *)dict @@ -1442,7 +1457,7 @@ - (SentryOptions *)getValidOptions:(NSDictionary *)dict [options addEntriesFromDictionary:dict]; - SentryOptions *sentryOptions = [[SentryOptions alloc] initWithDict:options + SentryOptions *sentryOptions = [SentryOptionsInternal initWithDict:options didFailWithError:&error]; XCTAssertNil(error); return sentryOptions; diff --git a/Tests/SentryTests/SentrySDKIntegrationTestsBase.swift b/Tests/SentryTests/SentrySDKIntegrationTestsBase.swift index 22a818ad59e..1e317a8cbe1 100644 --- a/Tests/SentryTests/SentrySDKIntegrationTestsBase.swift +++ b/Tests/SentryTests/SentrySDKIntegrationTestsBase.swift @@ -16,7 +16,7 @@ class SentrySDKIntegrationTestsBase: XCTestCase { override func setUp() { super.setUp() - crashWrapper = TestSentryCrashWrapper.sharedInstance() + crashWrapper = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo) SentryDependencyContainer.sharedInstance().crashWrapper = crashWrapper currentDate = TestCurrentDateProvider() } @@ -28,14 +28,14 @@ class SentrySDKIntegrationTestsBase: XCTestCase { func givenSdkWithHub(_ options: Options? = nil, scope: Scope = Scope()) { let client = TestClient(options: options ?? self.options) - let hub = SentryHub(client: client, andScope: scope, andCrashWrapper: TestSentryCrashWrapper.sharedInstance(), andDispatchQueue: SentryDispatchQueueWrapper()) + let hub = SentryHub(client: client, andScope: scope, andCrashWrapper: TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo), andDispatchQueue: SentryDispatchQueueWrapper()) - SentrySDK.setStart(self.options) - SentrySDK.setCurrentHub(hub) + SentrySDKInternal.setStart(with: self.options) + SentrySDKInternal.setCurrentHub(hub) } func assertNoEventCaptured() { - guard let client = SentrySDK.currentHub().getClient() as? TestClient else { + guard let client = SentrySDKInternal.currentHub().getClient() as? TestClient else { XCTFail("Hub Client is not a `TestClient`") return } @@ -43,7 +43,7 @@ class SentrySDKIntegrationTestsBase: XCTestCase { } func assertEventWithScopeCaptured(_ callback: (Event?, Scope?, [SentryEnvelopeItem]?) throws -> Void) throws { - guard let client = SentrySDK.currentHub().getClient() as? TestClient else { + guard let client = SentrySDKInternal.currentHub().getClient() as? TestClient else { XCTFail("Hub Client is not a `TestClient`") return } @@ -54,7 +54,7 @@ class SentrySDKIntegrationTestsBase: XCTestCase { } func assertFatalEventWithScope(_ callback: (Event?, Scope?) throws -> Void) rethrows { - guard let client = SentrySDK.currentHub().getClient() as? TestClient else { + guard let client = SentrySDKInternal.currentHub().getClient() as? TestClient else { XCTFail("Hub Client is not a `TestClient`") return } diff --git a/Tests/SentryTests/SentrySDK+Tests.h b/Tests/SentryTests/SentrySDKInternal+Tests.h similarity index 69% rename from Tests/SentryTests/SentrySDK+Tests.h rename to Tests/SentryTests/SentrySDKInternal+Tests.h index 60948c78afa..54d7e28fb92 100644 --- a/Tests/SentryTests/SentrySDK+Tests.h +++ b/Tests/SentryTests/SentrySDKInternal+Tests.h @@ -1,16 +1,15 @@ #import "SentryDefines.h" -#import "SentrySDK.h" @class SentryEnvelope; @class SentryHub; NS_ASSUME_NONNULL_BEGIN -@interface SentrySDK () +@interface SentrySDKInternal () + (void)setCurrentHub:(nullable SentryHub *)hub; -+ (void)setStartOptions:(nullable SentryOptions *)options; ++ (void)setStartOptions:(nullable SentryOptions *)options NS_SWIFT_NAME(setStart(with:)); + (void)captureEnvelope:(SentryEnvelope *)envelope; diff --git a/Tests/SentryTests/SentrySDKInternalTests.swift b/Tests/SentryTests/SentrySDKInternalTests.swift new file mode 100644 index 00000000000..7b3c0214050 --- /dev/null +++ b/Tests/SentryTests/SentrySDKInternalTests.swift @@ -0,0 +1,1176 @@ +@_spi(Private) @testable import Sentry +@_spi(Private) import SentryTestUtils +import XCTest + +// swiftlint:disable file_length +class SentrySDKInternalTests: XCTestCase { + + private static let dsnAsString = TestConstants.dsnAsString(username: "SentrySDKTests") + + private class Fixture { + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + let options: Options = { + let options = Options.noIntegrations() + options.dsn = SentrySDKInternalTests.dsnAsString + options.releaseName = "1.0.0" + return options + }() + + let event: Event + let scope: Scope + let client: TestClient + let hub: SentryHub + let error: Error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Object does not exist"]) + let exception = NSException(name: NSExceptionName("My Custom exeption"), reason: "User clicked the button", userInfo: nil) + @available(*, deprecated, message: "SentryUserFeedback is deprecated in favor of SentryFeedback.") + let userFeedback: UserFeedback + let feedback: SentryFeedback + + let currentDate = TestCurrentDateProvider() + + let dispatchQueueWrapper = TestSentryDispatchQueueWrapper() +#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) + let observer: SentryWatchdogTerminationScopeObserver + let scopePersistentStore: TestSentryScopePersistentStore +#endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) + + let scopeBlock: (Scope) -> Void = { scope in + scope.setTag(value: "tag", key: "tag") + } + + var scopeWithBlockApplied: Scope { + let scope = self.scope + scopeBlock(scope) + return scope + } + + let message = "message" + let operation = "ui.load" + let transactionName = "Load Main Screen" + + @available(*, deprecated, message: "This is marked deprecated as a workaround until we can remove SentryUserFeedback in favor of SentryFeedback. When SentryUserFeedback is removed, this deprecation annotation can be removed.") + init() { + SentryDependencyContainer.sharedInstance().dateProvider = currentDate + + event = Event() + event.message = SentryMessage(formatted: message) + + scope = Scope() + scope.setTag(value: "value", key: "key") + + client = TestClient(options: options)! + hub = SentryHub(client: client, andScope: scope, andCrashWrapper: TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo), andDispatchQueue: SentryDispatchQueueWrapper()) + + userFeedback = UserFeedback(eventId: SentryId()) + userFeedback.comments = "Again really?" + userFeedback.email = "tim@apple.com" + userFeedback.name = "Tim Apple" + + feedback = SentryFeedback(message: "Again really?", name: "Tim Apple", email: "tim@apple.com") + +#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) + options.dsn = SentrySDKInternalTests.dsnAsString + + let fileManager = try! TestFileManager( + options: options, + dateProvider: currentDate, + dispatchQueueWrapper: dispatchQueueWrapper + ) + let breadcrumbProcessor = SentryWatchdogTerminationBreadcrumbProcessor(maxBreadcrumbs: 10, fileManager: fileManager) + scopePersistentStore = try! XCTUnwrap(TestSentryScopePersistentStore(fileManager: fileManager)) + let attributesProcessor = SentryWatchdogTerminationAttributesProcessor( + withDispatchQueueWrapper: dispatchQueueWrapper, + scopePersistentStore: scopePersistentStore + ) + observer = SentryWatchdogTerminationScopeObserver(breadcrumbProcessor: breadcrumbProcessor, attributesProcessor: attributesProcessor) +#endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) + } + } + + private var fixture: Fixture! + + @available(*, deprecated, message: "This is marked deprecated as a workaround (for the workaround deprecating the Fixture.init method) until we can remove SentryUserFeedback in favor of SentryFeedback. When SentryUserFeedback is removed, this deprecation annotation can be removed.") + override func setUp() { + super.setUp() + fixture = Fixture() + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + override func tearDown() { + super.tearDown() + + givenSdkWithHubButNoClient() + + if let autoSessionTracking = SentrySDKInternal.currentHub().installedIntegrations().first(where: { it in + it is SentryAutoSessionTrackingIntegration + }) as? SentryAutoSessionTrackingIntegration { + autoSessionTracking.stop() + } + + clearTestState() + } + + func testDetectedStartUpCrash() { + SentrySDKInternal.setDetectedStartUpCrash(true) + XCTAssertEqual(SentrySDK.detectedStartUpCrash, true) + + SentrySDKInternal.setDetectedStartUpCrash(false) + XCTAssertFalse(SentrySDK.detectedStartUpCrash) + } + + func testCaptureFatalEvent() { + let hub = TestHub(client: nil, andScope: nil) + SentrySDKInternal.setCurrentHub(hub) + + let event = fixture.event + SentrySDKInternal.captureFatalEvent(event) + + XCTAssertEqual(1, hub.sentFatalEvents.count) + XCTAssertEqual(event.message, hub.sentFatalEvents.first?.message) + XCTAssertEqual(event.eventId, hub.sentFatalEvents.first?.eventId) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testCaptureEnvelope() { + givenSdkWithHub() + + let envelope = SentryEnvelope(event: TestData.event) + SentrySDKInternal.capture(envelope) + + XCTAssertEqual(1, fixture.client.captureEnvelopeInvocations.count) + XCTAssertEqual(envelope.header.eventId, fixture.client.captureEnvelopeInvocations.first?.header.eventId) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testStoreEnvelope() { + givenSdkWithHub() + + let envelope = SentryEnvelope(event: TestData.event) + SentrySDKInternal.store(envelope) + + XCTAssertEqual(1, fixture.client.storedEnvelopeInvocations.count) + XCTAssertEqual(envelope.header.eventId, fixture.client.storedEnvelopeInvocations.first?.header.eventId) + } + + /// This is to prevent https://github.com/getsentry/sentry-cocoa/issues/4280 + /// With 8.33.0, writing an envelope could fail in the middle of the process, which the envelope + /// payload below simulates. The JSON stems from writing an envelope to disk with vast data + /// that leads to an OOM termination on v 8.33.0. + /// Running this test on v 8.33.0 leads to a crash. + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testStartSDK_WithCorruptedEnvelope() throws { + + let fileManager = try SentryFileManager( + options: fixture.options, + dateProvider: fixture.currentDate, + dispatchQueueWrapper: fixture.dispatchQueueWrapper + ) + + let corruptedEnvelopeData = Data(""" + {"event_id":"1990b5bc31904b7395fd07feb72daf1c","sdk":{"name":"sentry.cocoa","version":"8.33.0"}} + {"type":"test","length":50} + """.utf8) + + try corruptedEnvelopeData.write(to: URL(fileURLWithPath: "\(fileManager.envelopesPath)/corrupted-envelope.json")) + + SentrySDK.start(options: fixture.options) + + fileManager.deleteAllEnvelopes() + } + + @available(*, deprecated, message: "This is only marked as deprecated because enableAppLaunchProfiling is marked as deprecated. Once that is removed this can be removed.") + func testStoreEnvelope_WhenNoClient_NoCrash() { + SentrySDKInternal.store(SentryEnvelope(event: TestData.event)) + + XCTAssertEqual(0, fixture.client.storedEnvelopeInvocations.count) + } + + @available(*, deprecated, message: "-[SentrySDK captureUserFeedback:] is deprecated. -[SentrySDK captureFeedback:] is the new way. This test case can be removed in favor of testCaptureFeedback when -[SentrySDK captureUserFeedback:] is removed.") + func testCaptureUserFeedback() { + givenSdkWithHub() + + SentrySDK.capture(userFeedback: fixture.userFeedback) + let client = fixture.client + XCTAssertEqual(1, client.captureUserFeedbackInvocations.count) + if let actual = client.captureUserFeedbackInvocations.first { + let expected = fixture.userFeedback + XCTAssertEqual(expected.eventId, actual.eventId) + XCTAssertEqual(expected.name, actual.name) + XCTAssertEqual(expected.email, actual.email) + XCTAssertEqual(expected.comments, actual.comments) + } + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testCaptureFeedback() { + givenSdkWithHub() + + SentrySDK.capture(feedback: fixture.feedback) + let client = fixture.client + XCTAssertEqual(1, client.captureSerializedFeedbackInvocations.count) + if let actual = client.captureSerializedFeedbackInvocations.first { + let expected = fixture.feedback + XCTAssertEqual(expected.eventId.sentryIdString, actual.0) + } + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testStartSession() { + givenSdkWithHub() + + SentrySDK.startSession() + + XCTAssertEqual(1, fixture.client.captureSessionInvocations.count) + + let actual = fixture.client.captureSessionInvocations.first + let expected = SentrySession(releaseName: fixture.options.releaseName ?? "", distinctId: "some-id") + + XCTAssertEqual(expected.flagInit, actual?.flagInit) + XCTAssertEqual(expected.errors, actual?.errors) + XCTAssertEqual(expected.sequence, actual?.sequence) + XCTAssertEqual(expected.releaseName, actual?.releaseName) + XCTAssertEqual(SentryDependencyContainer.sharedInstance().dateProvider.date(), actual?.started) + XCTAssertEqual(SentrySessionStatus.ok, actual?.status) + XCTAssertNil(actual?.timestamp) + XCTAssertNil(actual?.duration) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testEndSession() throws { + givenSdkWithHub() + + SentrySDK.startSession() + advanceTime(bySeconds: 1) + SentrySDK.endSession() + + XCTAssertEqual(2, fixture.client.captureSessionInvocations.count) + + let actual = try XCTUnwrap(fixture.client.captureSessionInvocations.invocations.last) + + XCTAssertNil(actual.flagInit) + XCTAssertEqual(0, actual.errors) + XCTAssertEqual(2, actual.sequence) + XCTAssertEqual(SentrySessionStatus.exited, actual.status) + XCTAssertEqual(fixture.options.releaseName ?? "", actual.releaseName) + XCTAssertEqual(1, actual.duration) + XCTAssertEqual(SentryDependencyContainer.sharedInstance().dateProvider.date(), actual.timestamp) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testSetUser_SetsUserToScopeOfHub() { + givenSdkWithHub() + + let user = TestData.user + SentrySDK.setUser(user) + + let actualScope = SentrySDKInternal.currentHub().scope + let event = actualScope.applyTo(event: fixture.event, maxBreadcrumbs: 10) + XCTAssertEqual(event?.user, user) + } + + func testSetUserBeforeStartingSDK_LogsFatalMessage() throws { + // Arrange + let oldOutput = SentrySDKLog.getLogOutput() + + defer { + SentrySDKLog.setOutput(oldOutput) + } + + let logOutput = TestLogOutput() + SentrySDKLog.setLogOutput(logOutput) + + // Act + SentrySDK.setUser(nil) + + // Assert + let actualLogMessage = try XCTUnwrap(logOutput.loggedMessages.first) + let expectedLogMessage = "The SDK is disabled, so setUser doesn't work. Please ensure to start the SDK before setting the user." + + XCTAssertTrue(actualLogMessage.contains(expectedLogMessage), "Expected log message to contain '\(expectedLogMessage)', but got '\(actualLogMessage)'") + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testSetUserAFterStartingSDK_DoesNotLogFatalMessage() { + // Arrange + let oldOutput = SentrySDKLog.getLogOutput() + + defer { + SentrySDKLog.setOutput(oldOutput) + } + + let logOutput = TestLogOutput() + SentrySDKLog.setLogOutput(logOutput) + + givenSdkWithHub() + + let user = TestData.user + + // Act + SentrySDK.setUser(user) + + //Assert + XCTAssertEqual(0, logOutput.loggedMessages.count, "Expected no log messages, but got \(logOutput.loggedMessages.count)") + } + + func testAddBreadcrumbBeforeStartingSDK_LogsFatalMessage() throws { + // Arrange + let oldOutput = SentrySDKLog.getLogOutput() + + defer { + SentrySDKLog.setOutput(oldOutput) + } + + let logOutput = TestLogOutput() + SentrySDKLog.setLogOutput(logOutput) + + // Act + SentrySDK.addBreadcrumb(Breadcrumb(level: .info, category: "test")) + + // Assert + let actualLogMessage = try XCTUnwrap(logOutput.loggedMessages.first) + let expectedLogMessage = "The SDK is disabled, so addBreadcrumb doesn't work. Please ensure to start the SDK before adding breadcrumbs." + + XCTAssertTrue(actualLogMessage.contains(expectedLogMessage), "Expected log message to contain '\(expectedLogMessage)', but got '\(actualLogMessage)'") + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testAddBreadcrumbAfterStartingSDK_DoesNotLogFatalMessage() { + // Arrange + let oldOutput = SentrySDKLog.getLogOutput() + + defer { + SentrySDKLog.setOutput(oldOutput) + } + let logOutput = TestLogOutput() + SentrySDKLog.setLogOutput(logOutput) + + givenSdkWithHub() + + let breadcrumb = Breadcrumb(level: .info, category: "test") + + // Act + SentrySDK.addBreadcrumb(breadcrumb) + + // Assert + XCTAssertEqual(0, logOutput.loggedMessages.count, "Expected no log messages, but got \(logOutput.loggedMessages.count)") + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testStartTransaction() throws { + givenSdkWithHub() + + let operation = "ui.load" + let name = "Load Main Screen" + let transaction = SentrySDK.startTransaction(name: name, operation: operation) + + XCTAssertEqual(operation, transaction.operation) + let tracer = try XCTUnwrap(transaction as? SentryTracer) + XCTAssertEqual(name, tracer.traceContext?.transaction) + + XCTAssertNil(SentrySDK.span) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testStartTransaction_WithBindToScope() throws { + givenSdkWithHub() + + let transaction = SentrySDK.startTransaction(name: fixture.transactionName, operation: fixture.operation, bindToScope: true) + + XCTAssertEqual(fixture.operation, transaction.operation) + let tracer = try XCTUnwrap(transaction as? SentryTracer) + XCTAssertEqual(fixture.transactionName, tracer.traceContext?.transaction) + XCTAssertEqual(.custom, tracer.transactionContext.nameSource) + + let newSpan = SentrySDK.span + + XCTAssert(transaction === newSpan) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testInstallIntegrations() throws { + let options = Options() + options.dsn = "mine" + options.integrations = ["SentryTestIntegration", "SentryTestIntegration", "IDontExist"] + + SentrySDK.start(options: options) + + assertIntegrationsInstalled(integrations: ["SentryTestIntegration"]) + let integration = SentrySDKInternal.currentHub().installedIntegrations().first + if let testIntegration = integration as? SentryTestIntegration { + XCTAssertEqual(options.dsn, testIntegration.options.dsn) + XCTAssertEqual(options.integrations, testIntegration.options.integrations) + } + } + +#if SENTRY_HAS_UIKIT + func testSetAppStartMeasurement_CallsPrivateSDKCallback() { + let appStartMeasurement = TestData.getAppStartMeasurement(type: .warm) + + var callbackCalled = false + PrivateSentrySDKOnly.onAppStartMeasurementAvailable = { measurement in + XCTAssertEqual(appStartMeasurement, measurement) + callbackCalled = true + } + + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) + XCTAssertTrue(callbackCalled) + } + + func testSetAppStartMeasurement_NoCallback_CallbackNotCalled() { + let appStartMeasurement = TestData.getAppStartMeasurement(type: .warm) + + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) + + XCTAssertEqual(SentrySDKInternal.getAppStartMeasurement(), appStartMeasurement) + } +#endif // SENTRY_HAS_UIKIT + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testSDKStartInvocations() { + XCTAssertEqual(0, SentrySDKInternal.startInvocations) + + SentrySDK.start { options in + options.dsn = SentrySDKInternalTests.dsnAsString + options.removeAllIntegrations() + } + + XCTAssertEqual(1, SentrySDKInternal.startInvocations) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testSDKStartTimestamp() { + let currentDateProvider = TestCurrentDateProvider() + SentryDependencyContainer.sharedInstance().dateProvider = currentDateProvider + + XCTAssertNil(SentrySDKInternal.startTimestamp) + + SentrySDK.start { options in + options.dsn = SentrySDKInternalTests.dsnAsString + options.removeAllIntegrations() + } + + XCTAssertEqual(SentrySDKInternal.startTimestamp, currentDateProvider.date()) + + SentrySDK.close() + XCTAssertNil(SentrySDKInternal.startTimestamp) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testIsEnabled() { + XCTAssertFalse(SentrySDK.isEnabled) + + SentrySDK.capture(message: "message") + XCTAssertFalse(SentrySDK.isEnabled) + + SentrySDK.start { options in + options.dsn = SentrySDKInternalTests.dsnAsString + options.removeAllIntegrations() + } + XCTAssertTrue(SentrySDK.isEnabled) + + SentrySDK.close() + XCTAssertFalse(SentrySDK.isEnabled) + + SentrySDK.capture(message: "message") + XCTAssertFalse(SentrySDK.isEnabled) + + SentrySDK.start { options in + options.dsn = SentrySDKInternalTests.dsnAsString + options.removeAllIntegrations() + } + XCTAssertTrue(SentrySDK.isEnabled) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testClose_ResetsDependencyContainer() { + SentrySDK.start { options in + options.dsn = SentrySDKInternalTests.dsnAsString + options.removeAllIntegrations() + } + + let first = SentryDependencyContainer.sharedInstance() + + SentrySDK.close() + + let second = SentryDependencyContainer.sharedInstance() + + XCTAssertNotEqual(first, second) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testClose_ClearsIntegrations() { + SentrySDK.start { options in + options.dsn = SentrySDKInternalTests.dsnAsString + options.swiftAsyncStacktraces = true + options.setIntegrations([SentrySwiftAsyncIntegration.self]) + } + + let hub = SentrySDKInternal.currentHub() + XCTAssertEqual(1, hub.installedIntegrations().count) + SentrySDK.close() + XCTAssertEqual(0, hub.installedIntegrations().count) + assertIntegrationsInstalled(integrations: []) + } + +#if SENTRY_HAS_UIKIT + func testClose_StopsAppStateManager() { + SentrySDK.start { options in + options.dsn = SentrySDKTests.dsnAsString + options.tracesSampleRate = 1 + options.removeAllIntegrations() + } + + let appStateManager = SentryDependencyContainer.sharedInstance().appStateManager + XCTAssertEqual(appStateManager.startCount, 1) + + SentrySDK.start { options in + options.dsn = SentrySDKTests.dsnAsString + options.tracesSampleRate = 1 + options.removeAllIntegrations() + } + + XCTAssertEqual(appStateManager.startCount, 2) + + SentrySDK.close() + + XCTAssertEqual(appStateManager.startCount, 0) + + let stateAfterStop = fixture.fileManager.readAppState() + XCTAssertFalse(stateAfterStop!.isSDKRunning) + } +#endif + +#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testReportFullyDisplayed() { + fixture.options.enableTimeToFullDisplayTracing = true + + let testTTDTracker = TestTimeToDisplayTracker(waitForFullDisplay: true) + let performanceTracker = Dynamic(SentryDependencyContainer.sharedInstance().uiViewControllerPerformanceTracker) + performanceTracker.currentTTDTracker = testTTDTracker + + // Start SDK after setting up the tracker to ensure we're changing the tracker during it's initialization, + // because some initialization logic happens on a BG thread and we would end up in a race condition. + SentrySDK.start(options: fixture.options) + + SentrySDK.reportFullyDisplayed() + + XCTAssertTrue(testTTDTracker.registerFullDisplayCalled) + } +#endif + +#if os(iOS) + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testSentryUIDeviceWrapperStarted() { + let deviceWrapper = TestSentryUIDeviceWrapper() + SentryDependencyContainer.sharedInstance().uiDeviceWrapper = deviceWrapper + SentrySDK.start(options: fixture.options) + XCTAssertTrue(deviceWrapper.started) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testSentryUIDeviceWrapperStopped() { + let deviceWrapper = TestSentryUIDeviceWrapper() + SentryDependencyContainer.sharedInstance().uiDeviceWrapper = deviceWrapper + SentrySDK.start(options: fixture.options) + SentrySDK.close() + XCTAssertFalse(deviceWrapper.started) + } + + /// Ensure to start the UIDeviceWrapper before initializing the hub, so enrich scope sets the correct OS version. + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testStartSDK_ScopeContextContainsOSVersion() throws { + let expectation = XCTestExpectation(description: "SentrySDK start called") + + DispatchQueue.global().async { + SentrySDK.start { options in + options.integrations = [ NSStringFromClass(MainThreadTestIntegration.self) ] + } + + // Since the SDK uses the dispatchqueue on the main queue, wait until it clears to fulfill the expectation + SentryDependencyContainer.sharedInstance().dispatchQueueWrapper.dispatchAsyncOnMainQueue { + expectation.fulfill() + } + } + + wait(for: [expectation], timeout: 5.0) + + let mainThreadIntegration = try XCTUnwrap(SentrySDKInternal.currentHub().installedIntegrations().first as? MainThreadTestIntegration) + + wait(for: [mainThreadIntegration.expectation], timeout: 5.0) + + let os = try XCTUnwrap (SentrySDKInternal.currentHub().scope.contextDictionary["os"] as? [String: Any]) +#if !targetEnvironment(macCatalyst) + XCTAssertEqual(UIDevice.current.systemVersion, os["version"] as? String) +#endif + } +#endif + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testResumeAndPauseAppHangTracking() { + SentrySDK.start { options in + options.dsn = SentrySDKInternalTests.dsnAsString + options.setIntegrations([SentryANRTrackingIntegration.self]) + } + + let client = fixture.client + SentrySDKInternal.currentHub().bindClient(client) + + let anrTrackingIntegration = SentrySDKInternal.currentHub().getInstalledIntegration(SentryANRTrackingIntegration.self) + + SentrySDK.pauseAppHangTracking() + Dynamic(anrTrackingIntegration).anrDetectedWithType(SentryANRType.unknown) + XCTAssertEqual(0, client.captureEventWithScopeInvocations.count) + + SentrySDK.resumeAppHangTracking() + Dynamic(anrTrackingIntegration).anrDetectedWithType(SentryANRType.unknown) + + if SentryDependencyContainer.sharedInstance().crashWrapper.isBeingTraced { + XCTAssertEqual(0, client.captureEventWithScopeInvocations.count) + } else { + XCTAssertEqual(1, client.captureEventWithScopeInvocations.count) + } + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testResumeAndPauseAppHangTracking_ANRTrackingNotInstalled() { + SentrySDK.start { options in + options.dsn = SentrySDKInternalTests.dsnAsString + options.removeAllIntegrations() + } + + let client = fixture.client + SentrySDKInternal.currentHub().bindClient(client) + + // Both invocations do nothing + SentrySDK.pauseAppHangTracking() + SentrySDK.resumeAppHangTracking() + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testClose_SetsClientToNil() { + SentrySDK.start { options in + options.dsn = SentrySDKInternalTests.dsnAsString + options.removeAllIntegrations() + } + + SentrySDK.close() + + XCTAssertNil(SentrySDKInternal.currentHub().client()) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testClose_ClosesClient() { + SentrySDK.start { options in + options.dsn = SentrySDKInternalTests.dsnAsString + options.removeAllIntegrations() + } + + let client = SentrySDKInternal.currentHub().client() + SentrySDK.close() + + XCTAssertFalse(client?.isEnabled ?? true) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testClose_CallsFlushCorrectlyOnTransport() throws { + SentrySDK.start { options in + options.dsn = SentrySDKInternalTests.dsnAsString + options.removeAllIntegrations() + } + + let transport = TestTransport() + let fileManager = try TestFileManager(options: fixture.options, dateProvider: fixture.currentDate, dispatchQueueWrapper: fixture.dispatchQueueWrapper) + let client = SentryClient(options: fixture.options, fileManager: fileManager, deleteOldEnvelopeItems: false) + Dynamic(client).transportAdapter = TestTransportAdapter(transports: [transport], options: fixture.options) + SentrySDKInternal.currentHub().bindClient(client) + SentrySDK.close() + + XCTAssertEqual(Options().shutdownTimeInterval, transport.flushInvocations.first) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testLogger_ReturnsSameInstanceOnMultipleCalls() { + givenSdkWithHub() + + let logger1 = SentrySDK.logger + let logger2 = SentrySDK.logger + + XCTAssertIdentical(logger1, logger2) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testClose_ResetsLogger() { + givenSdkWithHub() + + // Get logger instance + let logger1 = SentrySDK.logger + XCTAssertNotNil(logger1) + + // Close SDK + SentrySDK.close() + + // Start SDK again + givenSdkWithHub() + + // Get logger instance again + let logger2 = SentrySDK.logger + XCTAssertNotNil(logger2) + + // Should be a different instance + XCTAssertNotIdentical(logger1, logger2) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testLogger_WithLogsEnabled_CapturesLog() { + fixture.client.options.experimental.enableLogs = true + givenSdkWithHub() + + SentrySDK.logger.error(String(repeating: "S", count: 1_024 * 1_024)) + + let expectation = self.expectation(description: "Wait for async add.") + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + expectation.fulfill() + } + waitForExpectations(timeout: 5.0) + + XCTAssertEqual(fixture.client.captureLogsDataInvocations.count, 1) + } + + func testLogger_WithNoClient_DoesNotCaptureLog() { + fixture.client.options.experimental.enableLogs = true + let hubWithoutClient = SentryHub(client: nil, andScope: nil) + SentrySDKInternal.setCurrentHub(hubWithoutClient) + + SentrySDK.logger.error(String(repeating: "S", count: 1_024 * 1_024)) + + let expectation = self.expectation(description: "Wait for async add.") + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + expectation.fulfill() + } + waitForExpectations(timeout: 5.0) + + XCTAssertEqual(fixture.client.captureLogsDataInvocations.count, 0) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testLogger_WithLogsDisabled_DoesNotCaptureLog() { + fixture.client.options.experimental.enableLogs = false + givenSdkWithHub() + + SentrySDK.logger.error("foo") + XCTAssertEqual(fixture.client.captureLogsDataInvocations.count, 0) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testFlush_CallsFlushCorrectlyOnTransport() throws { + SentrySDK.start { options in + options.dsn = SentrySDKInternalTests.dsnAsString + options.removeAllIntegrations() + } + + let transport = TestTransport() + let fileManager = try TestFileManager(options: fixture.options, dateProvider: fixture.currentDate, dispatchQueueWrapper: fixture.dispatchQueueWrapper) + let client = SentryClient(options: fixture.options, fileManager: fileManager, deleteOldEnvelopeItems: false) + Dynamic(client).transportAdapter = TestTransportAdapter(transports: [transport], options: fixture.options) + SentrySDKInternal.currentHub().bindClient(client) + + let flushTimeout = 10.0 + SentrySDK.flush(timeout: flushTimeout) + + XCTAssertEqual(flushTimeout, transport.flushInvocations.first ?? 0.0, accuracy: 0.001) + } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testStartOnTheMainThread() throws { + + let expectation = XCTestExpectation(description: "SentrySDK start called") + + print("[Sentry] [TEST] [\(#file):\(#line) Dispatching to nonmain queue.") + DispatchQueue.global(qos: .utility).async { + print("[Sentry] [TEST] [\(#file):\(#line) About to start SDK from nonmain queue.") + SentrySDK.start { options in + print("[Sentry] [TEST] [\(#file):\(#line) configuring options.") + options.integrations = [ NSStringFromClass(MainThreadTestIntegration.self) ] + } + + // Since the SDK uses the dispatchqueue on the main queue, wait until it clears to fulfill the expectation + SentryDependencyContainer.sharedInstance().dispatchQueueWrapper.dispatchAsyncOnMainQueue { + expectation.fulfill() + } + } + + wait(for: [expectation], timeout: 5.0) + + let mainThreadIntegration = try XCTUnwrap(SentrySDKInternal.currentHub().installedIntegrations().first as? MainThreadTestIntegration) + + wait(for: [mainThreadIntegration.expectation], timeout: 5.0) + } + +#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) + + func testSetAppStartMeasurementConcurrently() { + let runtimeInitSystemTimestamp = SentryDependencyContainer.sharedInstance().dateProvider.date() + + func setAppStartMeasurement(_ queue: DispatchQueue, _ i: Int) { + queue.async { + let appStartTimestamp = SentryDependencyContainer.sharedInstance().dateProvider.date().addingTimeInterval(TimeInterval(i)) + let appStartMeasurement = TestData.getAppStartMeasurement( + type: .warm, + appStartTimestamp: appStartTimestamp, + runtimeInitSystemTimestamp: UInt64(runtimeInitSystemTimestamp.timeIntervalSince1970) + ) + SentrySDKInternal.setAppStartMeasurement(appStartMeasurement) + + expectation.fulfill() + } + } + + func createQueue() -> DispatchQueue { + return DispatchQueue(label: "SentrySDKTests", qos: .userInteractive, attributes: [.initiallyInactive]) + } + + let queue1 = createQueue() + let queue2 = createQueue() + + let amount = 100 + + let expectation = XCTestExpectation(description: "Wait for all measurements to be set") + expectation.expectedFulfillmentCount = amount * 2 + expectation.assertForOverFulfill = true + + for i in 0.. Bool { + print("[Sentry] [TEST] [\(#file):\(#line) starting install.") + dispatchPrecondition(condition: .onQueue(.main)) + + expectation.fulfill() + + return true + } + + public func uninstall() { + + } +} +// swiftlint:enable file_length diff --git a/Tests/SentryTests/SentrySDKTests.swift b/Tests/SentryTests/SentrySDKTests.swift index 71cb7f0cd8a..37039cb76d6 100644 --- a/Tests/SentryTests/SentrySDKTests.swift +++ b/Tests/SentryTests/SentrySDKTests.swift @@ -2,13 +2,13 @@ @_spi(Private) import SentryTestUtils import XCTest -// swiftlint:disable file_length class SentrySDKTests: XCTestCase { - + private static let dsnAsString = TestConstants.dsnAsString(username: "SentrySDKTests") - + private class Fixture { + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") let options: Options = { let options = Options.noIntegrations() options.dsn = SentrySDKTests.dsnAsString @@ -25,10 +25,11 @@ class SentrySDKTests: XCTestCase { @available(*, deprecated, message: "SentryUserFeedback is deprecated in favor of SentryFeedback.") let userFeedback: UserFeedback let feedback: SentryFeedback + let currentDate = TestCurrentDateProvider() - -#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) let dispatchQueueWrapper = TestSentryDispatchQueueWrapper() + +#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) let observer: SentryWatchdogTerminationScopeObserver let scopePersistentStore: TestSentryScopePersistentStore #endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) @@ -58,7 +59,7 @@ class SentrySDKTests: XCTestCase { scope.setTag(value: "value", key: "key") client = TestClient(options: options)! - hub = SentryHub(client: client, andScope: scope, andCrashWrapper: TestSentryCrashWrapper.sharedInstance(), andDispatchQueue: SentryDispatchQueueWrapper()) + hub = SentryHub(client: client, andScope: scope, andCrashWrapper: TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo), andDispatchQueue: SentryDispatchQueueWrapper()) userFeedback = UserFeedback(eventId: SentryId()) userFeedback.comments = "Again really?" @@ -70,7 +71,11 @@ class SentrySDKTests: XCTestCase { #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) options.dsn = SentrySDKTests.dsnAsString - let fileManager = try! TestFileManager(options: options) + let fileManager = try! TestFileManager( + options: options, + dateProvider: currentDate, + dispatchQueueWrapper: dispatchQueueWrapper + ) let breadcrumbProcessor = SentryWatchdogTerminationBreadcrumbProcessor(maxBreadcrumbs: 10, fileManager: fileManager) scopePersistentStore = try! XCTUnwrap(TestSentryScopePersistentStore(fileManager: fileManager)) let attributesProcessor = SentryWatchdogTerminationAttributesProcessor( @@ -89,13 +94,14 @@ class SentrySDKTests: XCTestCase { super.setUp() fixture = Fixture() } - + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") override func tearDown() { super.tearDown() givenSdkWithHubButNoClient() - if let autoSessionTracking = SentrySDK.currentHub().installedIntegrations().first(where: { it in + if let autoSessionTracking = SentrySDKInternal.currentHub().installedIntegrations().first(where: { it in it is SentryAutoSessionTrackingIntegration }) as? SentryAutoSessionTrackingIntegration { autoSessionTracking.stop() @@ -105,6 +111,7 @@ class SentrySDKTests: XCTestCase { } // Repro for: https://github.com/getsentry/sentry-cocoa/issues/1325 + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testStartWithZeroMaxBreadcrumbsOptionsDoesNotCrash() { SentrySDK.start { options in options.dsn = SentrySDKTests.dsnAsString @@ -113,10 +120,10 @@ class SentrySDKTests: XCTestCase { } SentrySDK.addBreadcrumb(Breadcrumb(level: SentryLevel.warning, category: "test")) - let breadcrumbs = Dynamic(SentrySDK.currentHub().scope).breadcrumbArray as [Breadcrumb]? + let breadcrumbs = Dynamic(SentrySDKInternal.currentHub().scope).breadcrumbArray as [Breadcrumb]? XCTAssertEqual(0, breadcrumbs?.count) } - + func testStartWithConfigureOptions() { SentrySDK.start { options in options.dsn = SentrySDKTests.dsnAsString @@ -125,7 +132,7 @@ class SentrySDKTests: XCTestCase { options.attachStacktrace = true } - let hub = SentrySDK.currentHub() + let hub = SentrySDKInternal.currentHub() XCTAssertNotNil(hub) XCTAssertNotNil(hub.installedIntegrations) XCTAssertNotNil(hub.getClient()?.options) @@ -143,52 +150,57 @@ class SentrySDKTests: XCTestCase { "SentryAutoSessionTrackingIntegration", "SentryNetworkTrackingIntegration" ] - if !SentryDependencyContainer.sharedInstance().crashWrapper.isBeingTraced() { + if !SentryDependencyContainer.sharedInstance().crashWrapper.isBeingTraced { expectedIntegrations.append("SentryANRTrackingIntegration") } assertIntegrationsInstalled(integrations: expectedIntegrations) } - func testStartStopBinaryImageCache() { + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testStartStopBinaryImageCache() throws { SentrySDK.start { options in options.debug = true options.removeAllIntegrations() } XCTAssertNotNil(SentryDependencyContainer.sharedInstance().binaryImageCache.cache) - XCTAssertGreaterThan(SentryDependencyContainer.sharedInstance().binaryImageCache.cache.count, 0) + let cache = try XCTUnwrap(SentryDependencyContainer.sharedInstance().binaryImageCache.cache) + XCTAssertGreaterThan(cache.count, 0) SentrySDK.close() XCTAssertNil(SentryDependencyContainer.sharedInstance().binaryImageCache.cache) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testStartWithConfigureOptions_NoDsn() throws { SentrySDK.start { options in options.debug = true options.removeAllIntegrations() } - let options = SentrySDK.currentHub().getClient()?.options + let options = SentrySDKInternal.currentHub().getClient()?.options XCTAssertNotNil(options, "Options should not be nil") XCTAssertNil(options?.parsedDsn) XCTAssertTrue(options?.enabled ?? false) XCTAssertEqual(true, options?.debug) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testStartWithConfigureOptions_WrongDsn() throws { SentrySDK.start { options in options.dsn = "wrong" options.removeAllIntegrations() } - let options = SentrySDK.currentHub().getClient()?.options + let options = SentrySDKInternal.currentHub().getClient()?.options XCTAssertNotNil(options, "Options should not be nil") XCTAssertTrue(options?.enabled ?? false) XCTAssertNil(options?.parsedDsn) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testStartWithConfigureOptions_BeforeSend() { var wasBeforeSendCalled = false SentrySDK.start { options in @@ -205,6 +217,7 @@ class SentrySDKTests: XCTestCase { XCTAssertTrue(wasBeforeSendCalled, "beforeSend was not called.") } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testStartWithScope() { let scope = Scope() scope.setUser(User(userId: "me")) @@ -217,8 +230,8 @@ class SentrySDKTests: XCTestCase { } options.removeAllIntegrations() } - XCTAssertEqual("me", SentrySDK.currentHub().scope.userObject?.userId) - XCTAssertIdentical(scope, SentrySDK.currentHub().scope) + XCTAssertEqual("me", SentrySDKInternal.currentHub().scope.userObject?.userId) + XCTAssertIdentical(scope, SentrySDKInternal.currentHub().scope) } func testDontStartInsideXcodePreview() { @@ -238,27 +251,31 @@ class SentrySDKTests: XCTestCase { func testDetectedStartUpCrash_DefaultValue() { XCTAssertFalse(SentrySDK.detectedStartUpCrash) } + + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testInstallIntegrations_NoIntegrations() { + SentrySDK.start { options in + options.removeAllIntegrations() + } - func testDetectedStartUpCrash() { - SentrySDK.setDetectedStartUpCrash(true) - XCTAssertEqual(SentrySDK.detectedStartUpCrash, true) + assertIntegrationsInstalled(integrations: []) + } - SentrySDK.setDetectedStartUpCrash(false) - XCTAssertFalse(SentrySDK.detectedStartUpCrash) + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testGlobalOptions() { + SentrySDK.start(options: fixture.options) + XCTAssertEqual(SentrySDKInternal.options, fixture.options) } - func testCaptureFatalEvent() { - let hub = TestHub(client: nil, andScope: nil) - SentrySDK.setCurrentHub(hub) + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + func testGlobalOptionsForPreview() { + startprocessInfoWrapperForPreview() - let event = fixture.event - SentrySDK.captureFatalEvent(event) - - XCTAssertEqual(1, hub.sentFatalEvents.count) - XCTAssertEqual(event.message, hub.sentFatalEvents.first?.message) - XCTAssertEqual(event.eventId, hub.sentFatalEvents.first?.eventId) + SentrySDK.start(options: fixture.options) + XCTAssertEqual(SentrySDKInternal.options, fixture.options) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureEvent() { givenSdkWithHub() @@ -267,6 +284,7 @@ class SentrySDKTests: XCTestCase { assertEventCaptured(expectedScope: fixture.scope) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureEventWithScope() { givenSdkWithHub() @@ -276,6 +294,7 @@ class SentrySDKTests: XCTestCase { assertEventCaptured(expectedScope: scope) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureEventWithScopeBlock_ScopePassedToHub() { givenSdkWithHub() @@ -284,6 +303,7 @@ class SentrySDKTests: XCTestCase { assertEventCaptured(expectedScope: fixture.scopeWithBlockApplied) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureEventWithScopeBlock_CreatesNewScope() { givenSdkWithHub() @@ -292,6 +312,7 @@ class SentrySDKTests: XCTestCase { assertHubScopeNotChanged() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureError() { givenSdkWithHub() @@ -300,6 +321,7 @@ class SentrySDKTests: XCTestCase { assertErrorCaptured(expectedScope: fixture.scope) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureErrorWithScope() { givenSdkWithHub() @@ -309,6 +331,7 @@ class SentrySDKTests: XCTestCase { assertErrorCaptured(expectedScope: scope) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureErrorWithScopeBlock_ScopePassedToHub() { givenSdkWithHub() @@ -317,6 +340,7 @@ class SentrySDKTests: XCTestCase { assertErrorCaptured(expectedScope: fixture.scopeWithBlockApplied) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureErrorWithScopeBlock_CreatesNewScope() { givenSdkWithHub() @@ -325,6 +349,7 @@ class SentrySDKTests: XCTestCase { assertHubScopeNotChanged() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureException() { givenSdkWithHub() @@ -333,6 +358,7 @@ class SentrySDKTests: XCTestCase { assertExceptionCaptured(expectedScope: fixture.scope) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureExceptionWithScope() { givenSdkWithHub() @@ -342,6 +368,7 @@ class SentrySDKTests: XCTestCase { assertExceptionCaptured(expectedScope: scope) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureExceptionWithScopeBlock_ScopePassedToHub() { givenSdkWithHub() @@ -350,6 +377,7 @@ class SentrySDKTests: XCTestCase { assertExceptionCaptured(expectedScope: fixture.scopeWithBlockApplied) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureExceptionWithScopeBlock_CreatesNewScope() { givenSdkWithHub() @@ -358,6 +386,7 @@ class SentrySDKTests: XCTestCase { assertHubScopeNotChanged() } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureMessageWithScopeBlock_ScopePassedToHub() { givenSdkWithHub() @@ -366,6 +395,7 @@ class SentrySDKTests: XCTestCase { assertMessageCaptured(expectedScope: fixture.scopeWithBlockApplied) } + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") func testCaptureMessageWithScopeBlock_CreatesNewScope() { givenSdkWithHub() @@ -373,931 +403,198 @@ class SentrySDKTests: XCTestCase { assertHubScopeNotChanged() } - - func testCaptureEnvelope() { - givenSdkWithHub() - - let envelope = SentryEnvelope(event: TestData.event) - SentrySDK.capture(envelope) - - XCTAssertEqual(1, fixture.client.captureEnvelopeInvocations.count) - XCTAssertEqual(envelope.header.eventId, fixture.client.captureEnvelopeInvocations.first?.header.eventId) - } - - func testStoreEnvelope() { - givenSdkWithHub() - - let envelope = SentryEnvelope(event: TestData.event) - SentrySDK.store(envelope) - - XCTAssertEqual(1, fixture.client.storedEnvelopeInvocations.count) - XCTAssertEqual(envelope.header.eventId, fixture.client.storedEnvelopeInvocations.first?.header.eventId) - } - - /// This is to prevent https://github.com/getsentry/sentry-cocoa/issues/4280 - /// With 8.33.0, writing an envelope could fail in the middle of the process, which the envelope - /// payload below simulates. The JSON stems from writing an envelope to disk with vast data - /// that leads to an OOM termination on v 8.33.0. - /// Running this test on v 8.33.0 leads to a crash. - func testStartSDK_WithCorruptedEnvelope() throws { - - let fileManager = try SentryFileManager(options: fixture.options) - - let corruptedEnvelopeData = Data(""" - {"event_id":"1990b5bc31904b7395fd07feb72daf1c","sdk":{"name":"sentry.cocoa","version":"8.33.0"}} - {"type":"test","length":50} - """.utf8) - - try corruptedEnvelopeData.write(to: URL(fileURLWithPath: "\(fileManager.envelopesPath)/corrupted-envelope.json")) - - SentrySDK.start(options: fixture.options) - - fileManager.deleteAllEnvelopes() - } - - func testStoreEnvelope_WhenNoClient_NoCrash() { - SentrySDK.store(SentryEnvelope(event: TestData.event)) - - XCTAssertEqual(0, fixture.client.storedEnvelopeInvocations.count) - } - - @available(*, deprecated, message: "-[SentrySDK captureUserFeedback:] is deprecated. -[SentrySDK captureFeedback:] is the new way. This test case can be removed in favor of testCaptureFeedback when -[SentrySDK captureUserFeedback:] is removed.") - func testCaptureUserFeedback() { - givenSdkWithHub() - - SentrySDK.capture(userFeedback: fixture.userFeedback) - let client = fixture.client - XCTAssertEqual(1, client.captureUserFeedbackInvocations.count) - if let actual = client.captureUserFeedbackInvocations.first { - let expected = fixture.userFeedback - XCTAssertEqual(expected.eventId, actual.eventId) - XCTAssertEqual(expected.name, actual.name) - XCTAssertEqual(expected.email, actual.email) - XCTAssertEqual(expected.comments, actual.comments) - } - } - - func testCaptureFeedback() { - givenSdkWithHub() - - SentrySDK.capture(feedback: fixture.feedback) - let client = fixture.client - XCTAssertEqual(1, client.captureFeedbackInvocations.count) - if let actual = client.captureFeedbackInvocations.first { - let expected = fixture.feedback - XCTAssertEqual(expected.eventId, actual.0.eventId) - XCTAssertEqual(expected.name, actual.0.name) - XCTAssertEqual(expected.email, actual.0.email) - XCTAssertEqual(expected.message, actual.0.message) - } - } - - func testSetUser_SetsUserToScopeOfHub() { - givenSdkWithHub() - - let user = TestData.user - SentrySDK.setUser(user) - - let actualScope = SentrySDK.currentHub().scope - let event = actualScope.applyTo(event: fixture.event, maxBreadcrumbs: 10) - XCTAssertEqual(event?.user, user) - } - - func testSetUserBeforeStartingSDK_LogsFatalMessage() throws { - // Arrange - let oldOutput = SentrySDKLog.getLogOutput() - - defer { - SentrySDKLog.setOutput(oldOutput) - } - - let logOutput = TestLogOutput() - SentrySDKLog.setLogOutput(logOutput) - - // Act - SentrySDK.setUser(nil) - // Assert - let actualLogMessage = try XCTUnwrap(logOutput.loggedMessages.first) - let expectedLogMessage = "The SDK is disabled, so setUser doesn't work. Please ensure to start the SDK before setting the user." - - XCTAssertTrue(actualLogMessage.contains(expectedLogMessage), "Expected log message to contain '\(expectedLogMessage)', but got '\(actualLogMessage)'") - } - - func testSetUserAFterStartingSDK_DoesNotLogFatalMessage() { + /// When events don't have debug meta the backend can't symbolicate the stack trace of events. + /// This is a regression test for https://github.com/getsentry/sentry-cocoa/issues/5334 + func testCaptureNonFatalEvent_HasDebugMeta() throws { // Arrange - let oldOutput = SentrySDKLog.getLogOutput() - - defer { - SentrySDKLog.setOutput(oldOutput) - } - - let logOutput = TestLogOutput() - SentrySDKLog.setLogOutput(logOutput) - - givenSdkWithHub() - - let user = TestData.user - - // Act - SentrySDK.setUser(user) - - //Assert - XCTAssertEqual(0, logOutput.loggedMessages.count, "Expected no log messages, but got \(logOutput.loggedMessages.count)") - } - - func testStartTransaction() throws { - givenSdkWithHub() - - let operation = "ui.load" - let name = "Load Main Screen" - let transaction = SentrySDK.startTransaction(name: name, operation: operation) - - XCTAssertEqual(operation, transaction.operation) - let tracer = try XCTUnwrap(transaction as? SentryTracer) - XCTAssertEqual(name, tracer.traceContext?.transaction) - - XCTAssertNil(SentrySDK.span) - } - - func testStartTransaction_WithBindToScope() throws { - givenSdkWithHub() - - let transaction = SentrySDK.startTransaction(name: fixture.transactionName, operation: fixture.operation, bindToScope: true) - - XCTAssertEqual(fixture.operation, transaction.operation) - let tracer = try XCTUnwrap(transaction as? SentryTracer) - XCTAssertEqual(fixture.transactionName, tracer.traceContext?.transaction) - XCTAssertEqual(.custom, tracer.transactionContext.nameSource) - - let newSpan = SentrySDK.span - - XCTAssert(transaction === newSpan) - } - - func testInstallIntegrations() throws { - let options = Options() - options.dsn = "mine" - options.integrations = ["SentryTestIntegration", "SentryTestIntegration", "IDontExist"] - - SentrySDK.start(options: options) - - assertIntegrationsInstalled(integrations: ["SentryTestIntegration"]) - let integration = SentrySDK.currentHub().installedIntegrations().first - if let testIntegration = integration as? SentryTestIntegration { - XCTAssertEqual(options.dsn, testIntegration.options.dsn) - XCTAssertEqual(options.integrations, testIntegration.options.integrations) - } - } - - func testInstallIntegrations_NoIntegrations() { SentrySDK.start { options in - options.removeAllIntegrations() + options.dsn = TestConstants.dsnAsString(username: "testCaptureNonFatalEvent_HasDebugMeta") } - assertIntegrationsInstalled(integrations: []) - } - - func testStartSession() { - givenSdkWithHub() - - SentrySDK.startSession() - - XCTAssertEqual(1, fixture.client.captureSessionInvocations.count) - - let actual = fixture.client.captureSessionInvocations.first - let expected = SentrySession(releaseName: fixture.options.releaseName ?? "", distinctId: "some-id") - - XCTAssertEqual(expected.flagInit, actual?.flagInit) - XCTAssertEqual(expected.errors, actual?.errors) - XCTAssertEqual(expected.sequence, actual?.sequence) - XCTAssertEqual(expected.releaseName, actual?.releaseName) - XCTAssertEqual(SentryDependencyContainer.sharedInstance().dateProvider.date(), actual?.started) - XCTAssertEqual(SentrySessionStatus.ok, actual?.status) - XCTAssertNil(actual?.timestamp) - XCTAssertNil(actual?.duration) - } - - func testEndSession() throws { - givenSdkWithHub() - - SentrySDK.startSession() - advanceTime(bySeconds: 1) - SentrySDK.endSession() - - XCTAssertEqual(2, fixture.client.captureSessionInvocations.count) - - let actual = try XCTUnwrap(fixture.client.captureSessionInvocations.invocations.last) - - XCTAssertNil(actual.flagInit) - XCTAssertEqual(0, actual.errors) - XCTAssertEqual(2, actual.sequence) - XCTAssertEqual(SentrySessionStatus.exited, actual.status) - XCTAssertEqual(fixture.options.releaseName ?? "", actual.releaseName) - XCTAssertEqual(1, actual.duration) - XCTAssertEqual(SentryDependencyContainer.sharedInstance().dateProvider.date(), actual.timestamp) - } - - func testGlobalOptions() { - SentrySDK.start(options: fixture.options) - XCTAssertEqual(SentrySDK.options, fixture.options) - } - - func testGlobalOptionsForPreview() { - startprocessInfoWrapperForPreview() - - SentrySDK.start(options: fixture.options) - XCTAssertEqual(SentrySDK.options, fixture.options) - } - -#if SENTRY_HAS_UIKIT - func testSetAppStartMeasurement_CallsPrivateSDKCallback() { - let appStartMeasurement = TestData.getAppStartMeasurement(type: .warm) - - var callbackCalled = false - PrivateSentrySDKOnly.onAppStartMeasurementAvailable = { measurement in - XCTAssertEqual(appStartMeasurement, measurement) - callbackCalled = true - } - - SentrySDK.setAppStartMeasurement(appStartMeasurement) - XCTAssertTrue(callbackCalled) - } - - func testSetAppStartMeasurement_NoCallback_CallbackNotCalled() { - let appStartMeasurement = TestData.getAppStartMeasurement(type: .warm) - - SentrySDK.setAppStartMeasurement(appStartMeasurement) - - XCTAssertEqual(SentrySDK.getAppStartMeasurement(), appStartMeasurement) - } -#endif // SENTRY_HAS_UIKIT - - func testSDKStartInvocations() { - XCTAssertEqual(0, SentrySDK.startInvocations) - - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.removeAllIntegrations() - } - - XCTAssertEqual(1, SentrySDK.startInvocations) - } - - func testSDKStartTimestamp() { - let currentDateProvider = TestCurrentDateProvider() - SentryDependencyContainer.sharedInstance().dateProvider = currentDateProvider - - XCTAssertNil(SentrySDK.startTimestamp) - - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.removeAllIntegrations() - } - - XCTAssertEqual(SentrySDK.startTimestamp, currentDateProvider.date()) - - SentrySDK.close() - XCTAssertNil(SentrySDK.startTimestamp) - } - - func testIsEnabled() { - XCTAssertFalse(SentrySDK.isEnabled) - - SentrySDK.capture(message: "message") - XCTAssertFalse(SentrySDK.isEnabled) - - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.removeAllIntegrations() - } - XCTAssertTrue(SentrySDK.isEnabled) - - SentrySDK.close() - XCTAssertFalse(SentrySDK.isEnabled) - - SentrySDK.capture(message: "message") - XCTAssertFalse(SentrySDK.isEnabled) - - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.removeAllIntegrations() - } - XCTAssertTrue(SentrySDK.isEnabled) - } - - func testClose_ResetsDependencyContainer() { - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.removeAllIntegrations() - } - - let first = SentryDependencyContainer.sharedInstance() - - SentrySDK.close() - - let second = SentryDependencyContainer.sharedInstance() - - XCTAssertNotEqual(first, second) - } - - func testClose_ClearsIntegrations() { - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.swiftAsyncStacktraces = true - options.setIntegrations([SentrySwiftAsyncIntegration.self]) - } - - let hub = SentrySDK.currentHub() - XCTAssertEqual(1, hub.installedIntegrations().count) - SentrySDK.close() - XCTAssertEqual(0, hub.installedIntegrations().count) - assertIntegrationsInstalled(integrations: []) - } - -#if SENTRY_HAS_UIKIT - func testClose_StopsAppStateManager() { - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.tracesSampleRate = 1 - options.removeAllIntegrations() - } - - let appStateManager = SentryDependencyContainer.sharedInstance().appStateManager - XCTAssertEqual(appStateManager.startCount, 1) - - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.tracesSampleRate = 1 - options.removeAllIntegrations() - } - - XCTAssertEqual(appStateManager.startCount, 2) - - SentrySDK.close() - - XCTAssertEqual(appStateManager.startCount, 0) - - let stateAfterStop = fixture.fileManager.readAppState() - XCTAssertFalse(stateAfterStop!.isSDKRunning) - } -#endif - -#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) - func testReportFullyDisplayed() { - fixture.options.enableTimeToFullDisplayTracing = true - - let testTTDTracker = TestTimeToDisplayTracker(waitForFullDisplay: true) - let performanceTracker = Dynamic(SentryDependencyContainer.sharedInstance().uiViewControllerPerformanceTracker) - performanceTracker.currentTTDTracker = testTTDTracker - - // Start SDK after setting up the tracker to ensure we're changing the tracker during it's initialization, - // because some initialization logic happens on a BG thread and we would end up in a race condition. - SentrySDK.start(options: fixture.options) - - SentrySDK.reportFullyDisplayed() - - XCTAssertTrue(testTTDTracker.registerFullDisplayCalled) - } -#endif - -#if os(iOS) - func testSentryUIDeviceWrapperStarted() { - let deviceWrapper = TestSentryUIDeviceWrapper() - SentryDependencyContainer.sharedInstance().uiDeviceWrapper = deviceWrapper - SentrySDK.start(options: fixture.options) - XCTAssertTrue(deviceWrapper.started) - } - - func testSentryUIDeviceWrapperStopped() { - let deviceWrapper = TestSentryUIDeviceWrapper() - SentryDependencyContainer.sharedInstance().uiDeviceWrapper = deviceWrapper - SentrySDK.start(options: fixture.options) - SentrySDK.close() - XCTAssertFalse(deviceWrapper.started) - } - - /// Ensure to start the UIDeviceWrapper before initializing the hub, so enrich scope sets the correct OS version. - func testStartSDK_ScopeContextContainsOSVersion() throws { - let expectation = expectation(description: "MainThreadTestIntegration install called") - MainThreadTestIntegration.expectation = expectation - - DispatchQueue.global(qos: .default).async { - SentrySDK.start { options in - options.integrations = [ NSStringFromClass(MainThreadTestIntegration.self) ] - } - } - - wait(for: [expectation], timeout: 1.0) - - let os = try XCTUnwrap (SentrySDK.currentHub().scope.contextDictionary["os"] as? [String: Any]) -#if !targetEnvironment(macCatalyst) - XCTAssertEqual(UIDevice.current.systemVersion, os["version"] as? String) -#endif - } -#endif - - func testResumeAndPauseAppHangTracking() { - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.setIntegrations([SentryANRTrackingIntegration.self]) - } - - let client = fixture.client - SentrySDK.currentHub().bindClient(client) - - let anrTrackingIntegration = SentrySDK.currentHub().getInstalledIntegration(SentryANRTrackingIntegration.self) - - SentrySDK.pauseAppHangTracking() - Dynamic(anrTrackingIntegration).anrDetectedWithType(SentryANRType.unknown) - XCTAssertEqual(0, client.captureEventWithScopeInvocations.count) - - SentrySDK.resumeAppHangTracking() - Dynamic(anrTrackingIntegration).anrDetectedWithType(SentryANRType.unknown) - - if SentryDependencyContainer.sharedInstance().crashWrapper.isBeingTraced() { - XCTAssertEqual(0, client.captureEventWithScopeInvocations.count) - } else { - XCTAssertEqual(1, client.captureEventWithScopeInvocations.count) - } - } - - func testResumeAndPauseAppHangTracking_ANRTrackingNotInstalled() { - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.removeAllIntegrations() - } - - let client = fixture.client - SentrySDK.currentHub().bindClient(client) - - // Both invocations do nothing - SentrySDK.pauseAppHangTracking() - SentrySDK.resumeAppHangTracking() - } - - func testClose_SetsClientToNil() { - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.removeAllIntegrations() - } - - SentrySDK.close() - - XCTAssertNil(SentrySDK.currentHub().client()) - } - - func testClose_ClosesClient() { - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.removeAllIntegrations() - } - - let client = SentrySDK.currentHub().client() - SentrySDK.close() - - XCTAssertFalse(client?.isEnabled ?? true) - } - - func testClose_CallsFlushCorrectlyOnTransport() throws { - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.removeAllIntegrations() - } - - let transport = TestTransport() - let client = SentryClient(options: fixture.options, fileManager: try TestFileManager(options: fixture.options), deleteOldEnvelopeItems: false) - Dynamic(client).transportAdapter = TestTransportAdapter(transports: [transport], options: fixture.options) - SentrySDK.currentHub().bindClient(client) - SentrySDK.close() - - XCTAssertEqual(Options().shutdownTimeInterval, transport.flushInvocations.first) - } - - func testFlush_CallsFlushCorrectlyOnTransport() throws { - SentrySDK.start { options in - options.dsn = SentrySDKTests.dsnAsString - options.removeAllIntegrations() - } - - let transport = TestTransport() - let client = SentryClient(options: fixture.options, fileManager: try TestFileManager(options: fixture.options), deleteOldEnvelopeItems: false) - Dynamic(client).transportAdapter = TestTransportAdapter(transports: [transport], options: fixture.options) - SentrySDK.currentHub().bindClient(client) - - let flushTimeout = 10.0 - SentrySDK.flush(timeout: flushTimeout) - - XCTAssertEqual(flushTimeout, transport.flushInvocations.first) - } - - func testStartOnTheMainThread() throws { - let expectation = expectation(description: "MainThreadTestIntegration install called") - MainThreadTestIntegration.expectation = expectation - - print("[Sentry] [TEST] [\(#file):\(#line) Dispatching to nonmain queue.") - DispatchQueue.global(qos: .background).async { - print("[Sentry] [TEST] [\(#file):\(#line) About to start SDK from nonmain queue.") - SentrySDK.start { options in - print("[Sentry] [TEST] [\(#file):\(#line) configuring options.") - options.integrations = [ NSStringFromClass(MainThreadTestIntegration.self) ] - } - } - - wait(for: [expectation], timeout: 1.0) - - let mainThreadIntegration = try XCTUnwrap(SentrySDK.currentHub().installedIntegrations().first as? MainThreadTestIntegration) - XCTAssert(mainThreadIntegration.installedInTheMainThread, "SDK is not being initialized in the main thread") - - } - -#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) - - func testSetAppStartMeasurementConcurrently() { - let runtimeInitSystemTimestamp = SentryDependencyContainer.sharedInstance().dateProvider.date() - - func setAppStartMeasurement(_ queue: DispatchQueue, _ i: Int) { - group.enter() - queue.async { - let appStartTimestamp = SentryDependencyContainer.sharedInstance().dateProvider.date().addingTimeInterval(TimeInterval(i)) - let appStartMeasurement = TestData.getAppStartMeasurement( - type: .warm, - appStartTimestamp: appStartTimestamp, - runtimeInitSystemTimestamp: UInt64(runtimeInitSystemTimestamp.timeIntervalSince1970) - ) - SentrySDK.setAppStartMeasurement(appStartMeasurement) - group.leave() - } - } + let fileManager = try XCTUnwrap(SentrySDKInternal.currentHub().getClient()?.fileManager) + fileManager.deleteAllEnvelopes() - func createQueue() -> DispatchQueue { - return DispatchQueue(label: "SentrySDKTests", qos: .userInteractive, attributes: [.initiallyInactive]) + defer { + fileManager.deleteAllEnvelopes() } - let queue1 = createQueue() - let queue2 = createQueue() - let group = DispatchGroup() - - let amount = 100 + // Act + SentrySDK.capture(message: "Test message") + // Ensures that the capture envelope is written to disk before we read it. + SentrySDK.flush(timeout: 0.1) - for i in 0...amount { - setAppStartMeasurement(queue1, i) - setAppStartMeasurement(queue2, i) + // Assert + let eventEnvelopeItems = try fileManager.getAllEnvelopes().map { fileContent in + return try XCTUnwrap(SentrySerialization.envelope(with: fileContent.contents)) + }.flatMap { envelope in + return envelope.items.filter { $0.header.type == SentryEnvelopeItemTypes.event } } - queue1.activate() - queue2.activate() - group.waitWithTimeout(timeout: 100) + XCTAssertEqual(eventEnvelopeItems.count, 1, "Expected exactly one event envelope item, but got \(eventEnvelopeItems.count)") + let eventEnvelopeItem = try XCTUnwrap(eventEnvelopeItems.first) - let timestamp = SentryDependencyContainer.sharedInstance().dateProvider.date().addingTimeInterval(TimeInterval(amount)) - XCTAssertEqual(timestamp, SentrySDK.getAppStartMeasurement()?.appStartTimestamp) - } + let event = try XCTUnwrap( SentryEventDecoder.decodeEvent(jsonData: XCTUnwrap(eventEnvelopeItem.data))) - func testMovesBreadcrumbsToPreviousBreadcrumbs() throws { - let options = Options() - options.dsn = SentrySDKTests.dsnAsString + let debugMetas = try XCTUnwrap(event.debugMeta, "Expected event to have debug meta but got nil") + // During local testing we got 6 debug metas, but to avoid flakiness in CI we only check for 3. + XCTAssertGreaterThanOrEqual(debugMetas.count, 3, "Expected debug meta to have at least 3 items, but got \(debugMetas.count)") - let fileManager = try TestFileManager(options: options) - let breadcrumbProcessor = SentryWatchdogTerminationBreadcrumbProcessor(maxBreadcrumbs: 10, fileManager: fileManager) - let dispatchQueueWrapper = TestSentryDispatchQueueWrapper() - let scopePersistentStore = try XCTUnwrap(TestSentryScopePersistentStore(fileManager: fileManager)) - let attributesProcessor = SentryWatchdogTerminationAttributesProcessor( - withDispatchQueueWrapper: dispatchQueueWrapper, - scopePersistentStore: scopePersistentStore - ) - let observer = SentryWatchdogTerminationScopeObserver(breadcrumbProcessor: breadcrumbProcessor, attributesProcessor: attributesProcessor) - let serializedBreadcrumb = TestData.crumb.serialize() - - for _ in 0..<3 { - observer.addSerializedBreadcrumb(serializedBreadcrumb) + for debugMeta in debugMetas { + XCTAssertEqual(debugMeta.type, "macho") + XCTAssertNotNil(debugMeta.debugID) + XCTAssertNotNil(debugMeta.imageAddress) + XCTAssertNotNil(debugMeta.imageSize) } - - SentrySDK.start(options: options) - - let result = fileManager.readPreviousBreadcrumbs() - XCTAssertEqual(result.count, 3) } - func testStartWithOptions_shouldMoveCurrentContextFileToPreviousFile() throws { - // -- Arrange -- - fixture.observer.setContext([ - "a": ["b": "c"] - ]) - - // Wait for the observer to complete - let expectation = XCTestExpectation(description: "setContext completes") - fixture.dispatchQueueWrapper.dispatchAsync { - // Dispatching a block on the same queue will be run after the context processor. - expectation.fulfill() - } - wait(for: [expectation], timeout: 1.0) - - // Delete the previous context file if it exists - fixture.scopePersistentStore.deleteAllPreviousState() - // Sanity-check for the pre-condition - let previousContext = fixture.scopePersistentStore.readPreviousContextFromDisk() - XCTAssertNil(previousContext) - - // -- Act -- - SentrySDK.start(options: fixture.options) - - // -- Assert -- - let result = try XCTUnwrap(fixture.scopePersistentStore.readPreviousContextFromDisk()) - XCTAssertEqual(result.count, 1) - let value = try XCTUnwrap(result["a"] as? [String: String]) - XCTAssertEqual(value["b"], "c") - } + // MARK: - Logger Flush Tests - func testStartWithOptions_shouldMoveCurrentUserFileToPreviousFile() throws { - // -- Arrange -- - fixture.observer.setUser(User(userId: "user1234")) - - // Wait for the observer to complete - let expectation = XCTestExpectation(description: "setUser completes") - fixture.dispatchQueueWrapper.dispatchAsync { - // Dispatching a block on the same queue will be run after the context processor. - expectation.fulfill() - } - wait(for: [expectation], timeout: 1.0) - - // Delete the previous context file if it exists - fixture.scopePersistentStore.deleteAllPreviousState() - // Sanity-check for the pre-condition - let previousUser = fixture.scopePersistentStore.readPreviousUserFromDisk() - XCTAssertNil(previousUser) - - // -- Act -- - SentrySDK.start(options: fixture.options) - - // -- Assert -- - let result = try XCTUnwrap(fixture.scopePersistentStore.readPreviousUserFromDisk()) - XCTAssertEqual(result.userId, "user1234") + func testFlush_CallsLoggerCaptureLogs() { + fixture.client.options.experimental.enableLogs = true + SentrySDKInternal.setCurrentHub(fixture.hub) + SentrySDKInternal.setStart(with: fixture.client.options) + + // Add a log to ensure there's something to flush + SentrySDK.logger.info("Test log message") + + // Initially no logs should be sent (they're buffered) + XCTAssertEqual(fixture.client.captureLogsDataInvocations.count, 0) + + // Flush the SDK + SentrySDK.flush(timeout: 1.0) + + // Now logs should be sent + XCTAssertEqual(fixture.client.captureLogsDataInvocations.count, 1) } - func testStartWithOptions_shouldMoveCurrentDistFileToPreviousFile() throws { - // -- Arrange -- - fixture.observer.setDist("dist-string") - - // Wait for the observer to complete - let expectation = XCTestExpectation(description: "setDist completes") - fixture.dispatchQueueWrapper.dispatchAsync { - // Dispatching a block on the same queue will be run after the context processor. - expectation.fulfill() - } - wait(for: [expectation], timeout: 1.0) - // Delete the previous context file if it exists - fixture.scopePersistentStore.deleteAllPreviousState() - // Sanity-check for the pre-condition - let previousUser = fixture.scopePersistentStore.readPreviousDistFromDisk() - XCTAssertNil(previousUser) - - // -- Act -- - SentrySDK.start(options: fixture.options) - - // -- Assert -- - let result = try XCTUnwrap(fixture.scopePersistentStore.readPreviousDistFromDisk()) - XCTAssertEqual(result, "dist-string") - } - - func testStartWithOptions_shouldMoveCurrentEnvironmentFileToPreviousFile() throws { - // -- Arrange -- - fixture.observer.setEnvironment("prod-string") - - // Wait for the observer to complete - let expectation = XCTestExpectation(description: "setEnvironment completes") - fixture.dispatchQueueWrapper.dispatchAsync { - // Dispatching a block on the same queue will be run after the context processor. - expectation.fulfill() - } - wait(for: [expectation], timeout: 1.0) - // Delete the previous context file if it exists - fixture.scopePersistentStore.deleteAllPreviousState() - // Sanity-check for the pre-condition - let previousUser = fixture.scopePersistentStore.readPreviousEnvironmentFromDisk() - XCTAssertNil(previousUser) - - // -- Act -- - SentrySDK.start(options: fixture.options) - - // -- Assert -- - let result = try XCTUnwrap(fixture.scopePersistentStore.readPreviousEnvironmentFromDisk()) - XCTAssertEqual(result, "prod-string") - } - - func testStartWithOptions_shouldMoveCurrentExtraFileToPreviousFile() throws { - // -- Arrange -- - fixture.observer.setExtras(["extra1": "value1", "extra2": "value2"]) - - // Wait for the observer to complete - let expectation = XCTestExpectation(description: "setExtras completes") - fixture.dispatchQueueWrapper.dispatchAsync { - // Dispatching a block on the same queue will be run after the context processor. - expectation.fulfill() - } - wait(for: [expectation], timeout: 1.0) - // Delete the previous context file if it exists - fixture.scopePersistentStore.deleteAllPreviousState() + func testClose_CallsLoggerCaptureLogs() { + fixture.client.options.experimental.enableLogs = true + SentrySDKInternal.setCurrentHub(fixture.hub) + SentrySDKInternal.setStart(with: fixture.client.options) - // Sanity-check for the pre-condition - let previousExtras = fixture.scopePersistentStore.readPreviousExtrasFromDisk() - XCTAssertNil(previousExtras) - - // -- Act -- - SentrySDK.start(options: fixture.options) - - // -- Assert -- - let result = try XCTUnwrap(fixture.scopePersistentStore.readPreviousExtrasFromDisk()) - XCTAssertEqual(result.count, 2) - XCTAssertEqual(result["extra1"] as? String, "value1") - XCTAssertEqual(result["extra2"] as? String, "value2") + // Add a log to ensure there's something to flush + SentrySDK.logger.info("Test log message") + + // Initially no logs should be sent (they're buffered) + XCTAssertEqual(fixture.client.captureLogsDataInvocations.count, 0) + + // Close the SDK + SentrySDK.close() + + // Now logs should be sent + XCTAssertEqual(fixture.client.captureLogsDataInvocations.count, 1) } - - func testStartWithOptions_shouldMoveCurrentFingerprintFileToPreviousFile() throws { - // -- Arrange -- - fixture.observer.setFingerprint(["fingerprint1", "fingerprint2"]) - - // Wait for the observer to complete - let expectation = XCTestExpectation(description: "setFingerprint completes") - fixture.dispatchQueueWrapper.dispatchAsync { - // Dispatching a block on the same queue will be run after the context processor. - expectation.fulfill() - } - wait(for: [expectation], timeout: 1.0) - - // Delete the previous fingerprint file if it exists - fixture.scopePersistentStore.deleteAllPreviousState() - // Sanity-check for the pre-condition - let previousFingerprint = fixture.scopePersistentStore.readPreviousFingerprintFromDisk() - XCTAssertNil(previousFingerprint) - - // -- Act -- - SentrySDK.start(options: fixture.options) - - // -- Assert -- - let result = try XCTUnwrap(fixture.scopePersistentStore.readPreviousFingerprintFromDisk()) - XCTAssertEqual(result.count, 2) - XCTAssertEqual(result[0], "fingerprint1") - XCTAssertEqual(result[1], "fingerprint2") + + func testLogger_RecreatedWhenSDKStartedAfterAccess() { + // Access logger before SDK is started + let loggerBeforeStart = SentrySDK.logger + + // Now properly start the SDK using internal APIs + fixture.client.options.experimental.enableLogs = true + SentrySDKInternal.setCurrentHub(fixture.hub) + SentrySDKInternal.setStart(with: fixture.client.options) + + // Access logger again after SDK is started + let loggerAfterStart = SentrySDK.logger + + // Verify it's a different instance (recreated) + XCTAssertNotIdentical(loggerBeforeStart, loggerAfterStart) + + // Verify the new logger can actually capture logs + loggerAfterStart.info("Test log message") + + // Force flush by closing the SDK + SentrySDK.close() + + // Verify log was captured + XCTAssertEqual(fixture.client.captureLogsDataInvocations.count, 1) } - func testStartWithOptions_shouldMoveCurrentTagsFileToPreviousFile() throws { - // -- Arrange -- - fixture.observer.setTags(["tag1": "value1", "tag2": "value2"]) - - // Wait for the observer to complete - let expectation = XCTestExpectation(description: "setTags completes") - fixture.dispatchQueueWrapper.dispatchAsync { - // Dispatching a block on the same queue will be run after the context processor. + func testLogger_WhenLogsDisabled() { + // Start SDK with logs disabled + fixture.client.options.experimental.enableLogs = false + SentrySDKInternal.setCurrentHub(fixture.hub) + SentrySDKInternal.setStart(with: fixture.client.options) + + // Access logger + let logger = SentrySDK.logger + + // Verify that logs are not captured when disabled + logger.info("Test log message") + + // Wait a bit for async processing + let expectation = self.expectation(description: "Wait for log capture") + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { expectation.fulfill() } - wait(for: [expectation], timeout: 1.0) - - // Delete the previous tags file if it exists - fixture.scopePersistentStore.deleteAllPreviousState() - // Sanity-check for the pre-condition - let previousTags = fixture.scopePersistentStore.readPreviousTagsFromDisk() - XCTAssertNil(previousTags) - - // -- Act -- - SentrySDK.start(options: fixture.options) - - // -- Assert -- - let result = try XCTUnwrap(fixture.scopePersistentStore.readPreviousTagsFromDisk()) - XCTAssertEqual(result.count, 2) - XCTAssertEqual(result["tag1"], "value1") - XCTAssertEqual(result["tag2"], "value2") - } -#endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) - -#if os(macOS) - func testCaptureCrashOnException() { - givenSdkWithHub() + waitForExpectations(timeout: 5.0) - SentrySDK.captureCrashOn(exception: fixture.exception) - - let client = fixture.client - XCTAssertEqual(1, client.captureExceptionWithScopeInvocations.count) - XCTAssertNotEqual(fixture.exception, client.captureExceptionWithScopeInvocations.first?.exception) - XCTAssertEqual(fixture.exception.name, client.captureExceptionWithScopeInvocations.first?.exception.name) - XCTAssertEqual(fixture.exception.reason, client.captureExceptionWithScopeInvocations.first?.exception.reason) - XCTAssertEqual(fixture.scope, client.captureExceptionWithScopeInvocations.first?.scope) + // Verify no logs were captured + XCTAssertEqual(fixture.client.captureLogsDataInvocations.count, 0) } -#endif // os(macOS) } -private extension SentrySDKTests { - func givenSdkWithHub() { - SentrySDK.setCurrentHub(fixture.hub) - SentrySDK.setStart(fixture.options) - } - - func givenSdkWithHubButNoClient() { - SentrySDK.setCurrentHub(SentryHub(client: nil, andScope: nil)) - SentrySDK.setStart(fixture.options) - } - - func assertIntegrationsInstalled(integrations: [String]) { - XCTAssertEqual(integrations.count, SentrySDK.currentHub().installedIntegrations().count) - integrations.forEach { integration in - if let integrationClass = NSClassFromString(integration) { - XCTAssertTrue(SentrySDK.currentHub().isIntegrationInstalled(integrationClass), "\(integration) not installed") - } else { - XCTFail("Integration \(integration) not installed.") - } - } - } - - func assertEventCaptured(expectedScope: Scope) { +extension SentrySDKTests { + private func assertEventCaptured(expectedScope: Scope) { let client = fixture.client XCTAssertEqual(1, client.captureEventWithScopeInvocations.count) XCTAssertEqual(fixture.event, client.captureEventWithScopeInvocations.first?.event) XCTAssertEqual(expectedScope, client.captureEventWithScopeInvocations.first?.scope) } - - func assertErrorCaptured(expectedScope: Scope) { + + private func assertErrorCaptured(expectedScope: Scope) { let client = fixture.client XCTAssertEqual(1, client.captureErrorWithScopeInvocations.count) XCTAssertEqual(fixture.error.localizedDescription, client.captureErrorWithScopeInvocations.first?.error.localizedDescription) XCTAssertEqual(expectedScope, client.captureErrorWithScopeInvocations.first?.scope) } - - func assertExceptionCaptured(expectedScope: Scope) { + + private func assertExceptionCaptured(expectedScope: Scope) { let client = fixture.client XCTAssertEqual(1, client.captureExceptionWithScopeInvocations.count) XCTAssertEqual(fixture.exception, client.captureExceptionWithScopeInvocations.first?.exception) XCTAssertEqual(expectedScope, client.captureExceptionWithScopeInvocations.first?.scope) } - - func assertMessageCaptured(expectedScope: Scope) { + + private func assertMessageCaptured(expectedScope: Scope) { let client = fixture.client XCTAssertEqual(1, client.captureMessageWithScopeInvocations.count) XCTAssertEqual(fixture.message, client.captureMessageWithScopeInvocations.first?.message) XCTAssertEqual(expectedScope, client.captureMessageWithScopeInvocations.first?.scope) } - - func assertHubScopeNotChanged() { - let hubScope = SentrySDK.currentHub().scope + + private func assertHubScopeNotChanged() { + let hubScope = SentrySDKInternal.currentHub().scope XCTAssertEqual(fixture.scope, hubScope) } - - func advanceTime(bySeconds: TimeInterval) { - fixture.currentDate.setDate(date: SentryDependencyContainer.sharedInstance().dateProvider.date().addingTimeInterval(bySeconds)) - } - - func startprocessInfoWrapperForPreview() { - let testProcessInfoWrapper = TestSentryNSProcessInfoWrapper() + + private func startprocessInfoWrapperForPreview() { + let testProcessInfoWrapper = MockSentryProcessInfo() testProcessInfoWrapper.overrides.environment = ["XCODE_RUNNING_FOR_PREVIEWS": "1"] SentryDependencyContainer.sharedInstance().processInfoWrapper = testProcessInfoWrapper } -} - -/// Tests in this class aren't part of SentrySDKTests because we need would need to undo a bunch of operations -/// that are done in the setup. -class SentrySDKWithSetupTests: XCTestCase { - - func testAccessingHubAndOptions_NoDeadlock() { - let concurrentQueue = DispatchQueue(label: "concurrent", attributes: .concurrent) - - let expectation = expectation(description: "no deadlock") - expectation.expectedFulfillmentCount = 20 - - SentrySDK.setStart(Options()) - - for _ in 0..<10 { - concurrentQueue.async { - SentrySDK.currentHub().capture(message: "mess") - SentrySDK.setCurrentHub(nil) - - expectation.fulfill() - } - - concurrentQueue.async { - let hub = SentryHub(client: nil, andScope: nil) - XCTAssertNotNil(hub) - - expectation.fulfill() + + private func assertIntegrationsInstalled(integrations: [String]) { + XCTAssertEqual(integrations.count, SentrySDKInternal.currentHub().installedIntegrations().count) + integrations.forEach { integration in + if let integrationClass = NSClassFromString(integration) { + XCTAssertTrue(SentrySDKInternal.currentHub().isIntegrationInstalled(integrationClass), "\(integration) not installed") + } else { + XCTFail("Integration \(integration) not installed.") } } - - wait(for: [expectation], timeout: 5.0) } -} - -public class MainThreadTestIntegration: NSObject, SentryIntegrationProtocol { - - static var expectation: XCTestExpectation? - - public var installedInTheMainThread = false - public func install(with options: Options) -> Bool { - print("[Sentry] [TEST] [\(#file):\(#line) starting install.") - installedInTheMainThread = Thread.isMainThread - MainThreadTestIntegration.expectation?.fulfill() - MainThreadTestIntegration.expectation = nil - return true + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + private func givenSdkWithHubButNoClient() { + SentrySDKInternal.setCurrentHub(SentryHub(client: nil, andScope: nil)) + SentrySDKInternal.setStart(with: fixture.options) } - public func uninstall() { + @available(*, deprecated, message: "This is deprecated because SentryOptions integrations is deprecated") + private func givenSdkWithHub() { + SentrySDKInternal.setCurrentHub(fixture.hub) + SentrySDKInternal.setStart(with: fixture.options) } } -// swiftlint:enable file_length diff --git a/Tests/SentryTests/SentrySDKThreadTests.swift b/Tests/SentryTests/SentrySDKThreadTests.swift index 223bf63de2d..e46433970e9 100644 --- a/Tests/SentryTests/SentrySDKThreadTests.swift +++ b/Tests/SentryTests/SentrySDKThreadTests.swift @@ -28,7 +28,7 @@ final class SentrySDKThreadTests: XCTestCase { sut.bindClient(nil) } - wait(for: [exp], timeout: 1.0) + wait(for: [exp], timeout: 10.0) } } } diff --git a/Tests/SentryTests/SentryScopeSwiftTests.swift b/Tests/SentryTests/SentryScopeSwiftTests.swift index 7565dfaa734..ffa64c0dcfb 100644 --- a/Tests/SentryTests/SentryScopeSwiftTests.swift +++ b/Tests/SentryTests/SentryScopeSwiftTests.swift @@ -1,3 +1,4 @@ +@_spi(Private) import Sentry import SentryTestUtils import XCTest diff --git a/Tests/SentryTests/SentryScreenShotTests.swift b/Tests/SentryTests/SentryScreenshotSourceTests.swift similarity index 68% rename from Tests/SentryTests/SentryScreenShotTests.swift rename to Tests/SentryTests/SentryScreenshotSourceTests.swift index b4c86e9810d..c30399ddb66 100644 --- a/Tests/SentryTests/SentryScreenShotTests.swift +++ b/Tests/SentryTests/SentryScreenshotSourceTests.swift @@ -3,13 +3,24 @@ import XCTest #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) -class SentryScreenShotTests: XCTestCase { +class SentryScreenshotSourceTests: XCTestCase { private class Fixture { - - let uiApplication = TestSentryUIApplication(notificationCenterWrapper: TestNSNotificationCenterWrapper(), dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) - - var sut: SentryScreenshot { - return SentryScreenshot() + let uiApplication = TestSentryUIApplication() + let renderer = TestSentryViewRenderer() + let photographer: TestSentryViewPhotographer + + let mockImage = UIImage() + + init() { + renderer.mockedReturnValue = mockImage + photographer = TestSentryViewPhotographer( + renderer: renderer, + redactOptions: SentryRedactDefaultOptions() + ) + } + + var sut: SentryScreenshotSource { + return SentryScreenshotSource(photographer: photographer) } } @@ -26,17 +37,18 @@ class SentryScreenShotTests: XCTestCase { clearTestState() } - func test_IsMainThread() { + func testappScreenshotsFromMainThread_IsMainThread() throws { // -- Arrange -- let testWindow = TestWindow(frame: CGRect(x: 0, y: 0, width: 10, height: 10)) var isMainThread = false - - testWindow.onDrawHierarchy = { + let onRenderCalledExpectation = self.expectation(description: "onDrawHierarchy called") + + fixture.uiApplication.windows = [testWindow] + fixture.renderer.onRender = { _ in + onRenderCalledExpectation.fulfill() isMainThread = Thread.isMainThread } - fixture.uiApplication.windows = [testWindow] - // -- Act -- let expect = expectation(description: "Screenshot") let queue = DispatchQueue(label: "TestQueue") @@ -47,28 +59,29 @@ class SentryScreenShotTests: XCTestCase { wait(for: [expect], timeout: 1) // -- Assert -- + wait(for: [onRenderCalledExpectation], timeout: 1) XCTAssertTrue(isMainThread) + + let invocation = try XCTUnwrap(fixture.renderer.renderInvocations.first) + XCTAssertIdentical(invocation.value, testWindow) } - func test_Draw_Each_Window() { + func test_Draw_Each_Window() throws { + // -- Arrange -- let firstWindow = TestWindow(frame: CGRect(x: 0, y: 0, width: 10, height: 10)) let secondWindow = TestWindow(frame: CGRect(x: 0, y: 0, width: 10, height: 10)) - var drawFirstWindow = false - var drawSecondWindow = false - - firstWindow.onDrawHierarchy = { - drawFirstWindow = true - } - secondWindow.onDrawHierarchy = { - drawSecondWindow = true - } - + fixture.uiApplication.windows = [firstWindow, secondWindow] - + + // -- Act -- _ = self.fixture.sut.appScreenshotsData() - - XCTAssertTrue(drawFirstWindow) - XCTAssertTrue(drawSecondWindow) + + // -- Assert -- + XCTAssertEqual(fixture.renderer.renderInvocations.count, 2) + let firstInvocation = try XCTUnwrap(fixture.renderer.renderInvocations.first) + XCTAssertIdentical(firstInvocation.value, firstWindow) + let secondInvocation = try XCTUnwrap(fixture.renderer.renderInvocations.last) + XCTAssertIdentical(secondInvocation.value, secondWindow) } func test_image_size() throws { @@ -108,19 +121,6 @@ class SentryScreenShotTests: XCTestCase { XCTAssertEqual(0, data.count, "No screenshot should be taken, cause the image has zero height.") } - - private class TestSentryUIApplication: SentryUIApplication { - private var _windows: [UIWindow]? - - override var windows: [UIWindow]? { - get { - return _windows - } - set { - _windows = newValue - } - } - } private class TestWindow: UIWindow { var onDrawHierarchy: (() -> Void)? diff --git a/Tests/SentryTests/SentrySessionTests.m b/Tests/SentryTests/SentrySessionTests.m index 920d65cc420..b63c6002a24 100644 --- a/Tests/SentryTests/SentrySessionTests.m +++ b/Tests/SentryTests/SentrySessionTests.m @@ -1,4 +1,4 @@ -#import "SentrySession.h" +@import Sentry; #import @interface SentrySessionTests : XCTestCase @@ -16,7 +16,7 @@ - (void)testInitDefaultValues XCTAssertEqual(0, session.errors); XCTAssertTrue(session.flagInit); XCTAssertNotNil(session.started); - XCTAssertEqual(kSentrySessionStatusOk, session.status); + XCTAssertEqual(SentrySessionStatusOk, session.status); XCTAssertNotNil(session.distinctId); XCTAssertNil(session.timestamp); @@ -105,15 +105,15 @@ - (void)testAbnormalSession { SentrySession *expected = [[SentrySession alloc] initWithReleaseName:@"" distinctId:@"some-id"]; XCTAssertEqual(0, expected.errors); - XCTAssertEqual(kSentrySessionStatusOk, expected.status); + XCTAssertEqual(SentrySessionStatusOk, expected.status); XCTAssertEqual(1, expected.sequence); [expected incrementErrors]; XCTAssertEqual(1, expected.errors); - XCTAssertEqual(kSentrySessionStatusOk, expected.status); + XCTAssertEqual(SentrySessionStatusOk, expected.status); XCTAssertEqual(2, expected.sequence); [expected endSessionAbnormalWithTimestamp:[NSDate date]]; XCTAssertEqual(1, expected.errors); - XCTAssertEqual(kSentrySessionStatusAbnormal, expected.status); + XCTAssertEqual(SentrySessionStatusAbnormal, expected.status); XCTAssertEqual(3, expected.sequence); } @@ -121,9 +121,9 @@ - (void)testCrashedSession { SentrySession *expected = [[SentrySession alloc] initWithReleaseName:@"" distinctId:@"some-id"]; XCTAssertEqual(1, expected.sequence); - XCTAssertEqual(kSentrySessionStatusOk, expected.status); + XCTAssertEqual(SentrySessionStatusOk, expected.status); [expected endSessionCrashedWithTimestamp:[NSDate date]]; - XCTAssertEqual(kSentrySessionStatusCrashed, expected.status); + XCTAssertEqual(SentrySessionStatusCrashed, expected.status); XCTAssertEqual(2, expected.sequence); } @@ -131,11 +131,11 @@ - (void)testExitedSession { SentrySession *expected = [[SentrySession alloc] initWithReleaseName:@"" distinctId:@"some-id"]; XCTAssertEqual(0, expected.errors); - XCTAssertEqual(kSentrySessionStatusOk, expected.status); + XCTAssertEqual(SentrySessionStatusOk, expected.status); XCTAssertEqual(1, expected.sequence); [expected endSessionExitedWithTimestamp:[NSDate date]]; XCTAssertEqual(0, expected.errors); - XCTAssertEqual(kSentrySessionStatusExited, expected.status); + XCTAssertEqual(SentrySessionStatusExited, expected.status); XCTAssertEqual(2, expected.sequence); } diff --git a/Tests/SentryTests/SentrySessionTests.swift b/Tests/SentryTests/SentrySessionTests.swift index 29cf78afcc3..e9cec040a19 100644 --- a/Tests/SentryTests/SentrySessionTests.swift +++ b/Tests/SentryTests/SentrySessionTests.swift @@ -1,3 +1,4 @@ +@_spi(Private) import Sentry @_spi(Private) import SentryTestUtils import XCTest @@ -173,6 +174,6 @@ class SentrySessionTestsSwift: XCTestCase { extension SentrySessionStatus { var description: String { - return nameForSentrySessionStatus(self) + return nameForSentrySessionStatus(self.rawValue) } } diff --git a/Tests/SentryTests/SentryTests-Bridging-Header.h b/Tests/SentryTests/SentryTests-Bridging-Header.h index b30cd8b6dcd..b79cb446750 100644 --- a/Tests/SentryTests/SentryTests-Bridging-Header.h +++ b/Tests/SentryTests/SentryTests-Bridging-Header.h @@ -2,9 +2,6 @@ # import "SentryReachability.h" #endif // !TARGET_OS_WATCH -#import "SentryDefines.h" -#import "SentryProfilingConditionals.h" - #if SENTRY_HAS_METRIC_KIT # import "SentryMetricKitIntegration.h" #endif // SENTRY_HAS_METRIC_KIT @@ -14,9 +11,6 @@ # import "SentryFramesTracker+TestInit.h" # import "SentrySessionReplayIntegration+Private.h" # import "SentrySessionReplayIntegration+Test.h" -# import "SentryUIApplication+Private.h" -# import "SentryUIApplication.h" -# import "SentryUIDeviceWrapper.h" # import "SentryUIEventTracker.h" # import "SentryUIEventTrackerTransactionMode.h" # import "SentryUIEventTrackingIntegration.h" @@ -41,8 +35,10 @@ # import "SentryTraceProfiler+Test.h" #endif // SENTRY_TARGET_PROFILING_SUPPORTED -#import "SentryNSApplication.h" +@import _SentryPrivate; +#import "Helper/ExceptionCatcher.h" +#import "NSData+Unzip.h" #import "NSLocale+Sentry.h" #import "NSMutableDictionary+Sentry.h" #import "PrivateSentrySDKOnly.h" @@ -53,8 +49,8 @@ #import "SentryAppStartMeasurement.h" #import "SentryAppStartTracker.h" #import "SentryAppStartTrackingIntegration.h" -#import "SentryAppState.h" #import "SentryAppStateManager.h" +#import "SentryArray.h" #import "SentryAttachment+Private.h" #import "SentryAutoBreadcrumbTrackingIntegration+Test.h" #import "SentryAutoBreadcrumbTrackingIntegration.h" @@ -68,36 +64,40 @@ #import "SentryClassRegistrator.h" #import "SentryClient+Private.h" #import "SentryClient+TestInit.h" -#import "SentryClientReport.h" #import "SentryConcurrentRateLimitsDictionary.h" #import "SentryCoreDataSwizzling.h" #import "SentryCoreDataTracker+Test.h" #import "SentryCoreDataTrackingIntegration.h" +#import "SentryCrash+Test.h" #import "SentryCrashBinaryImageCache.h" #import "SentryCrashBinaryImageProvider.h" #import "SentryCrashC.h" +#import "SentryCrashCachedData.h" #import "SentryCrashCxaThrowSwapper.h" #import "SentryCrashDebug.h" #import "SentryCrashDefaultBinaryImageProvider.h" #import "SentryCrashDefaultMachineContextWrapper.h" #import "SentryCrashDoctor.h" +#import "SentryCrashInstallation+Private.h" #import "SentryCrashInstallationReporter.h" #import "SentryCrashIntegration+TestInit.h" #import "SentryCrashIntegration.h" #import "SentryCrashJSONCodecObjC.h" #import "SentryCrashMachineContext.h" +#import "SentryCrashMachineContext_Apple.h" #import "SentryCrashMonitor.h" #import "SentryCrashMonitorContext.h" #import "SentryCrashMonitor_AppState.h" +#import "SentryCrashMonitor_MachException.h" #import "SentryCrashMonitor_System.h" #import "SentryCrashReport.h" #import "SentryCrashReportSink.h" #import "SentryCrashReportStore.h" #import "SentryCrashScopeObserver.h" +#import "SentryCrashStackCursor_Backtrace.h" #import "SentryCrashStackCursor_SelfThread.h" #import "SentryCrashStackEntryMapper.h" #import "SentryCrashUUIDConversion.h" -#import "SentryCrashWrapper.h" #import "SentryDataCategory.h" #import "SentryDataCategoryMapper.h" #import "SentryDateUtil.h" @@ -105,19 +105,16 @@ #import "SentryDebugImageProvider+HybridSDKs.h" #import "SentryDebugImageProvider+TestInit.h" #import "SentryDebugMeta.h" -#import "SentryDefaultObjCRuntimeWrapper.h" #import "SentryDefaultRateLimits.h" +#import "SentryDefines.h" #import "SentryDependencyContainer.h" #import "SentryDiscardReason.h" #import "SentryDiscardReasonMapper.h" -#import "SentryDiscardedEvent.h" #import "SentryDispatchFactory.h" #import "SentryDispatchSourceWrapper.h" #import "SentryDisplayLinkWrapper.h" #import "SentryDsn.h" -#import "SentryEnvelope+Private.h" #import "SentryEnvelopeAttachmentHeader.h" -#import "SentryEnvelopeItemType.h" #import "SentryEnvelopeRateLimit.h" #import "SentryEvent+Private.h" #import "SentryExtraContextProvider.h" @@ -135,7 +132,6 @@ #import "SentryHttpTransport.h" #import "SentryHub+Private.h" #import "SentryHub+Test.h" -#import "SentryInAppLogic.h" #import "SentryInitializeForGettingSubclassesNotCalled.h" #import "SentryInstallation+Test.h" #import "SentryInstallation.h" @@ -144,31 +140,26 @@ #import "SentryLevelMapper.h" #import "SentryLogC.h" #import "SentryLogTestHelper.h" -#import "SentryMeasurementValue.h" #import "SentryMechanism.h" #import "SentryMechanismMeta.h" #import "SentryMeta.h" #import "SentryMigrateSessionInit.h" -#import "SentryMsgPackSerializer.h" #import "SentryNSDataUtils.h" #import "SentryNSDictionarySanitize+Tests.h" #import "SentryNSDictionarySanitize.h" #import "SentryNSError.h" -#import "SentryNSNotificationCenterWrapper.h" -#import "SentryNSProcessInfoWrapper.h" -#import "SentryNSTimerFactory.h" #import "SentryNSURLRequestBuilder.h" #import "SentryNSURLSessionTaskSearch.h" #import "SentryNetworkTracker.h" #import "SentryNetworkTrackingIntegration.h" #import "SentryNoOpSpan.h" -#import "SentryObjCRuntimeWrapper.h" -#import "SentryOptions+HybridSDKs.h" #import "SentryOptions+Private.h" +#import "SentryOptionsInternal.h" #import "SentryPerformanceTracker+Testing.h" #import "SentryPerformanceTracker.h" #import "SentryPerformanceTrackingIntegration.h" #import "SentryPredicateDescriptor.h" +#import "SentryProfilingConditionals.h" #import "SentryPropagationContext.h" #import "SentryQueueableRequestManager.h" #import "SentryRateLimitParser.h" @@ -176,34 +167,15 @@ #import "SentryReachability.h" #import "SentryRetryAfterHeaderParser.h" #import "SentrySDK+Private.h" -#import "SentrySDK+Tests.h" +#import "SentrySDKInternal+Tests.h" #import "SentrySampleDecision+Private.h" #import "SentryScope+Private.h" #import "SentryScopeObserver.h" #import "SentryScopeSyncC.h" #import "SentryScreenFrames.h" #import "SentryScreenshotIntegration.h" -#import "SentrySwift.h" -#import "SentrySwiftAsyncIntegration.h" -#import "SentryUncaughtNSExceptions.h" -#import "SentryWatchdogTerminationBreadcrumbProcessor.h" -#import "SentryWeakMap.h" - -#import "NSData+Unzip.h" -#import "Sentry/Sentry-Swift.h" -#import "SentryBinaryImageCache+Private.h" -#import "SentryCrashBinaryImageCache.h" -#import "SentryDispatchFactory.h" -#import "SentryDispatchSourceWrapper.h" -#import "SentryEnvelopeAttachmentHeader.h" -#import "SentryExtraContextProvider.h" -#import "SentryMeasurementValue.h" -#import "SentryNSProcessInfoWrapper.h" -#import "SentryPerformanceTracker+Testing.h" -#import "SentryPropagationContext.h" -#import "SentrySampleDecision+Private.h" #import "SentrySerialization.h" -#import "SentrySession+Private.h" +#import "SentrySessionReplaySyncC.h" #import "SentrySessionTracker.h" #import "SentrySpan.h" #import "SentrySpanDataKey.h" @@ -235,24 +207,17 @@ #import "SentryTransport.h" #import "SentryTransportAdapter.h" #import "SentryTransportFactory.h" +#import "SentryUncaughtNSExceptions.h" +#import "SentryUseNSExceptionCallstackWrapper.h" #import "SentryViewHierarchyIntegration.h" #import "SentryViewHierarchyProvider.h" +#import "SentryWatchdogTerminationBreadcrumbProcessor.h" #import "SentryWatchdogTerminationLogic.h" #import "SentryWatchdogTerminationScopeObserver.h" #import "SentryWatchdogTerminationTracker.h" #import "SentryWatchdogTerminationTrackingIntegration.h" +#import "SentryWeakMap.h" #import "TestNSURLRequestBuilder.h" -#import "TestSentryCrashWrapper.h" #import "TestSentrySpan.h" #import "TestSentryViewHierarchyProvider.h" #import "URLSessionTaskMock.h" -@import _SentryPrivate; -#import "Helper/ExceptionCatcher.h" -#import "SentryCrash+Test.h" -#import "SentryCrashCachedData.h" -#import "SentryCrashInstallation+Private.h" -#import "SentryCrashMachineContext_Apple.h" -#import "SentryCrashMonitor_MachException.h" -#import "SentryCrashStackCursor_Backtrace.h" -#import "SentrySessionReplaySyncC.h" -#import "SentryUseNSExceptionCallstackWrapper.h" diff --git a/Tests/SentryTests/SentryTests.m b/Tests/SentryTests/SentryTests.m index b0c7ca3c3b4..946ef24fbbd 100644 --- a/Tests/SentryTests/SentryTests.m +++ b/Tests/SentryTests/SentryTests.m @@ -8,7 +8,7 @@ #import "SentryLevelMapper.h" #import "SentryMessage.h" #import "SentryMeta.h" -#import "SentryOptions+HybridSDKs.h" +#import "SentryOptionsInternal.h" #import "SentrySDK+Private.h" #import #import @@ -28,22 +28,22 @@ @implementation SentryTests - (void)setUp { - [SentrySDK.currentHub bindClient:nil]; + [SentrySDKInternal.currentHub bindClient:nil]; } - (void)testSharedClient { NSError *error = nil; - SentryOptions *options = [[SentryOptions alloc] + SentryOptions *options = [SentryOptionsInternal initWithDict:@{ @"dsn" : @"https://username:password@app.getsentry.com/12345" } didFailWithError:&error]; SentryClient *client = [[SentryClient alloc] initWithOptions:options]; XCTAssertNil(error); - XCTAssertNil([SentrySDK.currentHub getClient]); - [SentrySDK.currentHub bindClient:client]; - XCTAssertNotNil([SentrySDK.currentHub getClient]); - [SentrySDK.currentHub bindClient:nil]; + XCTAssertNil([SentrySDKInternal.currentHub getClient]); + [SentrySDKInternal.currentHub bindClient:client]; + XCTAssertNotNil([SentrySDKInternal.currentHub getClient]); + [SentrySDKInternal.currentHub bindClient:nil]; } - (void)testSDKDefaultHub @@ -51,8 +51,8 @@ - (void)testSDKDefaultHub [SentrySDK startWithConfigureOptions:^(SentryOptions *_Nonnull options) { options.dsn = @"https://username:password@app.getsentry.com/12345"; }]; - XCTAssertNotNil([SentrySDK.currentHub getClient]); - [SentrySDK.currentHub bindClient:nil]; + XCTAssertNotNil([SentrySDKInternal.currentHub getClient]); + [SentrySDKInternal.currentHub bindClient:nil]; } - (void)testSDKBreadCrumbAdd diff --git a/Tests/SentryTests/SentryUIApplication+Private.h b/Tests/SentryTests/SentryUIApplication+Private.h deleted file mode 100644 index ab5de62e05c..00000000000 --- a/Tests/SentryTests/SentryUIApplication+Private.h +++ /dev/null @@ -1,21 +0,0 @@ - -#ifndef SentryUIApplication_Private_h -#define SentryUIApplication_Private_h - -#import "SentryDefines.h" -#import "SentryUIApplication.h" - -#if SENTRY_HAS_UIKIT - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryUIApplication () - -- (NSArray *)relevantViewControllers; - -@end - -NS_ASSUME_NONNULL_END - -#endif /* SentryUIApplication_Private_h */ -#endif diff --git a/Tests/SentryTests/SentryUIApplicationTests.swift b/Tests/SentryTests/SentryUIApplicationTests.swift index f933263ad66..db956280b79 100644 --- a/Tests/SentryTests/SentryUIApplicationTests.swift +++ b/Tests/SentryTests/SentryUIApplicationTests.swift @@ -1,3 +1,4 @@ +@_spi(Private) @testable import Sentry @_spi(Private) import SentryTestUtils import XCTest @@ -10,17 +11,17 @@ class SentryUIApplicationTests: XCTestCase { } func test_noScene_delegateWithNoWindow() { - let sut = MockSentryUIApplicationTests() - XCTAssertEqual(sut.windows?.count, 0) + let sut = TestSentryUIApplication() + XCTAssertEqual(sut.getWindows()?.count, 0) } func test_delegateWithWindow() { - let sut = MockSentryUIApplicationTests() + let sut = TestSentryUIApplication() let delegate = TestApplicationDelegate() sut.appDelegate = delegate sut.appDelegate?.window = UIWindow() - XCTAssertEqual(sut.windows?.count, 1) + XCTAssertEqual(sut.getWindows()?.count, 1) } //Somehow this is running under iOS 12 and is breaking the test. Disabling it. @@ -32,10 +33,10 @@ class SentryUIApplicationTests: XCTestCase { let scene1 = MockUIScene() scene1.delegate = sceneDelegate - let sut = MockSentryUIApplicationTests() + let sut = TestSentryUIApplication() sut.scenes = [scene1] - XCTAssertEqual(sut.windows?.count, 1) + XCTAssertEqual(sut.getWindows()?.count, 1) } //Somehow this is running under iOS 12 and is breaking the test. Disabling it. @@ -49,11 +50,11 @@ class SentryUIApplicationTests: XCTestCase { let delegate = TestApplicationDelegate() delegate.window = UIWindow() - let sut = MockSentryUIApplicationTests() + let sut = TestSentryUIApplication() sut.scenes = [scene1] sut.appDelegate = delegate - XCTAssertEqual(sut.windows?.count, 2) + XCTAssertEqual(sut.getWindows()?.count, 2) } //Somehow this is running under iOS 12 and is breaking the test. Disabling it. @@ -68,11 +69,11 @@ class SentryUIApplicationTests: XCTestCase { let delegate = TestApplicationDelegate() delegate.window = window - let sut = MockSentryUIApplicationTests() + let sut = TestSentryUIApplication() sut.scenes = [scene1] sut.appDelegate = delegate - XCTAssertEqual(sut.windows?.count, 1) + XCTAssertEqual(sut.getWindows()?.count, 1) } //Somehow this is running under iOS 12 and is breaking the test. Disabling it. @@ -83,63 +84,14 @@ class SentryUIApplicationTests: XCTestCase { let scene1 = MockUIScene() scene1.delegate = sceneDelegate - let sut = MockSentryUIApplicationTests() + let sut = TestSentryUIApplication() sut.scenes = [scene1] - XCTAssertEqual(sut.windows?.count, 0) - } - - @available(iOS 13.0, tvOS 13.0, *) - func test_ApplicationState() { - let sut = MockSentryUIApplicationTests() - sut.notificationCenterWrapper.ignoreRemoveObserver = true - XCTAssertEqual(sut.applicationState, .active) - - sut.notificationCenterWrapper.addObserverInvocations.invocations.forEach { (observer: Any, selector: Selector, name: NSNotification.Name) in - if name == UIApplication.didEnterBackgroundNotification { - sut.perform(selector, with: observer) - } - } - - XCTAssertEqual(sut.applicationState, .background) - - sut.notificationCenterWrapper.addObserverInvocations.invocations.forEach { (observer: Any, selector: Selector, name: NSNotification.Name) in - if name == UIApplication.didBecomeActiveNotification { - sut.perform(selector, with: observer) - } - } - - XCTAssertEqual(sut.applicationState, .active) - } - - private class TestApplicationDelegate: NSObject, UIApplicationDelegate { - var window: UIWindow? + XCTAssertEqual(sut.getWindows()?.count, 0) } private class TestUISceneDelegate: NSObject, UIWindowSceneDelegate { var window: UIWindow? } - - private class MockSentryUIApplicationTests: SentryUIApplication { - - let notificationCenterWrapper: TestNSNotificationCenterWrapper - - weak var appDelegate: TestApplicationDelegate? - var scenes: [Any]? - - init() { - notificationCenterWrapper = TestNSNotificationCenterWrapper() - super.init(notificationCenterWrapper: notificationCenterWrapper, dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) - } - - override func getDelegate(_ application: UIApplication) -> UIApplicationDelegate? { - return appDelegate - } - - @available(iOS 13.0, tvOS 13.0, *) - override func getConnectedScenes(_ application: UIApplication) -> [UIScene] { - return scenes as? [UIScene] ?? super.getConnectedScenes(application) - } - } } #endif diff --git a/Tests/SentryTests/SentryViewHierarchyProviderTests.swift b/Tests/SentryTests/SentryViewHierarchyProviderTests.swift index bcfe07c3cd9..37a15d6430f 100644 --- a/Tests/SentryTests/SentryViewHierarchyProviderTests.swift +++ b/Tests/SentryTests/SentryViewHierarchyProviderTests.swift @@ -196,7 +196,7 @@ class SentryViewHierarchyProviderTests: XCTestCase { let _ = sut.appViewHierarchyFromMainThread() } - wait(for: [ex], timeout: 1) + wait(for: [ex], timeout: 5) } func test_appViewHierarchy_usesMainThread() { @@ -211,33 +211,8 @@ class SentryViewHierarchyProviderTests: XCTestCase { ex.fulfill() } - wait(for: [ex], timeout: 1) + wait(for: [ex], timeout: 5) XCTAssertTrue(fixture.uiApplication.calledOnMainThread, "appViewHierarchy is not using the main thread to get UI windows") } - - private class TestSentryUIApplication: SentryUIApplication { - - init() { - super.init(notificationCenterWrapper: TestNSNotificationCenterWrapper(), dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) - } - - private var _windows: [UIWindow]? - private var _calledOnMainThread = true - - var calledOnMainThread: Bool { - return _calledOnMainThread - } - - override var windows: [UIWindow]? { - get { - _calledOnMainThread = Thread.isMainThread - return _windows - } - set { - _calledOnMainThread = Thread.isMainThread - _windows = newValue - } - } - } } #endif diff --git a/Tests/SentryTests/Swift/Core/Tools/LoadValidatorTests.swift b/Tests/SentryTests/Swift/Core/Tools/LoadValidatorTests.swift new file mode 100644 index 00000000000..281bb225624 --- /dev/null +++ b/Tests/SentryTests/Swift/Core/Tools/LoadValidatorTests.swift @@ -0,0 +1,249 @@ +import ObjectiveC +@_spi(Private) @testable import Sentry +@_spi(Private) import SentryTestUtils +import XCTest + +class LoadValidatorTests: XCTestCase { + + // MARK: - Test Properties + + private var testOutput: TestLogOutput! + private var testObjCRuntimeWrapper: SentryTestObjCRuntimeWrapper! + private var dispatchQueueWrapper: TestSentryDispatchQueueWrapper! + private var defaultImageAddress: UInt64 = 0x1000 + private var defaultImageSize: UInt64 = 0x20 + + // MARK: - Setup and Teardown + + override func setUp() { + super.setUp() + testOutput = TestLogOutput() + SentrySDKLog.setLogOutput(testOutput) + SentrySDKLog.configureLog(true, diagnosticLevel: .debug) + + testObjCRuntimeWrapper = SentryTestObjCRuntimeWrapper() + + dispatchQueueWrapper = TestSentryDispatchQueueWrapper() + dispatchQueueWrapper.dispatchAfterExecutesBlock = true + } + + override func tearDown() { + clearTestState() + super.tearDown() + } + + // MARK: - Test Cases + + func testValidateSDKPresenceIn_SystemLibraryPath_DoesNotValidate() { + // Arrange + let imageName = "/usr/lib/system.dylib" + var getClassListCalled = false + testObjCRuntimeWrapper.beforeGetClassList = { + getClassListCalled = true + } + let expectation = XCTestExpectation(description: "LoadValidation should complete") + + // Act + var validationResult = false + LoadValidator.internalCheckForDuplicatedSDK(imageName, + defaultImageAddress, + defaultImageSize, + objcRuntimeWrapper: testObjCRuntimeWrapper, + dispatchQueueWrapper: dispatchQueueWrapper) { result in + validationResult = result + expectation.fulfill() + } + wait(for: [expectation], timeout: 5) + + // Assert + XCTAssertFalse(validationResult, "Validation should return false for system libraries") + XCTAssertFalse(getClassListCalled, "ObjectiveC Wrapper should not be called for a system library") + XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") }) + XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 0) + } + + func testValidateSDKPresenceIn_SimulatorPath_DoesNotValidate() { + // Arrange + let imageName = "/Library/Developer/CoreSimulator/Volumes/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system.dylib" + var getClassListCalled = false + testObjCRuntimeWrapper.beforeGetClassList = { + getClassListCalled = true + } + let expectation = XCTestExpectation(description: "LoadValidation should complete") + + // Act + var validationResult = false + LoadValidator.internalCheckForDuplicatedSDK(imageName, + defaultImageAddress, + defaultImageSize, + objcRuntimeWrapper: testObjCRuntimeWrapper, + dispatchQueueWrapper: dispatchQueueWrapper) { result in + validationResult = result + expectation.fulfill() + } + wait(for: [expectation], timeout: 5) + + // Assert + XCTAssertFalse(validationResult, "Validation should return false for simulator libraries") + XCTAssertFalse(getClassListCalled, "ObjectiveC Wrapper should not be called for a simulator library") + XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") }) + XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 0) + } + + func testValidateSDKPresenceIn_SystemPath_DoesNotValidate() { + // Arrange + let imageName = "/System/Library/system.dylib" + var getClassListCalled = false + testObjCRuntimeWrapper.beforeGetClassList = { + getClassListCalled = true + } + let expectation = XCTestExpectation(description: "LoadValidation should complete") + + // Act + var validationResult = false + LoadValidator.internalCheckForDuplicatedSDK(imageName, + defaultImageAddress, + defaultImageSize, + objcRuntimeWrapper: testObjCRuntimeWrapper, + dispatchQueueWrapper: dispatchQueueWrapper) { result in + validationResult = result + expectation.fulfill() + } + wait(for: [expectation], timeout: 5) + + // Assert + XCTAssertFalse(validationResult, "Validation should return false for system libraries") + XCTAssertFalse(getClassListCalled, "ObjectiveC Wrapper should not be called for a simulator library") + XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") }) + XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 0) + } + + func testValidateSDKPresenceIn_AppImage_CallsRuntimeWrapper() { + // Arrange + let imageName = "/var/containers/Bundle/Application/TestApp.app/TestApp" + var getClassListCalled = false + testObjCRuntimeWrapper.beforeGetClassList = { + getClassListCalled = true + } + let expectation = XCTestExpectation(description: "LoadValidation should complete") + + // Act + var validationResult = false + LoadValidator.internalCheckForDuplicatedSDK(imageName, + defaultImageAddress, + defaultImageSize, + objcRuntimeWrapper: testObjCRuntimeWrapper, + dispatchQueueWrapper: dispatchQueueWrapper) { result in + validationResult = result + expectation.fulfill() + } + wait(for: [expectation], timeout: 5) + + // Assert + XCTAssertFalse(validationResult, "Validation should return false") + XCTAssertTrue(getClassListCalled, "ObjectiveC Wrapper should be called for an app binary") + XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") }) + XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) + } + + func testValidateSDKPresenceIn_ContainsTargetClassName_LogsError() { + // Arrange + let imageName = "/var/containers/Bundle/Application/TestApp.app/TestApp" + testObjCRuntimeWrapper.classesNames = { _ in + return ["SentryDependencyContainerSwiftHelper"] + } + var getClassListCalled = false + testObjCRuntimeWrapper.beforeGetClassList = { + getClassListCalled = true + } + let expectation = XCTestExpectation(description: "LoadValidation should complete") + + // Act + var validationResult = false + LoadValidator.internalCheckForDuplicatedSDK(imageName, + defaultImageAddress, + defaultImageSize, + objcRuntimeWrapper: testObjCRuntimeWrapper, + dispatchQueueWrapper: dispatchQueueWrapper) { result in + validationResult = result + expectation.fulfill() + } + wait(for: [expectation], timeout: 5) + + // Assert + XCTAssertTrue(validationResult, "Validation should skip for app binary") + XCTAssertTrue(getClassListCalled, "ObjectiveC Wrapper should be called for an app binary") + XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times in the same binary ❌") }) + XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("⚠️ This can cause undefined behavior, crashes, or duplicate reporting.") }) + XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("Ensure the SDK is linked only once, found `SentryDependencyContainerSwiftHelper` class in image path: \(imageName)") }) + XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) + } + + func testValidateSDKPresenceIn_ContainsSubclass_LogsError() { + // Arrange + let imageName = "/var/containers/Bundle/Application/TestApp.app/TestApp" + testObjCRuntimeWrapper.classesNames = { _ in + return ["EmergeSentryDependencyContainerSwiftHelper"] + } + var getClassListCalled = false + testObjCRuntimeWrapper.beforeGetClassList = { + getClassListCalled = true + } + let expectation = XCTestExpectation(description: "LoadValidation should complete") + + // Act + var validationResult = false + LoadValidator.internalCheckForDuplicatedSDK(imageName, + defaultImageAddress, + defaultImageSize, + objcRuntimeWrapper: testObjCRuntimeWrapper, + dispatchQueueWrapper: dispatchQueueWrapper) { result in + validationResult = result + expectation.fulfill() + } + wait(for: [expectation], timeout: 5) + + // Assert + XCTAssertTrue(validationResult, "Validation should return true for app") + XCTAssertTrue(getClassListCalled, "ObjectiveC Wrapper should be called for an app binary") + XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times in the same binary ❌") }) + XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("⚠️ This can cause undefined behavior, crashes, or duplicate reporting.") }) + XCTAssertTrue(testOutput.loggedMessages.contains { $0.contains("Ensure the SDK is linked only once, found `SentryDependencyContainerSwiftHelper` class in image path: \(imageName)") }) + XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) + } + + func testValidateSDKPresenceIn_ContainsTargetClassNameInCurrentImage_SkipsValidation() { + // Arrange + let imageName = "/path/to/sentry/libSentry.dylib" + let loadValidatorAddress = LoadValidator.getCurrentFrameworkTextPointer() + let loadValidatorAddressValue = UInt(bitPattern: loadValidatorAddress) + let imageAddress = UInt64(loadValidatorAddressValue) + let imageSize: UInt64 = 0x1000 + var getClassListCalled = false + testObjCRuntimeWrapper.beforeGetClassList = { + getClassListCalled = true + } + testObjCRuntimeWrapper.classesNames = { _ in + return ["SentryDependencyContainerSwiftHelper"] + } + let expectation = XCTestExpectation(description: "LoadValidation should complete") + + // Act + var validationResult = false + LoadValidator.internalCheckForDuplicatedSDK(imageName, + imageAddress, + imageSize, + objcRuntimeWrapper: testObjCRuntimeWrapper, + dispatchQueueWrapper: dispatchQueueWrapper) { result in + validationResult = result + expectation.fulfill() + } + wait(for: [expectation], timeout: 5) + + // Assert + XCTAssertFalse(validationResult, "Validation should skip for sentry framework") + XCTAssertTrue(getClassListCalled, "ObjectiveC Wrapper should not be called for an app binary") + XCTAssertFalse(testOutput.loggedMessages.contains { $0.contains("❌ Sentry SDK was loaded multiple times") }) + XCTAssertEqual(dispatchQueueWrapper.dispatchAsyncInvocations.count, 1) + } +} diff --git a/Tests/SentryTests/TestLogOutput.swift b/Tests/SentryTests/TestLogOutput.swift index 194239d1f43..c5bb5920047 100644 --- a/Tests/SentryTests/TestLogOutput.swift +++ b/Tests/SentryTests/TestLogOutput.swift @@ -4,14 +4,16 @@ import XCTest final class TestLogOutput { - private let queue = DispatchQueue(label: "TestLogOutput", attributes: .concurrent) - + private let logsToConsole: Bool private var _loggedMessages: [String] = [] - - var logsToConsole: Bool = true + private let lock = NSLock() + + init(logsToConsole: Bool = true) { + self.logsToConsole = logsToConsole + } var loggedMessages: [String] { - queue.sync { + lock.synchronized { return _loggedMessages } } @@ -20,7 +22,7 @@ final class TestLogOutput { if logsToConsole { print(message) } - queue.async(flags: .barrier) { + lock.synchronized { self._loggedMessages.append(message) } } @@ -28,13 +30,108 @@ final class TestLogOutput { class TestLogOutPutTests: XCTestCase { - func testLoggingFromMulitpleThreads() { - let sut = TestLogOutput() - sut.logsToConsole = false - testConcurrentModifications(writeWork: { i in - sut.log("Some message \(i)") - }, readWork: { - XCTAssertNotNil(sut.loggedMessages) - }) + func testLoggingFromMultipleThreads() { + // Arrange + let sut = TestLogOutput(logsToConsole: false) + + let queue = DispatchQueue(label: "testLoggingFromMultipleThreads", attributes: [.concurrent]) + let expectation = expectation(description: "Logging from multiple threads") + + let iterations = 100 + expectation.expectedFulfillmentCount = iterations * 2 + + // Act + for i in 0.. [UIWindow]? { + if let windows { + return windows + } + return internal_getWindows() + } + + private var _windows: [UIWindow]? + private(set) var calledOnMainThread = true + var windows: [UIWindow]? { + get { + calledOnMainThread = Thread.isMainThread + return _windows + } + set { + calledOnMainThread = Thread.isMainThread + _windows = newValue + } + } + + var _relevantViewControllerNames: [String]? + func relevantViewControllersNames() -> [String]? { + if let _relevantViewControllerNames { + return _relevantViewControllerNames + } + return UIApplication.shared.relevantViewControllersNames() + } + + private var _underlyingAppState: UIApplication.State = .active + var unsafeApplicationState: UIApplication.State { + get { _underlyingAppState } + set { _underlyingAppState = newValue } + } + + var mainThread_isActive: Bool { + return unsafeApplicationState == .active + } + + var connectedScenes: Set { + if let scenes = scenes as? [UIScene] { + return Set(scenes) + } + return [] + } + + weak var appDelegate: TestApplicationDelegate? + var scenes: [Any]? + + var delegate: UIApplicationDelegate? { + return appDelegate + } +} + +final class TestApplicationDelegate: NSObject, UIApplicationDelegate { + var window: UIWindow? +} +#endif diff --git a/Tests/SentryTests/TestUtils/Async.swift b/Tests/SentryTests/TestUtils/Async.swift index ec522c76a7b..3141317917c 100644 --- a/Tests/SentryTests/TestUtils/Async.swift +++ b/Tests/SentryTests/TestUtils/Async.swift @@ -1,18 +1,6 @@ import Foundation import XCTest -func delayNonBlocking(timeout: Double = 0.2) { - let group = DispatchGroup() - group.enter() - let queue = DispatchQueue(label: "delay", qos: .background, attributes: []) - - queue.asyncAfter(deadline: .now() + timeout) { - group.leave() - } - - group.wait() -} - extension DispatchGroup { /** diff --git a/Tests/SentryTests/TestUtils/TestConncurrentModifications.swift b/Tests/SentryTests/TestUtils/TestConncurrentModifications.swift index e1fd4596504..b722f638a03 100644 --- a/Tests/SentryTests/TestUtils/TestConncurrentModifications.swift +++ b/Tests/SentryTests/TestUtils/TestConncurrentModifications.swift @@ -1,26 +1,33 @@ -import Foundation @_spi(Private) import Sentry @_spi(Private) import SentryTestUtils +import XCTest -func testConcurrentModifications(asyncWorkItems: Int = 5, writeLoopCount: Int = 1_000, writeWork: @escaping (Int) -> Void, readWork: @escaping () -> Void = {}) { - - let queue = DispatchQueue(label: "testConcurrentModifications", qos: .userInteractive, attributes: [.concurrent, .initiallyInactive]) - let group = DispatchGroup() - - for _ in 0.. Void, readWork: @escaping () -> Void = {}) { + + let queue = DispatchQueue(label: "testConcurrentModifications", qos: .userInteractive, attributes: [.concurrent, .initiallyInactive]) + + let expectation = XCTestExpectation(description: "ConcurrentModifications") + expectation.expectedFulfillmentCount = asyncWorkItems + expectation.assertForOverFulfill = true + + for _ in 0.. Span { - let hub = SentryHub(client: client, andScope: nil, andCrashWrapper: TestSentryCrashWrapper.sharedInstance(), andDispatchQueue: TestSentryDispatchQueueWrapper()) + let hub = SentryHub(client: client, andScope: nil, andCrashWrapper: TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo), andDispatchQueue: TestSentryDispatchQueueWrapper()) return hub.startTransaction(name: someTransaction, operation: someOperation) } @@ -68,10 +69,10 @@ class SentrySpanTests: XCTestCase { #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) func testSpanDoesNotIncludeTraceProfilerID() throws { fixture.options.profilesSampleRate = 1 - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setStart(with: fixture.options) let span = fixture.getSut() - let continuousProfileObservations = fixture.notificationCenter.addObserverInvocations.invocations.filter { - $0.name.rawValue == kSentryNotificationContinuousProfileStarted + let continuousProfileObservations = fixture.notificationCenter.addObserverWithObjectInvocations.invocations.filter { + $0.name?.rawValue == kSentryNotificationContinuousProfileStarted } XCTAssertEqual(continuousProfileObservations.count, 0) XCTAssert(SentryTraceProfiler.isCurrentlyProfiling()) @@ -84,30 +85,30 @@ class SentrySpanTests: XCTestCase { func testSpanDoesNotSubscribeToNotificationsIfAlreadyCapturedContinuousProfileID() { fixture.options.profilesSampleRate = nil SentryContinuousProfiler.start() - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setStart(with: fixture.options) let _ = fixture.getSut() - let continuousProfileObservations = fixture.notificationCenter.addObserverInvocations.invocations.filter { - $0.name.rawValue == kSentryNotificationContinuousProfileStarted + let continuousProfileObservations = fixture.notificationCenter.addObserverWithObjectInvocations.invocations.filter { + $0.name?.rawValue == kSentryNotificationContinuousProfileStarted } XCTAssertEqual(continuousProfileObservations.count, 0) } func testSpanDoesNotSubscribeToNotificationsIfContinuousProfilingDisabled() { fixture.options.profilesSampleRate = 1 - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setStart(with: fixture.options) let _ = fixture.getSut() - let continuousProfileObservations = fixture.notificationCenter.addObserverInvocations.invocations.filter { - $0.name.rawValue == kSentryNotificationContinuousProfileStarted + let continuousProfileObservations = fixture.notificationCenter.addObserverWithObjectInvocations.invocations.filter { + $0.name?.rawValue == kSentryNotificationContinuousProfileStarted } XCTAssertEqual(continuousProfileObservations.count, 0) } func testSpanDoesSubscribeToNotificationsIfNotAlreadyCapturedContinuousProfileID() { fixture.options.profilesSampleRate = nil - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setStart(with: fixture.options) let _ = fixture.getSut() - let continuousProfileObservations = fixture.notificationCenter.addObserverInvocations.invocations.filter { - $0.name.rawValue == kSentryNotificationContinuousProfileStarted + let continuousProfileObservations = fixture.notificationCenter.addObserverWithObjectInvocations.invocations.filter { + $0.name?.rawValue == kSentryNotificationContinuousProfileStarted } XCTAssertEqual(continuousProfileObservations.count, 1) } @@ -120,10 +121,10 @@ class SentrySpanTests: XCTestCase { /// ``` func test_spanStart_profileStart_spanEnd_profileEnd_spanIncludesProfileID() throws { fixture.options.profilesSampleRate = nil - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setStart(with: fixture.options) let span = fixture.getSut() - XCTAssertEqual(fixture.notificationCenter.addObserverInvocations.invocations.filter { - $0.name.rawValue == kSentryNotificationContinuousProfileStarted + XCTAssertEqual(fixture.notificationCenter.addObserverWithObjectInvocations.invocations.filter { + $0.name?.rawValue == kSentryNotificationContinuousProfileStarted }.count, 1) SentryContinuousProfiler.start() let profileId = try XCTUnwrap(SentryContinuousProfiler.profiler()?.profilerId.sentryIdString) @@ -142,7 +143,7 @@ class SentrySpanTests: XCTestCase { /// ``` func test_spanStart_profileStart_profileEnd_spanEnd_spanIncludesProfileID() throws { fixture.options.profilesSampleRate = nil - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setStart(with: fixture.options) let span = fixture.getSut() SentryContinuousProfiler.start() let profileId = try XCTUnwrap(SentryContinuousProfiler.profiler()?.profilerId.sentryIdString) @@ -162,7 +163,7 @@ class SentrySpanTests: XCTestCase { /// ``` func test_profileStart_spanStart_profileEnd_spanEnd_spanIncludesProfileID() throws { fixture.options.profilesSampleRate = nil - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setStart(with: fixture.options) SentryContinuousProfiler.start() let profileId = try XCTUnwrap(SentryContinuousProfiler.profiler()?.profilerId.sentryIdString) let span = fixture.getSut() @@ -182,7 +183,7 @@ class SentrySpanTests: XCTestCase { /// ``` func test_profileStart_spanStart_spanEnd_profileEnd_spanIncludesProfileID() throws { fixture.options.profilesSampleRate = nil - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setStart(with: fixture.options) SentryContinuousProfiler.start() let profileId = try XCTUnwrap(SentryContinuousProfiler.profiler()?.profilerId.sentryIdString) let span = fixture.getSut() @@ -201,7 +202,7 @@ class SentrySpanTests: XCTestCase { /// ``` func test_spanStart_profileStart_profileEnd_profileStart_profileEnd_spanEnd_spanIncludesSameProfileID() throws { fixture.options.profilesSampleRate = nil - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setStart(with: fixture.options) let span = fixture.getSut() SentryContinuousProfiler.start() let profileId1 = try XCTUnwrap(SentryContinuousProfiler.profiler()?.profilerId.sentryIdString) @@ -224,7 +225,7 @@ class SentrySpanTests: XCTestCase { /// ``` func test_spanStart_spanEnd_profileStart_profileEnd_spanDoesNotIncludeProfileID() { fixture.options.profilesSampleRate = nil - SentrySDK.setStart(fixture.options) + SentrySDKInternal.setStart(with: fixture.options) SentryContinuousProfiler.start() SentryContinuousProfiler.stop() let span = fixture.getSut() @@ -308,7 +309,7 @@ class SentrySpanTests: XCTestCase { XCTAssertEqual(lastEvent.transaction, fixture.someTransaction) XCTAssertEqual(lastEvent.timestamp, TestData.timestamp) XCTAssertEqual(lastEvent.startTimestamp, TestData.timestamp) - XCTAssertEqual(lastEvent.type, SentryEnvelopeItemTypeTransaction) + XCTAssertEqual(lastEvent.type, SentryEnvelopeItemTypes.transaction) } func testFinish_Custom_Timestamp() throws { @@ -330,7 +331,7 @@ class SentrySpanTests: XCTestCase { XCTAssertEqual(lastEvent.transaction, fixture.someTransaction) XCTAssertEqual(lastEvent.timestamp, finishDate) XCTAssertEqual(lastEvent.startTimestamp, TestData.timestamp) - XCTAssertEqual(lastEvent.type, SentryEnvelopeItemTypeTransaction) + XCTAssertEqual(lastEvent.type, SentryEnvelopeItemTypes.transaction) } func testFinishSpanWithDefaultTimestamp() { @@ -602,7 +603,6 @@ class SentrySpanTests: XCTestCase { func testModifyingExtraFromMultipleThreads() { let queue = DispatchQueue(label: "SentrySpanTests", qos: .userInteractive, attributes: [.concurrent, .initiallyInactive]) - let group = DispatchGroup() let span = fixture.getSut() @@ -611,9 +611,13 @@ class SentrySpanTests: XCTestCase { let innerLoop = 1_000 let outerLoop = 20 let value = fixture.extraValue + + let expectation = XCTestExpectation(description: "ModifyingExtraFromMultipleThreads") + expectation.expectedFulfillmentCount = outerLoop + expectation.assertForOverFulfill = true for i in 0.. (String, ObjectIdentifier?) in + guard let classType = NSClassFromString(className) else { + print("Class \(className) not found, skipping test") + return (className, nil) + } + return (className, ObjectIdentifier(classType)) + } + + // -- Act -- let sut = getSut() - expectedList.forEach { element in - XCTAssertTrue(sut.containsRedactClass(element), "\(element) not found") + + // -- Assert -- + // Build sets of expected and actual identifiers for comparison + let expectedIdentifiers = Set(expectedList.compactMap { $0.1 }) + let actualIdentifiers = Set(sut.redactClassesIdentifiers) + + // Check for identifiers that are expected but missing in the actual result + let missingIdentifiers = expectedIdentifiers.subtracting(actualIdentifiers) + // Check for identifiers that are present in the actual result but not expected + let unexpectedIdentifiers = actualIdentifiers.subtracting(expectedIdentifiers) + + // For each expected class, check that if we expect the class identifier to be nil, it is nil + for (expectedClassName, expectedNullableIdentifier) in expectedList { + if expectedNullableIdentifier == nil { + // If we expect nil, assert that no identifier in the actual list matches the class name + let found = sut.redactClassesIdentifiers.contains { $0.debugDescription.contains(expectedClassName) } + XCTAssertFalse(found, "Class \(expectedClassName) not found in runtime, but it is present in the redact list") + } else { + // If we expect a non-nil identifier, assert that it is present in the actual list + XCTAssertTrue(sut.redactClassesIdentifiers.contains(where: { $0 == expectedNullableIdentifier }), "Expected class \(expectedClassName) not found in redact list") + } } + + // Assert that there are no missing identifiers + XCTAssertTrue(missingIdentifiers.isEmpty, "Missing expected class identifiers: \(missingIdentifiers)") + + // Assert that there are no unexpected identifiers + for identifier in unexpectedIdentifiers { + // Try to get the class name from the identifier + let classCount = objc_getClassList(nil, 0) + var className = "" + if classCount > 0 { + let classes = UnsafeMutablePointer.allocate(capacity: Int(classCount)) + defer { classes.deallocate() } + let autoreleasingClasses = AutoreleasingUnsafeMutablePointer(classes) + let count = objc_getClassList(autoreleasingClasses, classCount) + for i in 0.. AnyObject + let sel = NSSelectorFromString("initWithFrame:") + let m = try XCTUnwrap(class_getInstanceMethod(UIView.self, sel)) + let f = unsafeBitCast(method_getImplementation(m), to: InitWithFrame.self) + _ = f(cameraView, sel, .zero) + + // Assert that the initialization worked but the type is still the expected one + XCTAssertEqual(type(of: cameraView).description(), "CameraUI.ChromeSwiftUIView") + + // Add the view to the hierarchy with additional subviews which should not be traversed even though they need + // redaction (i.e. an UILabel). + cameraView.frame = CGRect(x: 10, y: 10, width: 150, height: 150) + subview.addSubview(cameraView) + + let nestedCameraView = UILabel(frame: CGRect(x: 30, y: 30, width: 50, height: 50)) + cameraView.addSubview(nestedCameraView) + + // -- Act -- + let sut = getSut() + let result = sut.redactRegionsFor(view: rootView) + + // -- Assert -- + XCTAssertEqual(result.count, 1) + XCTAssertEqual(result.element(at: 0)?.size, CGSize(width: 150, height: 150)) + XCTAssertEqual(result.element(at: 0)?.type, SentryRedactRegionType.redact) + XCTAssertEqual(result.element(at: 0)?.transform, CGAffineTransform(a: 1, b: 0, c: 0, d: 1, tx: 30, ty: 30)) + XCTAssertTrue(result.element(at: 0)?.name.contains("CameraUI.ChromeSwiftUIView") == true) + XCTAssertNil(result.element(at: 0)?.color) + } + + func testMapRedactRegion_viewHasCustomDebugDescription_shouldUseDebugDescriptionAsName() { + // -- Arrange -- + // We use a subclass of UILabel, so that the view is redacted by default + class CustomDebugDescriptionLabel: UILabel { + override var debugDescription: String { + return "CustomDebugDescription" + } + } + + let sut = getSut() + let view = CustomDebugDescriptionLabel(frame: CGRect(x: 20, y: 20, width: 40, height: 40)) + rootView.addSubview(view) + + // -- Act -- + let result = sut.redactRegionsFor(view: rootView) + + // -- Assert -- + XCTAssertEqual(result.count, 1) + XCTAssertEqual(result.first?.name, "CustomDebugDescription") + } + + func testViewSubtreeIgnored_noDuplicateRedactionRegions_whenViewMeetsBothConditions() throws { + // -- Arrange -- + // This test verifies that views meeting both general redaction criteria AND isViewSubtreeIgnored + // condition don't create duplicate redaction regions. The ordering of checks is important - + // isViewSubtreeIgnored must be checked first to prevent processing duplicates. + + let rootView = UIView(frame: .init(origin: .zero, size: .init(width: 200, height: 200))) + + // Create a CameraUI view that would trigger isViewSubtreeIgnored + // The key is that this CameraUI view should only generate ONE redaction region, not two + let cameraView = try createCameraUIView(frame: CGRect(x: 10, y: 10, width: 100, height: 100)) + rootView.addSubview(cameraView) + + // -- Act -- + let sut = getSut() + let result = sut.redactRegionsFor(view: rootView) + + // -- Assert -- + // Verify that exactly ONE redaction region is created for the CameraUI view, + // proving that the deduplication fix works and we don't get duplicate regions + XCTAssertEqual(result.count, 1, "Should have exactly one redaction region, not duplicates") + XCTAssertEqual(result.first?.size, CGSize(width: 100, height: 100)) + XCTAssertEqual(result.first?.type, SentryRedactRegionType.redact) + XCTAssertEqual(result.first?.transform, CGAffineTransform(a: 1, b: 0, c: 0, d: 1, tx: 10, ty: 10)) + XCTAssertTrue(result.first?.name.contains("CameraUI.ChromeSwiftUIView") == true) + } + + func testViewSubtreeIgnored_noDuplicatesWithCustomRedactedView() throws { + // -- Arrange -- + // This test more explicitly demonstrates the duplicate region scenario that could occur: + // A view hierarchy where a CameraUI view contains a UILabel that would normally be redacted. + // The ordering of checks is important - isViewSubtreeIgnored must be checked first to prevent + // duplicate redaction regions when views meet both conditions. + + let rootView = UIView(frame: .init(origin: .zero, size: .init(width: 200, height: 200))) + + // Create a CameraUI view that triggers isViewSubtreeIgnored + let cameraView = try createCameraUIView(frame: CGRect(x: 10, y: 10, width: 100, height: 100)) + rootView.addSubview(cameraView) + + // Create a view hierarchy: root -> cameraView -> label + // The label would normally be redacted, but since it's inside a CameraUI view that triggers + // isViewSubtreeIgnored, the entire subtree should be redacted as one region + let label = UILabel(frame: CGRect(x: 20, y: 20, width: 60, height: 30)) + label.text = "Test Label" + cameraView.addSubview(label) + + // -- Act -- + let sut = getSut() + let result = sut.redactRegionsFor(view: rootView) + + // -- Assert -- + // With the fix, we should get exactly ONE redaction region for the CameraUI view + // The label inside should NOT create a separate redaction region because the + // CameraUI view is handled with early return in isViewSubtreeIgnored + XCTAssertEqual(result.count, 1, "Should have exactly one redaction region for the CameraUI view, no duplicates or separate regions for nested views") + XCTAssertEqual(result.first?.size, CGSize(width: 100, height: 100), "Should redact the entire CameraUI view") + XCTAssertEqual(result.first?.type, SentryRedactRegionType.redact) + XCTAssertEqual(result.first?.transform, CGAffineTransform(a: 1, b: 0, c: 0, d: 1, tx: 10, ty: 10)) + XCTAssertTrue(result.first?.name.contains("CameraUI.ChromeSwiftUIView") == true) + } + + // MARK: - Helper Methods + + /// Creates a CameraUI.ChromeSwiftUIView instance for testing isViewSubtreeIgnored functionality. + /// - Parameters: + /// - frame: The frame to set for the created view + /// - Returns: The created CameraUI view + /// - Throws: XCTSkip if CameraUI is not available, or other errors if creation fails + private func createCameraUIView(frame: CGRect) throws -> UIView { + // Load the private framework indirectly by creating an instance of UIImagePickerController + let _ = UIImagePickerController() + + // Get the CameraUI.ChromeSwiftUIView class + let cameraViewClass: AnyClass + if #available(iOS 26.0, *) { + cameraViewClass = try XCTUnwrap( + NSClassFromString("CameraUI.ChromeSwiftUIView"), + "Test case expects the CameraUI.ChromeSwiftUIView class to exist" + ) + } else { + throw XCTSkip("Type CameraUI.ChromeSwiftUIView is not available on this platform") + } + + // Create an instance of the CameraUI view + let cameraView = try XCTUnwrap(class_createInstance(cameraViewClass, 0) as? UIView) + + // Reinitialize storage using UIView.initWithFrame(_:) + typealias InitWithFrame = @convention(c) (AnyObject, Selector, CGRect) -> AnyObject + let sel = NSSelectorFromString("initWithFrame:") + let m = try XCTUnwrap(class_getInstanceMethod(UIView.self, sel)) + let f = unsafeBitCast(method_getImplementation(m), to: InitWithFrame.self) + _ = f(cameraView, sel, .zero) + + // Configure the view frame + cameraView.frame = frame + + return cameraView + } } -#endif +#endif // os(iOS) diff --git a/Utils/VersionBump/main.swift b/Utils/VersionBump/main.swift index 687d6d1f0eb..5a1924f802d 100644 --- a/Utils/VersionBump/main.swift +++ b/Utils/VersionBump/main.swift @@ -50,8 +50,7 @@ let files = [ let restrictFiles = [ "./Sources/Configuration/SDK.xcconfig", "./Sources/Configuration/Versioning.xcconfig", - "./Sources/Configuration/SentrySwiftUI.xcconfig", - "./Samples/Shared/Config/Versioning.xcconfig" + "./Sources/Configuration/SentrySwiftUI.xcconfig" ] let args = CommandLine.arguments @@ -180,7 +179,7 @@ func getRegexString(for file: String) throws -> String { return "s\\.dependency\\s\"Sentry\\/HybridSDK\",\\s\"(?[a-zA-z0-9\\.\\-]+)\"" } return "\\ss\\.version\\s+=\\s\"(?[a-zA-z0-9\\.\\-]+)\"" - } else if file == "./Package.swift" { + } else if file.hasPrefix("./Package") && file.hasSuffix(".swift") { return "https:\\/\\/github\\.com\\/getsentry\\/sentry-cocoa\\/releases\\/download\\/(?[a-zA-z0-9\\.\\-]+)\\/Sentry" } else if file == "./Sources/Sentry/SentryMeta.m" { return "static NSString \\*versionString = @\"(?[a-zA-z0-9\\.\\-]+)\"" diff --git a/develop-docs/ARCHITECTURE.md b/develop-docs/ARCHITECTURE.md new file mode 100644 index 00000000000..2e518b9e518 --- /dev/null +++ b/develop-docs/ARCHITECTURE.md @@ -0,0 +1,123 @@ +# Sentry Cocoa SDK Architecture + +This document provides a high-level overview of the Sentry Cocoa SDK core components and codebase organization. + +## Core Architecture + +At the highest level, the SDK is composed of a few key components: + +- **SentrySDK**: a static wrapper around common functionality +- **SentryOptions**: a configuration class +- **SentryScope**: holds metadata that is sent with every event, to assist in querying later +- **SentryHub** and **SentryClient**: tie together configuration, features and scopes along with lower level machinery needed to store and transmit data + +## Feature Areas + +- **Performance Tracking**: `SentryTracer`, `SentrySpan`, `SentryPerformanceTracker` for transaction monitoring +- **App Start Tracking**: `SentryTimeToDisplayTracker` measures TTID/TTFD for UI performance; `SentryLaunchProfiling` manages profiling specifically for app launches +- **Session Replay**: Recording and transmission of user sessions +- **User Feedback**: Both code-based API to send feedback from users, and injectable UI to gather it from users +- **Crash Reporting**: Originally forked from KSCrash and independently evolved since then + +### Integrations + +The SDK packages most feature areas in "integrations" that inherit from the `SentryBaseIntegration` superclass. By default, it installs the following (order matters for initialization): + +**Core Integrations** (all platforms): + +- **SentrySessionReplayIntegration**: Session recording and replay (iOS 16+) +- **SentryCrashIntegration**: Crash detection and reporting +- **SentryANRTrackingIntegration**: Application Not Responding detection +- **SentryAutoBreadcrumbTrackingIntegration**: Automatic breadcrumb collection +- **SentryAutoSessionTrackingIntegration**: Session tracking and release health +- **SentryCoreDataTrackingIntegration**: Core Data performance monitoring +- **SentryFileIOTrackingIntegration**: File I/O performance tracking +- **SentryNetworkTrackingIntegration**: Network request monitoring +- **SentrySwiftAsyncIntegration**: Swift async/await support + +**UIKit Integrations** (iOS/tvOS/macOS with UIKit): + +- **SentryAppStartTrackingIntegration**: App launch performance measurement +- **SentryFramesTrackingIntegration**: Frame rate and rendering performance +- **SentryPerformanceTrackingIntegration**: Automatic performance transaction creation +- **SentryUIEventTrackingIntegration**: User interaction tracking +- **SentryViewHierarchyIntegration**: View hierarchy capture for debugging +- **SentryWatchdogTerminationTrackingIntegration**: Out-of-memory crash detection +- **SentryScreenshotIntegration**: Screenshot capture on errors + +**Platform-Specific Integrations**: + +- **SentryUserFeedbackIntegration**: User feedback UI (iOS 13+) +- **SentryMetricKitIntegration**: Apple MetricKit integration (iOS 15+, macOS 12+) + +### Spotlight + +In addition to the component that uploads data to the Sentry backend (`SentryHTTPTransport`), customers can also set `SentryOptions.enableSpotlight` to also send that data to a local running program to inspect the contents of the payloads. See more at https://spotlightjs.com and https://github.com/getsentry/spotlight. + +### Profiling + +In addition to tracing and spans, the SDK provides a sampling profiler that captures the stack traces of all running threads at regular intervals so that developers can see what is happening in their code at a specific time, and aggregate and query the stack trace samples to find performance issues. The SDK supports multiple profiling modes: + +### Transaction profiling + +The profiler runs on a dedicated thread, and on a predefined interval will enumerate all other threads and gather the backtrace on each non-idle thread. + +The information is stored in deduplicated frame and stack indexed lookups for memory and transmission efficiency. These are maintained in `SentryProfilerState`. + +If enabled and sampled in (controlled by `SentryOptions.profilesSampleRate` or `SentryOptions.profilesSampler`), the profiler will start along with a trace, and the profile information is sliced to the start and end of each transaction and sent with them an envelope attachments. + +The profiler will automatically time out if it is not stopped within 30 seconds, and also stops automatically if the app is sent to the background. + +With transaction profiling, there's only ever one profiler instance running at a time, but instances that have timed out will be kept in memory until all traces that ran concurrently with it have finished and serialized to envelopes. The associations between profiler instances and traces are maintained in `SentryProfiledTracerConcurrency`. + +### Continuous profiling (beta) + +With continuous profiling, there's also only ever one profiler instance running at a time. They are either started manually by customers or automatically based on active root span counts. They aren't tied to transactions otherwise so are immediately captured in envelopes when stopped. + +### UI Profiling + +Also referred to in implementation as continuous profiling V2. Essentially a combination of transaction-based profiling (although now focused on "root spans" instead of transactions) for the trace lifecycle and continuous profiling beta for the manual lifecycle, with the exception that manual mode also respects a configured sample rate. + +The sample apps are configured by default to use UI Profiling with trace lifecycle (to override the default of manual lifecycle), traces and profile session sample rates of 1 (to override the defaults of 0), and to use app start profiling. + +### Launch Profiling + +Key files: + +- `Sources/Sentry/Profiling/SentryLaunchProfiling.m`: Main launch profiling logic +- `Sources/Sentry/SentryTimeToDisplayTracker.m`: TTID/TTFD tracking with profiling integration +- `Sources/Sentry/Profiling/SentryProfiledTracerConcurrency.mm`: Profiler/tracer lifecycle management + +Order of operations: + +- `sentry_startLaunchProfile()` called early in app lifecycle from `SentryTracer.load` + - for transaction profiling and trace lifecycle UI profiling, a tracer is created to manage profiling session +- Configuration written to disk via `sentry_configureLaunchProfiling` during SentrySDK.start +- Before SentrySDK.start completes, it checks to see if it should stop any running launch profiler + - if TTID/TTFD tracking is enabled and the launch profile is a transaction profile or UI profile with trace lifecycle, stopping profiles is deferred until TTID/TTFD + - otherwise for transaction/trace profiles, `sentry_stopAndDiscardLaunchProfileTracer()` is called + - otherwise, the profile continues until SentrySDK.stopProfiler is called in consumer code + +### Testing + +Note that the profiler cannot run if a process is running with the thread sanitizer. + +In testing and debug environments, when a profile payload is serialized for transmission, the dictionary will also be written to a file in NSCachesDirectory that can be retrieved by a sample app. This helps with UI tests that want to verify the contents of a profile after some app interaction. See `iOS-Swift.ProfilingViewController.viewLastProfile` and `iOS-Swift-UITests.ProfilingUITests`. + +## Headers + +Non public headers should be placed into `Sources/include` + +To make a header public follow these steps: + +- Move it into the folder [Public](/Sources/Sentry/Public). Both [CocoaPods](Sentry.podspec) and [Swift Package Manager](Package.swift) make all headers in this folder public. +- Add it to the Umbrella Header [Sentry.h](/Sources/Sentry/Public/Sentry.h). +- Set the target membership to public. + +## Logging + +We have a set of macros for logging at various levels defined in SentryLog.h. These are not async-safe because they use NSLog, which takes its own lock, and aren't suitable for SentryCrash. + +### SentryCrash Logging + +In SentryCrash we have to use SentryAsyncSafeLog and we can't use NSLog, as it's not async-safe. Therefore, logging to the console is disabled for log messages from SentryAsyncSafeLog. You can enable it by setting `SENTRY_ASYNC_SAFE_LOG_ALSO_WRITE_TO_CONSOLE` to `1`, but you MUST NEVER commit this change. SentryAsyncSafeLog writes its messages to the file `/Caches/io.sentry/async.log`. The default log level is error. To see all log messages set `SENTRY_ASYNC_SAFE_LOG_LEVEL` in `SentryAsyncSafeLog.h` to `SENTRY_ASYNC_SAFE_LOG_LEVEL_TRACE`. diff --git a/develop-docs/BUILD.md b/develop-docs/BUILD.md new file mode 100644 index 00000000000..889b404b0aa --- /dev/null +++ b/develop-docs/BUILD.md @@ -0,0 +1,42 @@ +# Build Configuration + +This document covers the build system and configuration details for the Sentry Cocoa SDK. + +### SDK Build Configuration + +- XCConfig files in `Sources/Configuration/` for SDK settings; settings should not be modified in pbxproj files + +## UIKit Linking Control + +Some customers would like to not link UIKit for various reasons. Either they simply may not want to use our UIKit functionality, or they actually cannot link to it in certain circumstances, like a File Provider app extension. + +There are two build configurations they can use for this: `DebugWithoutUIKit` and `ReleaseWithoutUIKit`, that are essentially the same as `Debug` and `Release` with the following differences: + +- They set `CLANG_MODULES_AUTOLINK` to `NO`. This avoids a load command being automatically inserted for any UIKit API that make their way into the type system during compilation of SDK sources. +- `GCC_PREPROCESSOR_DEFINITIONS` has an additional setting `SENTRY_NO_UIKIT=1`. This is now part of the definition of `SENTRY_HAS_UIKIT` in `SentryDefines.h` that is used to conditionally compile out any code that would otherwise use UIKit API and cause UIKit to be automatically linked as described above. There is another macro `SENTRY_UIKIT_AVAILABLE` defined as `SENTRY_HAS_UIKIT` used to be, meaning simply that compilation is targeting a platform where UIKit is available to be used. This is used in headers we deliver in the framework bundle to compile out declarations that rely on UIKit, and their corresponding implementations are switched over `SENTRY_HAS_UIKIT` to either provide the logic for configurations that link UIKit, or to provide a stub delivering a default value (`nil`, `0.0`, `NO` etc) and a warning log for publicly facing things like SentryOptions, or debug log for internal things like SentryDependencyContainer. + +There are two jobs in `.github/workflows/build.yml` that will build each of the new configs and use `otool -L` to ensure that UIKit does not appear as a load command in the build products. + +This feature is experimental and is currently not compatible with SPM. + +## Build System Commands + +```bash +make build-xcframework # Build XCFramework for distribution +make pod-lint # Validate CocoaPods specs +make bump-version TO=X.Y.Z # Bump version (requires TO parameter) +``` + +## Platform-Specific Build Notes + +### visionOS Considerations + +- Requires `SWIFT_OBJC_INTEROP_MODE=objcxx` for static framework +- Cannot call C functions directly from Swift with visionOS settings +- Special handling required for mixed Swift/Objective-C code + +### SPM Limitations + +- Uses pre-built binaries for faster builds and mixed-language limitations +- Binary distribution via git release assets +- Not compatible with UIKit-free configurations diff --git a/develop-docs/DECISIONS.md b/develop-docs/DECISIONS.md index a1a6a81a886..42c97e78dda 100644 --- a/develop-docs/DECISIONS.md +++ b/develop-docs/DECISIONS.md @@ -419,3 +419,17 @@ Related links: - https://github.com/getsentry/sentry-cocoa/issues/4887 - https://github.com/getsentry/sentry-cocoa/pull/4910 + +## Decodable conformances to ObjC types + +A few types that are defined in ObjC have Decodable conformances in "Sources/Swift/Protocol/Codable/". This works for xcodebuild where ObjC and Swift are in the same target +but not for SPM where ObjC and Swift have to be in different targets. This is because Swift does not support adding a protocol conformance to a type in a different module +than the one the type/protocol is defined in. To work around this Swift code subclasses the ObjC type and adds the conformance to the subclass. It is then decoded as a +subclass and cast back to the superclass. This is only done for SPM, not xcodebuild, because the Codable conformance is part of the public API and therefore requires a +major version bump to change. + +Future types conforming to Decodable can be written in Swift from the start and therefore have the conformance added directly to the type. + +## v9 + +Work on the v9 SDK is being done behind the compiler flag `SDK_V9`. CI builds the SDK with this flag enabled to ensure it does not break during the course of non-v9 development. This SDK version will focus on quality and be a part of Sentry’s quality quarter initiative. Notably, the minimum supported OS version will be bumped in this release. The changelog for this release is being tracked in [CHANGELOG-v9.md](../CHANGELOG-v9.md). diff --git a/develop-docs/README.md b/develop-docs/README.md index ba3e53d36e4..0e753e310b8 100644 --- a/develop-docs/README.md +++ b/develop-docs/README.md @@ -1,289 +1,9 @@ # Develop Documentation -This page contains internal documentation for development. +This is a collection of documents that can help you develop for the SentrySDK. -## Coding with Swift - -To use Swift in the project take a look at [Swift Usage](Swift-Usage.md) documentation. - -## Code Signing - -This repository follows the [codesiging.guide](https://codesigning.guide/) in combination with [fastlane match](https://docs.fastlane.tools/actions/match/). -Therefore the sample apps use manual code signing, see [fastlane docs](https://docs.fastlane.tools/codesigning/xcode-project/): - -> In most cases, fastlane will work out of the box with Xcode 9 and up if you selected manual code signing and choose a provisioning profile name for each of your targets. - -### Creating new App Identifiers - -E.g. if you create a new extension target, like a File Provider for iOS-Swift, make sure it has a unique bundle identifier like `io.sentry.sample.iOS-Swift.FileProvider`. Then, run the following terminal command: - -``` -rbenv exec bundle exec fastlane produce -u andrew.mcknight@sentry.io --skip_itc -a io.sentry.sample.iOS-Swift.FileProvider -``` - -You'll be prompted for an Apple Developer Portal 2FA code, and the description for the identifier; in this example, "Sentry Cocoa Sample Swift File Provider Extension". - -### Creating provisioning profiles - -For an existing app identifier, run the terminal command, after changing the email address in the Matchfile to your personal ADP account's: - -``` -rbenv exec bundle exec fastlane match development --app_identifier io.sentry.sample.iOS-Swift.FileProvider -``` - -You can include the `--force` option to regenerate an existing profile. - -### Help - -Reach out to a [CODEOWNER](https://github.com/getsentry/sentry-cocoa/blob/main/.github/CODEOWNERS) if you need access to the match git repository. - -## Testing - -### Unit Tests with Thread Sanitizer - -CI runs the unit tests for one job with thread sanitizer enabled to detect race conditions. -To ignore false positives or known issues, use the `SENTRY_DISABLE_THREAD_SANITIZER` macro or the [suppression file](../Sources/Resources/ThreadSanitizer.sup). -It's worth noting that you can use the `$(PROJECT_DIR)` to specify the path to the suppression file. -To run the unit tests with the thread sanitizer enabled in Xcode click on edit scheme, go to tests, then open diagnostics, and enable Thread Sanitizer. -The profiler doesn't work with TSAN attached, so tests that run the profiler will be skipped. - -#### Further Reading - -- [ThreadSanitizerSuppressions](https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions) -- [Running Tests with Clang's AddressSanitizer](https://pspdfkit.com/blog/2016/test-with-asan/) -- [Diagnosing Memory, Thread, and Crash Issues Early](https://developer.apple.com/documentation/xcode/diagnosing-memory-thread-and-crash-issues-early) -- [Stackoverflow: ThreadSanitizer suppression file with Xcode](https://stackoverflow.com/questions/38251409/how-can-i-suppress-thread-sanitizer-warnings-in-xcode-from-an-external-library) - -### Using Xcode Test Plans - -Test plans in Xcode provide a convenient way to organize and configure test execution. -They allow us to segment tests into different groups and configure specific test environments without creating additional targets or schemes. -Furthermore, test plans provide additional features such as built-in test repetition and retry on failures, automatic screen capture for debugging UI test failures, and custom test configurations for different scenarios. - -Each Xcode scheme can have multiple test plans configured, but only one test plan can be marked as the default test plan. -When adding new test plans, they must also be added to the relevant schemes. - -Some of the features of test plans are: - -- Built-in test repetition and retry on failures -- Automatic screen capture for debugging UI test failures -- Custom test configurations for different scenarios - -Additional outputs are written to the Xcode results (`.xcresult`) files, which can be found in the `~/Library/Developer/Xcode/DerivedData/.../Logs/Test/` directory. - -#### Base Test Plans - -We maintain "base" test plans that automatically include all new tests as they are configured by defining a list skipped tests. -This prevents tests from being accidentally excluded and provides convenience when adding new test files. - -In case a test is manually marked as skipped in the test plan, it should be added to another test plan (which must also be used in the CI workflow). -When using `xcodebuild` to run tests, only the default test plan is executed unless explicitly specified with the -testPlan argument. - -#### Test Plan Organization - -Test plans are stored in the repository root since they are shared between sample apps and SDK targets. -This central location makes them easily accessible while maintaining the relationship between plans and schemes. - -#### UI Test Recording - -It is possible to record UI tests by changing the test plan configuration `Automatic Screen Capture` to `On, and keep all` or `On, and delete if test succeeds`. - -After running the tests with the configuration set, it is possible to open the test results in Xcode, inspect the tests in detail by double clicking them. - -![UI Test Capture Settings](./xcode_test_plan_uicapture_settings.png) - -The details of the test case will display the UI Test history and also display playback of the screen captures. - -![UI Test Capture Playback](./xcode_test_plan_uicapture_playback.png) - -#### Further Resources - -For more details on test plans and their capabilities, refer to: - -- [WWDC21 video on Test Plans](https://developer.apple.com/videos/play/wwdc2021/10296/) -- [Apple's documentation on Test Plans](https://developer.apple.com/documentation/xcode/running-tests-and-interpreting-results) - -### Test Logs - -We used to set the log level to debug all tests to investigate flaky tests. For individual tests we then disabled the logs because printing the messages via NSLog uses synchronization and caused specific tests to fail due to timeouts in CI. The debug logs can also be extremely verbose for tests using tight loops and completely spamming the test logs. - -Therefore, the default log level is error for tests. If debug logs can help with fixing flaky tests, we should enable these for specific test cases only with `SentrySDKLog.withDebugLogs`. - -### UI Tests - -CI runs UI tests on simulators via the `ui-tests.yml` workflow for every PR and every commit on main. - -#### Saucelabs - -You can find the available devices on [their website](https://saucelabs.com/platform/supported-browsers-devices). Another way to check their available devices is to go to [live app testing](https://app.saucelabs.com/live/app-testing), go to iOS-Swift and click on choose device. This brings the full list of devices with more details. - -### Test Expectations - -We recommend using `XCTAssertEqual(, )` over `XCTAssertEqual(, )` for no strong reason, but to align so tests are consistent and therefore easier to read. - -## Performance benchmarking - -Once daily and for every PR via [Github action](../.github/workflows/benchmarking.yml), the benchmark runs in Sauce Labs, on a [high-end device](https://github.com/getsentry/sentry/blob/8986f81e19f63ee370b1649e08630c9b946c87ed/src/sentry/profiles/device.py#L43-L49) we categorize. Benchmarks run from an XCUITest (`iOS-Benchmarking` target) using the iOS-Swift sample app, under the `iOS-Benchmarking` scheme. [`PerformanceViewController`](../Samples/iOS-Swift/ViewControllers/PerformanceViewController.swift) provides a start and stop button for controlling when the benchmarking runs, and a text field to marshal observations from within the test harness app into the test runner app. There, we assert that the P90 of all trials remains under 5%. We also print the raw results to the test runner's console logs for postprocessing into reports with `//scripts/process-benchmark-raw-results.py`. - -### Test procedure - -- Tap the button to start a Sentry transaction with the associated profiling. -- Run a loop performing large amount of calculations to use as much CPU as possible. This simulates something an app developer would want to profile in a real world scenario. -- While benchmarking, run a sampling profiler at 10 Hz to calculate the CPU usage of each thread, in particular the Sentry profiler's, to calculate its relative usage. -- Tap the button to stop the transaction after waiting for 15 seconds. -- Calculate the total time used by app threads and separately, the profiler's thread. Keep separated by system call and user call times. -- Write these four values as CSV into the text field accessible as an XCUIElement in the runner app. - -### Test Plan - -- Run the procedure 20 times, then assert that the 90th percentile remains under 5% so we can be alerted via CI if it spikes. - - Sauce Labs allows relaxing the timeout for a suite of tests and for a `XCTestCase` subclass' collection of test case methods, but each test case in the suite must run in less than 15 minutes. 20 trials takes too long, so we split it up into multiple test cases, each running a subset of the trials. - - This is done by dynamically generating test case methods in `SentrySDKPerformanceBenchmarkTests`, which is necessarily written in Objective-C since this is not possible to do in Swift tests. By doing this dynamically, we can easily fine tune how we split up the work to account for changes in the test duration or in constraints on how things run in Sauce Labs etc. - -## Upload iOS-Swift's dSYMs with Xcode Run Script - -The following script applies a patch so Xcode uploads the iOS-Swift's dSYMs to Sentry during Xcode's build phase. -Ensure to not commit the patch file after running this script, which then contains your auth token. - -```sh -./scripts/upload-dsyms-with-xcode-build-phase.sh YOUR_AUTH_TOKEN -``` - -## Generating classes - -You can use the `generate-classes.sh` to generate ViewControllers and other classes to emulate a large project. This is useful, for example, to test the performance of swizzling in a large project without having to check in thousands of lines of code. - -## UIKit - -Some customers would like to not link UIKit for various reasons. Either they simply may not want to use our UIKit functionality, or they actually cannot link to it in certain circumstances, like a File Provider app extension. - -There are two build configurations they can use for this: `DebugWithoutUIKit` and `ReleaseWithoutUIKit`, that are essentially the same as `Debug` and `Release` with the following differences: - -- They set `CLANG_MODULES_AUTOLINK` to `NO`. This avoids a load command being automatically inserted for any UIKit API that make their way into the type system during compilation of SDK sources. -- `GCC_PREPROCESSOR_DEFINITIONS` has an additional setting `SENTRY_NO_UIKIT=1`. This is now part of the definition of `SENTRY_HAS_UIKIT` in `SentryDefines.h` that is used to conditionally compile out any code that would otherwise use UIKit API and cause UIKit to be automatically linked as described above. There is another macro `SENTRY_UIKIT_AVAILABLE` defined as `SENTRY_HAS_UIKIT` used to be, meaning simply that compilation is targeting a platform where UIKit is available to be used. This is used in headers we deliver in the framework bundle to compile out declarations that rely on UIKit, and their corresponding implementations are switched over `SENTRY_HAS_UIKIT` to either provide the logic for configurations that link UIKit, or to provide a stub delivering a default value (`nil`, `0.0`, `NO` etc) and a warning log for publicly facing things like SentryOptions, or debug log for internal things like SentryDependencyContainer. - -There are two jobs in `.github/workflows/build.yml` that will build each of the new configs and use `otool -L` to ensure that UIKit does not appear as a load command in the build products. - -This feature is experimental and is currently not compatible with SPM. - -## Logging - -We have a set of macros for logging at various levels defined in SentryLog.h. These are not async-safe because they use NSLog, which takes its own lock, and aren't suitable for SentryCrash. - -### SentryCrash Logging - -In SentryCrash we have to use SentryAsyncSafeLog and we can't use NSLog, as it's not async-safe. Therefore, logging to the console is disabled for log messages from SentryAsyncSafeLog. You can enable it by setting `SENTRY_ASYNC_SAFE_LOG_ALSO_WRITE_TO_CONSOLE` to `1`, but you MUST NEVER commit this change. SentryAsyncSafeLog writes its messages to the file `/Caches/io.sentry/async.log`. The default log level is error. To see all log messages set `SENTRY_ASYNC_SAFE_LOG_LEVEL` in `SentryAsyncSafeLog.h` to `SENTRY_ASYNC_SAFE_LOG_LEVEL_TRACE`. - -## Profiling - -### Transaction profiling - -The profiler runs on a dedicated thread, and on a predefined interval will enumerate all other threads and gather the backtrace on each non-idle thread. - -The information is stored in deduplicated frame and stack indexed lookups for memory and transmission efficiency. These are maintained in `SentryProfilerState`. - -If enabled and sampled in (controlled by `SentryOptions.profilesSampleRate` or `SentryOptions.profilesSampler`), the profiler will start along with a trace, and the profile information is sliced to the start and end of each transaction and sent with them an envelope attachments. - -The profiler will automatically time out if it is not stopped within 30 seconds, and also stops automatically if the app is sent to the background. - -With transaction profiling, there's only ever one profiler instance running at a time, but instances that have timed out will be kept in memory until all traces that ran concurrently with it have finished and serialized to envelopes. The associations between profiler instances and traces are maintained in `SentryProfiledTracerConcurrency`. - -App launches can be automatically profiled if configured with `SentryOptions.enableAppLaunchProfiling`. If enabled, when `SentrySDK.startWithOptions` is called, `SentryLaunchProfiling.configureLaunchProfiling` will get a sample rate for traces and profiles with their respective options, and store those rates in a file to be read on the next launch. On each launch, `SentryLaunchProfiling.startLaunchProfile` checks for the presence of that file is used to decide whether to start an app launch profiled trace, and afterwards retrieves those rates to initialize a `SentryTransactionContext` and `SentryTracerConfiguration`, and provides them to a new `SentryTracer` instance, which is what actually starts the profiler. There is no hub at this time; also in the call to `SentrySDK.startWithOptions`, any current profiled launch trace is attempted to be finished, and the hub that exists by that time is provided to the `SentryTracer` instance via `SentryLaunchProfiling.stopAndTransmitLaunchProfile` so that when it needs to transmit the transaction envelope, the infrastructure is in place to do so. If TTID/TTFD tracking is also enabled, then the launch profile is stopped when the SDK detects that initial/full display have completed, instead of when `SentrySDK.startWithOptions` is called. - -### Continuous profiling (beta) - -With continuous profiling, there's also only ever one profiler instance running at a time. They are either started manually by customers or automatically based on active root span counts. They aren't tied to transactions otherwise so are immediately captured in envelopes when stopped. - -### UI Profiling - -Also referred to in implementation as continuous profiling V2. Essentially a combination of transaction-based profiling (although now focused on "root spans" instead of transactions) for the trace lifecycle and continuous profiling beta for the manual lifecycle, with the exception that manual mode also respects a configured sample rate. - -The sample apps are configured by default to use UI Profiling with trace lifecycle (to override the default of manual lifecycle), traces and profile session sample rates of 1 (to override the defaults of 0), and to use app start profiling. - -### Sample apps - -> The sample apps are moving towards being managed by [XcodeGen](https://github.com/yonaskolb/XcodeGen). Run `make xcode` to ensure that the projects in Sentry.xcworkspace are present and up-to-date. You can add this to your `post-checkout` git hook to automate the process: `echo "make xcode" >> .git/hooks/post-checkout`. - -The iOS-Swift and iOS-ObjectiveC sample apps have schema launch args and environment variables available to customize how the SDK is configured. - -In iOS-Swift, these can also be modified at runtime, to help test various configurations in scenarios where using launch args and environment variables isn't possible, like TestFlight builds. Runtime overrides are set via `UserDefaults`. They interact with schema launch arguments and environment variables as follows: - Boolean flags are ORed together: if either a `true` is set in User Defaults, or a launch argument is set, then the override takes effect. - Values written to user defaults take precedence over schema environment variables by default. If you want to give precedence to schema environment vars over user defaults values, enable the launch arg `--io.sentry.schema-environment-variable-precedence`. - -Note that if a key we use to write a boolean value to defaults isn't present in defaults, then UserDefaults returns `false` for the query by default. We write all environment variables as strings, so that by default, if the associated key isn't present, `UserDefaults` returns `nil` (if we directly wrote and read Floats, for example, defaults would return `0` if the key isn't present, and we'd have to do more work to disambiguate that from having overridden it to 0, for cases where 0 isn't the default we want to set in the sample app). - -You can see the current override value being used in the "Features" tab. - -You can also remove all stored values in user defaults by launching with `--io.sentry.wipe-data`. See `SentrySDKWrapper.swift` and `SentrySDKOverrides.swift` for usages. - -Note that in-app overrides don't take effect until the app is relaunched (and not simply backgrounded and then foregrounded again). This means that if you want to test changes to launch profiling, you must change the settings, then relaunch the app for the launch profile configuration to be written to disk, and then relaunch once more for the launch profile scenario to actually be tested. - -### Testing - -In testing and debug environments, when a profile payload is serialized for transmission, the dictionary will also be written to a file in NSCachesDirectory that can be retrieved by a sample app. This helps with UI tests that want to verify the contents of a profile after some app interaction. See `iOS-Swift.ProfilingViewController.viewLastProfile` and `iOS-Swift-UITests.ProfilingUITests`. - -## Swift and Objective-C Interoperability - -When making an Objective-C class public for Swift SDK code, do the following: - -- Add it to SentryPrivate.h -- Remove existing imports from any test bridging headers. -- Add the import `@_implementationOnly import _SentryPrivate` to your Swift class that wants to use - the Objective-C class. - -To make internal Swift code accessible to ObjC it needs to be `public`. This allows the ObjC header to be generated by Swift Package Manager. -To discourage use outside of the SDK, add `@_spi(Private)` to these declarations. This ensures they can only be used when the import also -adds the SPI attribute. - -## Public Protocols - -pod lib lint fails with the warning duplicate protocol definition when including a public header for -a protocol in a private ObjC class header, when adding that header to `SentryPrivate.h` to expose it -to internal SDK Swift code, as `SentrySDKInfo.h`. To solve this problem we have to use the -`SentryInternalSerializable` for internal classes implementing serializable. - -### Detailed explanation of the Swift and Objective-C Interoperability setup - -The SentrySDK uses Swift and Objective-C code. Public Objective-C classes, made public -[through the umbrella header](https://developer.apple.com/documentation/swift/importing-objective-c-into-swift#Import-Code-Within-a-Framework-Target), -are automatically visible to Swift without imports. Our umbrella header is defined in the `Sentry.modulemap`. -Accessing private Objective-C classes doesn't -work out of the box. One approach to making this work is to define a private module that contains -all the private ObjC headers. To define such a module, we added a module.modulemap file to our -project with the name _SentryPrivate. We added the prefix `_`because Xcode autocomplete seems to ignore such modules. This modulemap file points to a header called`SentryPrivate.h`, which include all private ObjC headers that should be available for Swift. When importing the generated _SentryPrivate module we have to use `@\_implementationOnly import \_SentryPrivate`. -[@_implementationOnly](https://github.com/apple/swift/blob/main/docs/ReferenceGuides/UnderscoredAttributes.md#_implementationonly) will most likely be superseded by [access level imports](https://github.com/apple/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md) in a future Swift version. Not using `@\_implementationOnly` leads to errors when including the -prebuilt XCFramwork into projects, such as: - -```sh -Sentry.swiftmodule/arm64-apple-ios.private.swiftinterface:10:8: error: no such module '_SentryPrivate' - -import _SentryPrivate -``` - -Adding Objective-C classes to the \_SentryPrivate module also exposes them to test classes written in -Swift. When making an Objective-C class public to SDK Swift code, we must remove it from test -bridging headers because this can lead to compiler errors. The SentryTests only find the -\_SentryPrivate module when adding setting `HEADER_SEARCH_PATHS = $(SRCROOT)/Sources/Sentry/include/**` -which we must not set for SwiftUI, because this uses its own implementation of SentryInternal.h. -Setting the `HEADER_SEARCH_PATHS` for SwiftUI breaks the build. - -See also [decision to remove SentryPrivate](./DECISIONS.md#removing-sentryprivate). - -Useful resources: - -- [Module Map Syntax](https://clang.llvm.org/docs/Modules.html#module-map-file) -- Sample GH Repo for [mixed Swift ObjC Framework](https://github.com/danieleggert/mixed-swift-objc-framework) -- [Swift Forum Discussion](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/6) -- [Apple Docs: Importing Objective-C into Swift](https://developer.apple.com/documentation/swift/importing-objective-c-into-swift#Import-Code-Within-a-Framework-Target) - -## Decodable conformances to ObjC types - -A few types that are defined in ObjC have Decodable conformances in "Sources/Swift/Protocol/Codable/". This works for xcodebuild where ObjC and Swift are in the same target -but not for SPM where ObjC and Swift have to be in different targets. This is because Swift does not support adding a protocol conformance to a type in a different module -than the one the type/protocol is defined in. To work around this Swift code subclasses the ObjC type and adds the conformance to the subclass. It is then decoded as a -subclass and cast back to the superclass. This is only done for SPM, not xcodebuild, because the Codable conformance is part of the public API and therefore requires a -major version bump to change. - -Future types conforming to Decodable can be written in Swift from the start and therefore have the conformance added directly to the type. - -## v9 - -Work on the v9 SDK is being done behind the compiler flag `SDK_V9`. CI builds the SDK with this flag enabled to ensure it does not break during the course of non-v9 development. This SDK version will focus on quality and be a part of Sentry’s quality quarter initiative. Notably, the minimum supported OS version will be bumped in this release. +- ARCHITECTURE.md: the high-level concepts, features and organization of the codebase +- 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 +- RELEASE.md: our release processes and best practices diff --git a/develop-docs/RELEASE.md b/develop-docs/RELEASE.md new file mode 100644 index 00000000000..bcd0c5a0829 --- /dev/null +++ b/develop-docs/RELEASE.md @@ -0,0 +1,18 @@ +# SDK Releases + +This repo uses the following ways to release SDK updates: + +- `Pre-release`: We create pre-releases (alpha, beta, RC,…) for larger and potentially more impactful changes, such as new features or major versions. +- `Latest`: We continuously release major/minor/hotfix versions from the `main` branch. These releases go through all our internal quality gates and are very safe to use and intended to be the default for most teams. +- `Stable`: We promote releases from `Latest` when they have been used in the field for some time and in scale, considering time since release, adoption, and other quality and stability metrics. These releases will be indicated on the [releases page](https://github.com/getsentry/sentry-cocoa/releases/) with the `Stable` suffix. + +## Promoting a beta release to a normal release + +We frequently release a beta version of our SDK and dogfood it with internal apps to increase our SDK stability. We continue to merge PRs to the main branch, so we can't promote a beta release by publishing it from the main branch. Instead, we create a branch from the GH tag of the beta release and promote it from there. To do this, follow these steps: + +1. Checkout a new branch from the GH tag of the beta release: `git checkout -b publish/x.x.x x.x.x-beta.1`. You can't use `release/x.x.x` or `x.x.x` as the branch name as craft will fail, as it creates a `release/x.x.x` branch for updating the changelog and it will create a tag `x.x.x` for the release. +2. Duplicate the Changelog.md entry of the beta release and change header of the version number to unreleased. +3. Commit and push the changes. +4. Trigger the release workflow with use workflow from the `publish/x.x.x` branch and set the target branch to merge into to `publish/x.x.x`, cause per default craft will merge into the main branch and this could lead to merge conflicts in the changelog. +5. After the successful release, validate that craft merged the changes back into `publish/x.x.x` branch and deleted the release branch. +6. Manually open a PR from the `publish/x.x.x` branch into the main branch and merge it. diff --git a/develop-docs/SWIFT.md b/develop-docs/SWIFT.md new file mode 100644 index 00000000000..25737e8d94d --- /dev/null +++ b/develop-docs/SWIFT.md @@ -0,0 +1,86 @@ +# Swift Usage + +Starting from version 8.0.0, it is now possible to include Swift code in the project. All Swift files should be placed under the `/Sources/Swift` directory. + +> In this document, `SentryPrivate` refers to the library written in Swift, while `Sentry` represents the framework written in Objective-C. The term `SentryPrivate` public API refers to the API that will be consumed by `Sentry` and is not intended for direct use by users. + +## Notes + +1. All Swift code will be bundled within the `SentryPrivate` library, which `Sentry` depends on. +2. User-facing APIs cannot be written in Swift because their components will be accessed through imports from "SentryPrivate." +3. `SentryPrivate` does not have access to `Sentry` classes to avoid cyclic references. As a result, any code written in Objective-C is not accessible from the Swift layer. + - However, it is possible to create Dependency Injection (DI) APIs in Swift, allowing `Sentry` to inject its objects for use within `SentryPrivate`. +4. `SentryPrivate` public APIs (code consumed by `Sentry`) cannot utilize certain Objective-C incompatible features, including: + - Generics + - Non-@objc protocols and protocol extensions + - Top-level functions and properties + - Global variables + - Structs + - Swift-only enums + - Swift-only optionals + - Swift-only tuples + +## Objective-C Interoperability + +- **ObjC to Swift**: Import `#import "SentrySwift.h"` +- **Swift to ObjC**: Add header to `SentryInternal.h`, then `@_implementationOnly import _SentryPrivate` +- **Module system**: `_SentryPrivate` module for internal ObjC headers accessible to Swift + +When making an Objective-C class public for Swift SDK code, do the following: + +- Add it to SentryPrivate.h +- Remove existing imports from any test bridging headers. +- Add the import `@_implementationOnly import _SentryPrivate` to your Swift class that wants to use + the Objective-C class. + +To make internal Swift code accessible to ObjC it needs to be `public`. This allows the ObjC header to be generated by Swift Package Manager. +To discourage use outside of the SDK, add `@_spi(Private)` to these declarations. This ensures they can only be used when the import also +adds the SPI attribute. + +Public Objective-C classes, made public +[through the umbrella header](https://developer.apple.com/documentation/swift/importing-objective-c-into-swift#Import-Code-Within-a-Framework-Target), +are automatically visible to Swift without imports. Our umbrella header is defined in the `Sentry.modulemap`. +Accessing private Objective-C classes doesn't +work out of the box. One approach to making this work is to define a private module that contains +all the private ObjC headers. To define such a module, we added a module.modulemap file to our +project with the name _SentryPrivate. We added the prefix `_`because Xcode autocomplete seems to ignore such modules. This modulemap file points to a header called`SentryPrivate.h`, which include all private ObjC headers that should be available for Swift. When importing the generated _SentryPrivate module we have to use `@\_implementationOnly import \_SentryPrivate`. +[@_implementationOnly](https://github.com/apple/swift/blob/main/docs/ReferenceGuides/UnderscoredAttributes.md#_implementationonly) will most likely be superseded by [access level imports](https://github.com/apple/swift-evolution/blob/main/proposals/0409-access-level-on-imports.md) in a future Swift version. Not using `@\_implementationOnly` leads to errors when including the +prebuilt XCFramwork into projects, such as: + +```sh +Sentry.swiftmodule/arm64-apple-ios.private.swiftinterface:10:8: error: no such module '_SentryPrivate' + +import _SentryPrivate +``` + +Adding Objective-C classes to the \_SentryPrivate module also exposes them to test classes written in +Swift. When making an Objective-C class public to SDK Swift code, we must remove it from test +bridging headers because this can lead to compiler errors. The SentryTests only find the +\_SentryPrivate module when adding setting `HEADER_SEARCH_PATHS = $(SRCROOT)/Sources/Sentry/include/**` +which we must not set for SwiftUI, because this uses its own implementation of SentryInternal.h. +Setting the `HEADER_SEARCH_PATHS` for SwiftUI breaks the build. + +See also [decision to remove SentryPrivate](./DECISIONS.md#removing-sentryprivate). + +Useful resources: + +- [Module Map Syntax](https://clang.llvm.org/docs/Modules.html#module-map-file) +- Sample GH Repo for [mixed Swift ObjC Framework](https://github.com/danieleggert/mixed-swift-objc-framework) +- [Swift Forum Discussion](https://forums.swift.org/t/mixing-swift-and-objective-c-in-a-framework-and-private-headers/27787/6) +- [Apple Docs: Importing Objective-C into Swift](https://developer.apple.com/documentation/swift/importing-objective-c-into-swift#Import-Code-Within-a-Framework-Target) + +## Public Protocols + +pod lib lint fails with the warning duplicate protocol definition when including a public header for +a protocol in a private ObjC class header, when adding that header to `SentryPrivate.h` to expose it +to internal SDK Swift code, as `SentrySDKInfo.h`. To solve this problem we have to use the +`SentryInternalSerializable` for internal classes implementing serializable. + +## Compatibility Notes + +- **visionOS**: Requires `SWIFT_OBJC_INTEROP_MODE=objcxx` for static framework +- **C Functions**: Cannot call C functions directly from Swift with visionOS settings + +## Converting to Swift + +Converting internal ObjC classes to Swift needs to be done following a partial order. The scripts in `SwiftConversion` generate this ordering and can be used to guide ObjC to Swift conversions. diff --git a/develop-docs/Swift-Usage.md b/develop-docs/Swift-Usage.md deleted file mode 100644 index 2dbcb4a99e1..00000000000 --- a/develop-docs/Swift-Usage.md +++ /dev/null @@ -1,23 +0,0 @@ -# Swift Usage - -Starting from version 8.0.0, it is now possible to include Swift code in the project. All Swift files should be placed under the `/Sources/Swift` directory. - -> In this document, `SentryPrivate` refers to the library written in Swift, while `Sentry` represents the framework written in Objective-C. The term `SentryPrivate` public API refers to the API that will be consumed by `Sentry` and is not intended for direct use by users. - -When working with Swift, it's important to keep the following restrictions in mind: - -1. All Swift code will be bundled within the `SentryPrivate` library, which `Sentry` depends on. -2. User-facing APIs cannot be written in Swift because their components will be accessed through imports from "SentryPrivate." -3. `SentryPrivate` does not have access to `Sentry` classes to avoid cyclic references. As a result, any code written in Objective-C is not accessible from the Swift layer. - - However, it is possible to create Dependency Injection (DI) APIs in Swift, allowing `Sentry` to inject its objects for use within `SentryPrivate`. -4. `SentryPrivate` public APIs (code consumed by `Sentry`) cannot utilize certain Objective-C incompatible features, including: - - Generics - - Non-@objc protocols and protocol extensions - - Top-level functions and properties - - Global variables - - Structs - - Swift-only enums - - Swift-only optionals - - Swift-only tuples - -By keeping these considerations in mind, you can effectively work with Swift code within the project, ensuring compatibility with the `Sentry` framework and adhering to the necessary restrictions imposed by the language differences. diff --git a/develop-docs/TEST.md b/develop-docs/TEST.md new file mode 100644 index 00000000000..f957f114074 --- /dev/null +++ b/develop-docs/TEST.md @@ -0,0 +1,144 @@ +# Testing + +## Sample Apps + +See //Samples/README.md for more information about how to use the sample apps to test SDK functionality. + +## Generating classes + +You can use the `generate-classes.sh` to generate ViewControllers and other classes to emulate a large project. This is useful, for example, to test the performance of swizzling in a large project without having to check in thousands of lines of code. + +## Tests + +The tests depend on our test server. To run the automated tests, you first need to have the server running locally with + +```sh +make run-test-server +``` + +Test guidelines: + +- We default to writing tests in Swift. When touching a test file written in Objective-C consider converting it to Swift and then add your tests. +- Make use of the fixture pattern for test setup code. For examples, checkout [SentryClientTest](/Tests/SentryTests/SentryClientTest.swift) or [SentryHttpTransportTests](/Tests/SentryTests/SentryHttpTransportTests.swift). +- Use [TestData](/Tests/SentryTests/Protocol/TestData.swift) when possible to avoid setting up data classes with test values. +- Name the variable of the class you are testing `sut`, which stands for [system under test](https://en.wikipedia.org/wiki/System_under_test). +- When calling `SentrySDK.start` in a test, specify only the minimum integrations required to minimize side effects for tests and reduce flakiness. + +Test can either be ran inside from Xcode or via + +```sh +make test +``` + +### Unit Tests with Thread Sanitizer + +CI runs the unit tests for one job with thread sanitizer enabled to detect race conditions. +To ignore false positives or known issues, use the `SENTRY_DISABLE_THREAD_SANITIZER` macro or the [suppression file](../Sources/Resources/ThreadSanitizer.sup). +It's worth noting that you can use the `$(PROJECT_DIR)` to specify the path to the suppression file. +To run the unit tests with the thread sanitizer enabled in Xcode click on edit scheme, go to tests, then open diagnostics, and enable Thread Sanitizer. +The profiler doesn't work with TSAN attached, so tests that run the profiler will be skipped. + +#### Further Reading + +- [ThreadSanitizerSuppressions](https://github.com/google/sanitizers/wiki/ThreadSanitizerSuppressions) +- [Running Tests with Clang's AddressSanitizer](https://pspdfkit.com/blog/2016/test-with-asan/) +- [Diagnosing Memory, Thread, and Crash Issues Early](https://developer.apple.com/documentation/xcode/diagnosing-memory-thread-and-crash-issues-early) +- [Stackoverflow: ThreadSanitizer suppression file with Xcode](https://stackoverflow.com/questions/38251409/how-can-i-suppress-thread-sanitizer-warnings-in-xcode-from-an-external-library) + +### Using Xcode Test Plans + +Test plans in Xcode provide a convenient way to organize and configure test execution. +They allow us to segment tests into different groups and configure specific test environments without creating additional targets or schemes. +Furthermore, test plans provide additional features such as built-in test repetition and retry on failures, automatic screen capture for debugging UI test failures, and custom test configurations for different scenarios. + +Each Xcode scheme can have multiple test plans configured, but only one test plan can be marked as the default test plan. +When adding new test plans, they must also be added to the relevant schemes. + +Some of the features of test plans are: + +- Built-in test repetition and retry on failures +- Automatic screen capture for debugging UI test failures +- Custom test configurations for different scenarios + +Additional outputs are written to the Xcode results (`.xcresult`) files, which can be found in the `~/Library/Developer/Xcode/DerivedData/.../Logs/Test/` directory. + +#### Base Test Plans + +We maintain "base" test plans that automatically include all new tests as they are configured by defining a list skipped tests. +This prevents tests from being accidentally excluded and provides convenience when adding new test files. + +In case a test is manually marked as skipped in the test plan, it should be added to another test plan (which must also be used in the CI workflow). +When using `xcodebuild` to run tests, only the default test plan is executed unless explicitly specified with the -testPlan argument. + +#### Test Plan Organization + +Test plans are stored in the repository root since they are shared between sample apps and SDK targets. +This central location makes them easily accessible while maintaining the relationship between plans and schemes. + +#### UI Test Recording + +It is possible to record UI tests by changing the test plan configuration `Automatic Screen Capture` to `On, and keep all` or `On, and delete if test succeeds`. + +After running the tests with the configuration set, it is possible to open the test results in Xcode, inspect the tests in detail by double clicking them. + +![UI Test Capture Settings](./xcode_test_plan_uicapture_settings.png) + +The details of the test case will display the UI Test history and also display playback of the screen captures. + +![UI Test Capture Playback](./xcode_test_plan_uicapture_playback.png) + +#### Further Resources + +For more details on test plans and their capabilities, refer to: + +- [WWDC21 video on Test Plans](https://developer.apple.com/videos/play/wwdc2021/10296/) +- [Apple's documentation on Test Plans](https://developer.apple.com/documentation/xcode/running-tests-and-interpreting-results) + +### Test Logs + +We used to set the log level to debug all tests to investigate flaky tests. For individual tests we then disabled the logs because printing the messages via NSLog uses synchronization and caused specific tests to fail due to timeouts in CI. The debug logs can also be extremely verbose for tests using tight loops and completely spamming the test logs. + +Therefore, the default log level is error for tests. If debug logs can help with fixing flaky tests, we should enable these for specific test cases only with `SentrySDKLog.withDebugLogs`. + +### UI Tests + +CI runs UI tests on simulators via the `ui-tests.yml` workflow for every PR and every commit on main. + +#### Saucelabs + +You can find the available devices on [their website](https://saucelabs.com/platform/supported-browsers-devices). Another way to check their available devices is to go to [live app testing](https://app.saucelabs.com/live/app-testing), go to iOS-Swift and click on choose device. This brings the full list of devices with more details. + +### Test Expectations + +We recommend using `XCTAssertEqual(, )` over `XCTAssertEqual(, )` for no strong reason, but to align so tests are consistent and therefore easier to read. + +## Performance benchmarking + +Once daily and for every PR via [Github action](../.github/workflows/benchmarking.yml), the benchmark runs in Sauce Labs, on a [high-end device](https://github.com/getsentry/sentry/blob/8986f81e19f63ee370b1649e08630c9b946c87ed/src/sentry/profiles/device.py#L43-L49) we categorize. Benchmarks run from an XCUITest (`iOS-Benchmarking` target) using the iOS-Swift sample app, under the `iOS-Benchmarking` scheme. [`PerformanceViewController`](../Samples/iOS-Swift/ViewControllers/PerformanceViewController.swift) provides a start and stop button for controlling when the benchmarking runs, and a text field to marshal observations from within the test harness app into the test runner app. There, we assert that the P90 of all trials remains under 5%. We also print the raw results to the test runner's console logs for postprocessing into reports with `//scripts/process-benchmark-raw-results.py`. + +### Test procedure + +- Tap the button to start a Sentry transaction with the associated profiling. +- Run a loop performing large amount of calculations to use as much CPU as possible. This simulates something an app developer would want to profile in a real world scenario. +- While benchmarking, run a sampling profiler at 10 Hz to calculate the CPU usage of each thread, in particular the Sentry profiler's, to calculate its relative usage. +- Tap the button to stop the transaction after waiting for 15 seconds. +- Calculate the total time used by app threads and separately, the profiler's thread. Keep separated by system call and user call times. +- Write these four values as CSV into the text field accessible as an XCUIElement in the runner app. + +### Test Plan + +- Run the procedure 20 times, then assert that the 90th percentile remains under 5% so we can be alerted via CI if it spikes. + - Sauce Labs allows relaxing the timeout for a suite of tests and for a `XCTestCase` subclass' collection of test case methods, but each test case in the suite must run in less than 15 minutes. 20 trials takes too long, so we split it up into multiple test cases, each running a subset of the trials. + - This is done by dynamically generating test case methods in `SentrySDKPerformanceBenchmarkTests`, which is necessarily written in Objective-C since this is not possible to do in Swift tests. By doing this dynamically, we can easily fine tune how we split up the work to account for changes in the test duration or in constraints on how things run in Sauce Labs etc. + +### Flaky tests + +If you see a test being flaky, you should ideally fix it immediately. If that's not feasible, you can disable the test in the test scheme by unchecking it in the associated test plan: + +![Disabling test cases via the Xcode Tests navigator](./develop-docs/disabling_tests_xcode_test_plan.png) + +Then create a GH issue with the [flaky test issue template](https://github.com/getsentry/sentry-cocoa/issues/new?assignees=&labels=Platform%3A+Cocoa%2CType%3A+Flaky+Test&template=flaky-test.yml). + +Disabling the test in the test plan has the advantage that the test report will state "X tests passed, Y tests failed, Z tests skipped", as well as maintaining a centralized list of skipped tests (look in the associated .xctestplan file source in //Plans/) and they will be grayed out when viewing in the Xcode Tests Navigator (⌘6): + +![How Xcode displays skipped tests in the Tests Navigator](./develop-docs/xcode_tests_navigator_with_skipped_test.png) diff --git a/dprint.json b/dprint.json index e497e05352a..c1c65b8d497 100644 --- a/dprint.json +++ b/dprint.json @@ -11,7 +11,7 @@ "excludes": [ ".github/labeler.yml", "Tests/Resources/**/*garbage*.json", - "sdk_api.json" + "sdk_api*.json" ], "plugins": [ "https://plugins.dprint.dev/json-0.20.0.wasm", diff --git a/fastlane/Appfile b/fastlane/Appfile index ea26976c6a9..6c00748a546 100644 --- a/fastlane/Appfile +++ b/fastlane/Appfile @@ -5,4 +5,3 @@ team_id("97JCY7859U") # Developer Portal Team ID # For more information about the Appfile, see: # https://docs.fastlane.tools/advanced/#appfile - diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 8d33070ee5a..b815a915e28 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -7,6 +7,7 @@ platform :ios do ios_swift_infoplist_path = "./Samples/iOS-Swift/iOS-Swift/Info.plist" ios_swift_clip_infoplist_path = "./Samples/iOS-Swift/iOS-SwiftClip/Info.plist" + ios_swift_share_extension_infoplist_path = "./Samples/iOS-Swift/iOS-Swift-ShareExtension/Info.plist" # Helper method to run tests with common configuration def run_ui_tests(scheme:, result_bundle_name:, device: nil, address_sanitizer: false) @@ -27,9 +28,9 @@ platform :ios do end lane :prepare_xcframework_signing do - setup_ci + setup_ci if is_ci - match( + sync_code_signing( type: "appstore", readonly: true, app_identifier: ["io.sentry.sample.iOS-Swift"], # Any app identifier will do @@ -66,6 +67,11 @@ platform :ios do key: "CFBundleShortVersionString", value: new_version ) + set_info_plist_value( + path: ios_swift_share_extension_infoplist_path, + key: "CFBundleShortVersionString", + value: new_version + ) sentryInfoPlistPath = "./Sources/Resources/Info.plist" set_info_plist_value( @@ -81,39 +87,48 @@ platform :ios do end desc "Run match for local development" - lane :match_local do - match( - type: "development", - app_identifier: ["io.sentry.sample.iOS-Swift", - "io.sentry.sample.iOS-Swift.Clip", - "io.sentry.iOS-Swift-UITests.xctrunner", - "io.sentry.cocoa.perf-test-app-plain", - "io.sentry.*", - "io.sentry.iOS-Benchmarking.xctrunner", - "io.sentry.cocoa.perf-test-app-sentry"], - readonly: true - ) - match( - type: "appstore", - app_identifier: ["io.sentry.sample.iOS-Swift", - "io.sentry.sample.iOS-Swift.Clip", - "io.sentry.iOS-Swift-UITests.xctrunner", - "io.sentry.cocoa.perf-test-app-plain", - "io.sentry.*", - "io.sentry.iOS-Benchmarking.xctrunner", - "io.sentry.cocoa.perf-test-app-sentry"], - readonly: true - ) + lane :match_local do + sync_code_signing( + type: "development", + app_identifier: [ + "io.sentry.*", + "io.sentry.cocoa.perf-test-app-plain", + "io.sentry.cocoa.perf-test-app-sentry", + "io.sentry.iOS-Benchmarking.xctrunner", + "io.sentry.iOS-Swift-UITests.xctrunner", + "io.sentry.sample.iOS-Swift", + "io.sentry.sample.iOS-Swift.Clip", + "io.sentry.sample.iOS-Swift.ShareExtension" + ], + readonly: true + ) + sync_code_signing( + type: "appstore", + app_identifier: [ + "io.sentry.*", + "io.sentry.cocoa.perf-test-app-plain", + "io.sentry.cocoa.perf-test-app-sentry", + "io.sentry.iOS-Benchmarking.xctrunner", + "io.sentry.iOS-Swift-UITests.xctrunner", + "io.sentry.sample.iOS-Swift", + "io.sentry.sample.iOS-Swift.Clip", + "io.sentry.sample.iOS-Swift.ShareExtension" + ], + readonly: true + ) end desc "Build iOS-Swift with Release" lane :build_ios_swift do - - setup_ci + setup_ci if is_ci sync_code_signing( type: "appstore", - app_identifier: ["io.sentry.sample.iOS-Swift", "io.sentry.sample.iOS-Swift.Clip"], + app_identifier: [ + "io.sentry.sample.iOS-Swift", + "io.sentry.sample.iOS-Swift.Clip", + "io.sentry.sample.iOS-Swift.ShareExtension" + ], ) # We must use build_ios_app because otherwise the build will succeed but it will not create the .ipa file. @@ -128,18 +143,21 @@ platform :ios do archive_path: "iOS-Swift" ) - delete_keychain(name: "fastlane_tmp_keychain") unless is_ci + delete_keychain(name: "fastlane_tmp_keychain") if is_ci end lane :build_ios_swift_for_tests do - setup_ci( force: true - ) + ) if is_ci sync_code_signing( type: "development", - app_identifier: ["io.sentry.sample.iOS-Swift", "io.sentry.sample.iOS-Swift.Clip"], + app_identifier: [ + "io.sentry.sample.iOS-Swift", + "io.sentry.sample.iOS-Swift.Clip", + "io.sentry.sample.iOS-Swift.ShareExtension" + ] ) build_app( @@ -150,35 +168,43 @@ platform :ios do skip_package_dependencies_resolution: true ) - delete_keychain(name: "fastlane_tmp_keychain") unless is_ci + delete_keychain(name: "fastlane_tmp_keychain") if is_ci end lane :build_ios_swift_ui_test do - setup_ci( force: true - ) + ) if is_ci sync_code_signing( type: "development", - app_identifier: ["io.sentry.sample.iOS-Swift", "io.sentry.sample.iOS-Swift.Clip", "io.sentry.iOS-Swift-UITests.xctrunner"], + app_identifier: [ + "io.sentry.sample.iOS-Swift", + "io.sentry.sample.iOS-Swift.Clip", + "io.sentry.sample.iOS-Swift.ShareExtension", + "io.sentry.iOS-Swift-UITests.xctrunner" + ], ) # don't use gym here because it always appends a "build" command which fails, since this is a test target not configured for running sh "set -o pipefail && NSUnbufferedIO=YES xcodebuild -workspace ../Sentry.xcworkspace -scheme iOS-Swift-UITests -derivedDataPath ../DerivedData -destination 'generic/platform=iOS' -configuration Test build-for-testing 2>&1 | xcbeautify" - delete_keychain(name: "fastlane_tmp_keychain") unless is_ci + delete_keychain(name: "fastlane_tmp_keychain") if is_ci end lane :build_ios_benchmark_test do - setup_ci( force: true - ) + ) if is_ci sync_code_signing( type: "development", - app_identifier: ["io.sentry.sample.iOS-Swift", "io.sentry.sample.iOS-Swift.Clip", "io.sentry.iOS-Benchmarking.xctrunner"], + app_identifier: [ + "io.sentry.sample.iOS-Swift", + "io.sentry.sample.iOS-Swift.Clip", + "io.sentry.sample.iOS-Swift.ShareExtension", + "io.sentry.iOS-Benchmarking.xctrunner" + ], ) build_app( @@ -190,7 +216,7 @@ platform :ios do skip_package_dependencies_resolution: true ) - delete_keychain(name: "fastlane_tmp_keychain") unless is_ci + delete_keychain(name: "fastlane_tmp_keychain") if is_ci end lane :ui_critical_tests_ios_swiftui_all do @@ -275,7 +301,7 @@ platform :ios do run_tests( project: "./Tests/DuplicatedSDKTest/DuplicatedSDKTest.xcodeproj", scheme: "DuplicatedSDKTest", - device: "iPhone 16 (18.5)", + device: "iPhone 16 Pro (18.4)", xcodebuild_formatter: "xcbeautify --report junit", result_bundle: true, result_bundle_path: "fastlane/#{result_bundle_path}" @@ -286,11 +312,13 @@ platform :ios do lane :build_perf_test_app_plain do setup_ci( force: true - ) + ) if is_ci sync_code_signing( type: "development", - app_identifier: ["io.sentry.cocoa.perf-test-app-plain"] + app_identifier: [ + "io.sentry.cocoa.perf-test-app-plain" + ] ) build_app( @@ -304,18 +332,20 @@ platform :ios do skip_package_dependencies_resolution: true ) - delete_keychain(name: "fastlane_tmp_keychain") unless is_ci + delete_keychain(name: "fastlane_tmp_keychain") if is_ci end desc "Build Perf-test app with Sentry" lane :build_perf_test_app_sentry do setup_ci( force: true - ) + ) if is_ci sync_code_signing( type: "development", - app_identifier: ["io.sentry.cocoa.perf-test-app-sentry"], + app_identifier: [ + "io.sentry.cocoa.perf-test-app-sentry" + ], ) build_app( @@ -329,7 +359,28 @@ platform :ios do skip_package_dependencies_resolution: true ) - delete_keychain(name: "fastlane_tmp_keychain") unless is_ci + delete_keychain(name: "fastlane_tmp_keychain") if is_ci end + desc "Generate all provisioning profiles for development" + lane :setup_code_signing do + sync_code_signing( + type: "development", + app_identifier: [ + "io.sentry.sample.iOS-Swift", + "io.sentry.sample.iOS-Swift.Clip", + "io.sentry.sample.iOS-Swift.ShareExtension" + ], + readonly: false + ) + sync_code_signing( + type: "appstore", + app_identifier: [ + "io.sentry.sample.iOS-Swift", + "io.sentry.sample.iOS-Swift.Clip", + "io.sentry.sample.iOS-Swift.ShareExtension" + ], + readonly: false + ) + end end diff --git a/scripts/.clang-format-version b/scripts/.clang-format-version index bf8f7ca9a29..2d978e312b5 100644 --- a/scripts/.clang-format-version +++ b/scripts/.clang-format-version @@ -1 +1 @@ -20.1.7 +21.1.1 diff --git a/scripts/.swiftlint-version b/scripts/.swiftlint-version index 8997e66597c..0b09455034e 100644 --- a/scripts/.swiftlint-version +++ b/scripts/.swiftlint-version @@ -1 +1 @@ -0.59.1 +0.61.0 diff --git a/scripts/build-xcframework-local.sh b/scripts/build-xcframework-local.sh index cf20a6d5072..0c2e77eb0bb 100755 --- a/scripts/build-xcframework-local.sh +++ b/scripts/build-xcframework-local.sh @@ -10,25 +10,43 @@ rm -rf Carthage/ mkdir Carthage if [ "$variants" = "DynamicOnly" ] || [ "$variants" = "AllVariants" ]; then - ./scripts/build-xcframework-variant.sh "Sentry" "-Dynamic" "mh_dylib" "" "$sdks" + ./scripts/build-xcframework-variant.sh "Sentry" "-Dynamic" "mh_dylib" "" "$sdks" "arm64e" + ./scripts/validate-xcframework-format.sh "Sentry-Dynamic.xcframework" ./scripts/compress-xcframework.sh "$signed" Sentry-Dynamic mv Sentry-Dynamic.xcframework.zip Carthage/Sentry-Dynamic.xcframework.zip fi +if [ "$variants" = "DynamicWithARM64eOnly" ] || [ "$variants" = "AllVariants" ]; then + ./scripts/build-xcframework-variant.sh "Sentry" "-Dynamic-WithARM64e" "mh_dylib" "" "$sdks" "" + ./scripts/validate-xcframework-format.sh "Sentry-Dynamic-WithARM64e.xcframework" + ./scripts/compress-xcframework.sh "$signed" Sentry-Dynamic-WithARM64e + mv Sentry-Dynamic-WithARM64e.xcframework.zip Carthage/Sentry-Dynamic-WithARM64e.xcframework.zip +fi + if [ "$variants" = "StaticOnly" ] || [ "$variants" = "AllVariants" ]; then - ./scripts/build-xcframework-variant.sh "Sentry" "" "staticlib" "" "$sdks" + ./scripts/build-xcframework-variant.sh "Sentry" "" "staticlib" "" "$sdks" "" + ./scripts/validate-xcframework-format.sh "Sentry.xcframework" ./scripts/compress-xcframework.sh "$signed" Sentry mv Sentry.xcframework.zip Carthage/Sentry.xcframework.zip fi if [ "$variants" = "SwiftUIOnly" ] || [ "$variants" = "AllVariants" ]; then - ./scripts/build-xcframework-variant.sh "SentrySwiftUI" "" "mh_dylib" "" "$sdks" + ./scripts/build-xcframework-variant.sh "SentrySwiftUI" "" "mh_dylib" "" "$sdks" "" + ./scripts/validate-xcframework-format.sh "SentrySwiftUI.xcframework" ./scripts/compress-xcframework.sh "$signed" SentrySwiftUI mv SentrySwiftUI.xcframework.zip Carthage/SentrySwiftUI.xcframework.zip fi if [ "$variants" = "WithoutUIKitOnly" ] || [ "$variants" = "AllVariants" ]; then - ./scripts/build-xcframework-variant.sh "Sentry" "-WithoutUIKitOrAppKit" "mh_dylib" "WithoutUIKit" "$sdks" + ./scripts/build-xcframework-variant.sh "Sentry" "-WithoutUIKitOrAppKit" "mh_dylib" "WithoutUIKit" "$sdks" "arm64e" + ./scripts/validate-xcframework-format.sh "Sentry-WithoutUIKitOrAppKit.xcframework" ./scripts/compress-xcframework.sh "$signed" Sentry-WithoutUIKitOrAppKit mv Sentry-WithoutUIKitOrAppKit.xcframework.zip Carthage/Sentry-WithoutUIKitOrAppKit.xcframework.zip fi + +if [ "$variants" = "WithoutUIKitWithARM64eOnly" ] || [ "$variants" = "AllVariants" ]; then + ./scripts/build-xcframework-variant.sh "Sentry" "-WithoutUIKitOrAppKit-WithARM64e" "mh_dylib" "WithoutUIKit" "$sdks" "" + ./scripts/validate-xcframework-format.sh "Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework" + ./scripts/compress-xcframework.sh "$signed" Sentry-WithoutUIKitOrAppKit-WithARM64e + mv Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework.zip Carthage/Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework.zip +fi diff --git a/scripts/build-xcframework-variant.sh b/scripts/build-xcframework-variant.sh index 8627a551f16..561bfb30b44 100755 --- a/scripts/build-xcframework-variant.sh +++ b/scripts/build-xcframework-variant.sh @@ -7,6 +7,7 @@ suffix="${2:-}" MACH_O_TYPE="${3-mh_dylib}" configuration_suffix="${4-}" sdks_to_build="${5:-}" +excluded_archs="${6:-}" if [ "$sdks_to_build" = "iOSOnly" ]; then sdks=( iphoneos iphonesimulator ) @@ -18,9 +19,13 @@ else sdks=( iphoneos iphonesimulator macosx maccatalyst appletvos appletvsimulator watchos watchsimulator xros xrsimulator ) fi - for sdk in "${sdks[@]}"; do - ./scripts/build-xcframework-slice.sh "$sdk" "$scheme" "$suffix" "$MACH_O_TYPE" "$configuration_suffix" - done +for sdk in "${sdks[@]}"; do + ./scripts/build-xcframework-slice.sh "$sdk" "$scheme" "$suffix" "$MACH_O_TYPE" "$configuration_suffix" +done + +if [ -n "$excluded_archs" ]; then + ./scripts/remove-architectures.sh "$(pwd)/Carthage/archive/$scheme$suffix/" "$excluded_archs" +fi xcframework_sdks="$(IFS=,; echo "${sdks[*]}")" ./scripts/assemble-xcframework.sh "$scheme" "$suffix" "$configuration_suffix" "$xcframework_sdks" "$(pwd)/Carthage/archive/$scheme$suffix/SDK_NAME.xcarchive" diff --git a/scripts/check-uikit-linkage.sh b/scripts/check-uikit-linkage.sh index e0170c91e29..36e190bc52e 100755 --- a/scripts/check-uikit-linkage.sh +++ b/scripts/check-uikit-linkage.sh @@ -4,34 +4,71 @@ set -eou pipefail +# Disable SC1091 because it won't work with pre-commit +# shellcheck source=./scripts/ci-utils.sh disable=SC1091 +source "$(cd "$(dirname "$0")" && pwd)/ci-utils.sh" + CONFIGURATION="${1}" DERIVED_DATA_PATH="${2}" LINKAGE_TEST="${3}" MODULE_NAME="${4}" +log_notice "Checking UIKit linkage for:" +log_notice " - Configuration: $CONFIGURATION" +log_notice " - Derived Data Path: $DERIVED_DATA_PATH" +log_notice " - Linkage Test: $LINKAGE_TEST" +log_notice " - Module Name: $MODULE_NAME" + +# Define the path to the Sentry build product. SENTRY_BUILD_PRODUCT_PATH="$DERIVED_DATA_PATH/Build/Products/$CONFIGURATION-iphonesimulator/$MODULE_NAME.framework/$MODULE_NAME" +log_notice "Checking build product path: $SENTRY_BUILD_PRODUCT_PATH" + +if [ ! -f "$SENTRY_BUILD_PRODUCT_PATH" ]; then + log_error "Sentry build product not found at path: $SENTRY_BUILD_PRODUCT_PATH" + exit 1 +fi + +# For some frameworks, the binary in the framework root is a symlink to the binary in the Versions directory. +# We need to check resolve the symlink and check the binary in the Versions directory. +if [ -L "$SENTRY_BUILD_PRODUCT_PATH" ]; then + log_notice "Sentry build product is a symlink, resolving it." + SENTRY_BUILD_PRODUCT_PATH=$(readlink -f "$SENTRY_BUILD_PRODUCT_PATH") + if [ ! -f "$SENTRY_BUILD_PRODUCT_PATH" ]; then + log_error "Sentry build product not found at path: $SENTRY_BUILD_PRODUCT_PATH" + exit 1 + fi + log_notice "Resolved Sentry build product path: $SENTRY_BUILD_PRODUCT_PATH" +fi -stat "$SENTRY_BUILD_PRODUCT_PATH" +# Check if the binary is linked to UIKit. +log_notice "Checking if Sentry build product is linked to UIKit." +OTOOL_OUTPUT=$(otool -L "$SENTRY_BUILD_PRODUCT_PATH") +begin_group "OTool output" +echo "$OTOOL_OUTPUT" +end_group -MATCHES=$(otool -L "$SENTRY_BUILD_PRODUCT_PATH" | grep -c -e "UIKit.framework/UIKit" -e "libswiftUIKit.dylib" ||:) +MATCHES=$(echo "$OTOOL_OUTPUT" | grep -c -e "UIKit.framework/UIKit" -e "libswiftUIKit.dylib" ||:) +log_notice "Matches: $MATCHES" +# Check the linkage. case "$LINKAGE_TEST" in "linked") if [ "$MATCHES" == 0 ]; then - echo "UIKit.framework linkage not found." + log_error "UIKit.framework linkage not found, but expected linkage." exit 1 fi - echo "Success! UIKit.framework linked." + log_notice "Success! UIKit.framework linked." ;; "unlinked") + log_notice "Checking if Sentry build product is not linked to UIKit." if [ "$MATCHES" != 0 ]; then - echo "UIKit.framework linkage found." + log_error "UIKit.framework linkage found, but expected no linkage." exit 1 fi - echo "Success! UIKit.framework not linked." + log_notice "Success! UIKit.framework not linked." ;; *) - echo "Provide an argument for either 'linked' or 'unlinked' UIKit check." + log_error "Provide an argument for either 'linked' or 'unlinked' UIKit check." exit 1 ;; esac diff --git a/scripts/ci-boot-simulator.sh b/scripts/ci-boot-simulator.sh index d06763dcc09..fe3a51d347c 100755 --- a/scripts/ci-boot-simulator.sh +++ b/scripts/ci-boot-simulator.sh @@ -11,6 +11,10 @@ set -euo pipefail +# Disable SC1091 because it won't work with pre-commit +# shellcheck source=./scripts/ci-utils.sh disable=SC1091 +source "$(cd "$(dirname "$0")" && pwd)/ci-utils.sh" + # Parse named arguments XCODE_VERSION="16.2" # Default value @@ -21,37 +25,110 @@ while [[ $# -gt 0 ]]; do shift 2 ;; *) - echo "Unknown argument: $1" - echo "Usage: $0 [-x|--xcode ]" + log_error "Unknown argument: $1" + log_error "Usage: $0 [-x|--xcode ]" exit 1 ;; esac done -SIMULATOR="iPhone 16" +log_notice "Starting simulator boot process with Xcode version: $XCODE_VERSION" + +begin_group "Simulator Selection" +SIMULATOR="iPhone 16 Pro" +IOS_VERSION="18.4" # Select simulator based on Xcode version case "$XCODE_VERSION" in "14.3.1") - SIMULATOR="iPhone 14" + SIMULATOR="iPhone 14 Pro" + IOS_VERSION="16.4" + log_notice "Selected: $SIMULATOR with iOS $IOS_VERSION for Xcode $XCODE_VERSION" ;; "15.4") - SIMULATOR="iPhone 15" + SIMULATOR="iPhone 15 Pro" + IOS_VERSION="17.5" + log_notice "Selected: $SIMULATOR with iOS $IOS_VERSION for Xcode $XCODE_VERSION" ;; "16.2") - SIMULATOR="iPhone 16" + SIMULATOR="iPhone 16 Pro" + IOS_VERSION="18.4" + log_notice "Selected: $SIMULATOR with iOS $IOS_VERSION for Xcode $XCODE_VERSION" ;; *) - SIMULATOR="iPhone 16" # Default fallback + SIMULATOR="iPhone 16 Pro" # Default fallback + IOS_VERSION="18.4" + log_warning "Unknown Xcode version '$XCODE_VERSION', using default: $SIMULATOR with iOS $IOS_VERSION" ;; esac +end_group + +begin_group "Available Devices" +log_notice "Listing all available simulators:" +xcrun simctl list devices available +end_group + +begin_group "Device Discovery" +log_notice "Searching for simulator: $SIMULATOR running iOS $IOS_VERSION" + +UDID=$(xcrun simctl list devices available | \ +grep -A 5 "^-- iOS $IOS_VERSION --" | \ +grep "$SIMULATOR (" | \ +sed -n 's/.*(\([0-9A-F-]\{36\}\)).*/\1/p' | \ +head -n1) -echo "Booting simulator $SIMULATOR" -xcrun simctl boot "$SIMULATOR" +if [ -z "$UDID" ]; then + log_error "Failed to find UDID for simulator: $SIMULATOR with iOS $IOS_VERSION" + log_error "Available devices:" + xcrun simctl list devices available + exit 1 +fi -# Wait for the simulator to boot +log_notice "Found simulator UDID: $UDID" +end_group + +begin_group "Simulator Boot" +log_notice "Booting simulator: $SIMULATOR - iOS $IOS_VERSION (UDID: $UDID)" + +if ! xcrun simctl boot "$UDID" 2>/dev/null; then + # If boot fails, it might be because the simulator is already booted + CURRENT_STATE=$(xcrun simctl list devices | grep "$UDID" | sed 's/.*(\([^)]*\)).*$/\1/') + if [ "$CURRENT_STATE" = "Booted" ]; then + log_notice "Simulator is already booted" + else + log_error "Failed to boot simulator. Current state: $CURRENT_STATE" + exit 1 + fi +else + log_notice "Simulator boot command executed successfully" +fi + +log_notice "Opening Simulator app UI" +# We use `open -a Simulator` because there's no lower-level CLI like `simctl` to display the simulator UI available. +if ! open -a Simulator; then + log_error "Failed to open Simulator app" + exit 1 +fi +log_notice "Simulator app opened successfully" +end_group + +begin_group "Boot Status Verification" +log_notice "Waiting for simulator to fully boot (this may take a moment)" # We need to wait for the simulator to boot to avoid the test to fail due to timeout (because the simulator is not booted yet) -xcrun simctl bootstatus "$SIMULATOR" +if ! xcrun simctl bootstatus "$UDID"; then + log_error "Failed to verify simulator boot status" + exit 1 +fi +log_notice "Simulator boot process completed successfully" +end_group + +begin_group "Booted Device Details" +log_notice "Listing all currently booted simulators:" +if ! xcrun simctl list devices --json | jq '.devices | to_entries[] | select(.value[] | .state == "Booted")'; then + log_warning "Failed to retrieve booted device details (jq might not be available)" + log_notice "Fallback: listing devices without JSON formatting" + xcrun simctl list devices | grep "Booted" +fi +end_group -# Print details about the booted simulator, iOS version, etc. -xcrun simctl list devices --json | jq '.devices | to_entries[] | select(.value[] | .state == "Booted")' +log_notice "Simulator boot process completed successfully!" diff --git a/scripts/ci-create-simulator.sh b/scripts/ci-create-simulator.sh new file mode 100755 index 00000000000..7c221b996ba --- /dev/null +++ b/scripts/ci-create-simulator.sh @@ -0,0 +1,120 @@ +#!/bin/bash +set -euo pipefail + +# Creating simulators takes some time and also cause flakiness. Please use the preinstalled simulators if possible. + +# Source CI utility functions for logging and grouping +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Disable SC1091 because it won't work with pre-commit +# shellcheck source=./scripts/ci-utils.sh disable=SC1091 +source "${SCRIPT_DIR}/ci-utils.sh" + +# Usage: ./scripts/ci-create-simulator.sh --platform --os-version --device-name +# Example: ./scripts/ci-create-simulator.sh --platform iOS --os-version 26.0 --device-name "iPhone 16e" + +PLATFORM="" +OS_VERSION="" +DEVICE_NAME="" + +usage() { + log_error "Usage: $0 --platform --os-version --device-name " + log_error " Example: $0 --platform iOS --os-version 26.0 --device-name \"iPhone 16e\"" + exit 1 +} + +begin_group "Parsing arguments for simulator creation" +while [[ $# -gt 0 ]]; do + case $1 in + --platform) + PLATFORM="$2" + shift 2 + ;; + --os-version) + OS_VERSION="$2" + shift 2 + ;; + --device-name) + DEVICE_NAME="$2" + shift 2 + ;; + *) + log_error "Unknown argument: $1" + usage + ;; + esac +done +end_group + +if [[ -z "$PLATFORM" || -z "$OS_VERSION" || -z "$DEVICE_NAME" ]]; then + usage +fi + +log_notice "Requested simulator: Platform='$PLATFORM', OS Version='$OS_VERSION', Device Name='$DEVICE_NAME'" + +# Map platform to simctl device type and runtime +case "$PLATFORM" in + iOS) + SIMCTL_PLATFORM="iOS" + ;; + tvOS) + SIMCTL_PLATFORM="tvOS" + ;; + visionOS) + SIMCTL_PLATFORM="visionOS" + ;; + *) + log_notice "Platform '$PLATFORM' does not require simulator creation or is not supported. Skipping." + exit 0 + ;; +esac + +begin_group "Finding runtime for ${SIMCTL_PLATFORM} ${OS_VERSION}" +RUNTIME_ID=$(xcrun simctl list runtimes | grep "${SIMCTL_PLATFORM} ${OS_VERSION}" | grep -v unavailable | awk '{print $NF}' | head -n1) +if [[ -z "$RUNTIME_ID" ]]; then + log_error "Could not find runtime for ${SIMCTL_PLATFORM} ${OS_VERSION}" + xcrun simctl list runtimes + end_group + exit 1 +fi +log_notice "Found runtime ID: $RUNTIME_ID" +end_group + +begin_group "Checking if simulator already exists" +# Use a simpler approach to check for existing simulator +DEVICES_OUTPUT=$(xcrun simctl list devices available 2>/dev/null || true) +EXISTING_UDID=$(echo "$DEVICES_OUTPUT" | grep -A 20 -- "-- ${SIMCTL_PLATFORM} ${OS_VERSION} --" | grep "${DEVICE_NAME} (" | awk -F '[()]' '{print $2}' | head -n1 || true) +if [[ -n "$EXISTING_UDID" ]]; then + log_notice "Simulator '${DEVICE_NAME}' for runtime '${SIMCTL_PLATFORM} ${OS_VERSION}' already exists (UDID: $EXISTING_UDID)" + end_group + exit 0 +fi +log_notice "No existing simulator found for '${DEVICE_NAME}' (${SIMCTL_PLATFORM} ${OS_VERSION})" +end_group + +begin_group "Creating simulator" +log_notice "Attempting to create simulator: Name='${DEVICE_NAME}', Platform='${SIMCTL_PLATFORM}', OS='${OS_VERSION}'" +NEW_UDID=$(xcrun simctl create "${DEVICE_NAME}" "com.apple.CoreSimulator.SimDeviceType.${DEVICE_NAME// /-}" "$RUNTIME_ID" 2>/dev/null || true) + +# If the above fails, try to find the device type identifier +if [[ -z "$NEW_UDID" ]]; then + log_warning "Default device type identifier failed, searching for device type ID for '${DEVICE_NAME}'" + DEVICE_TYPE_ID=$(xcrun simctl list devicetypes | grep -i "${DEVICE_NAME}" | awk -F '[()]' '{print $2}' | head -n1) + if [[ -z "$DEVICE_TYPE_ID" ]]; then + log_error "Could not find device type for '${DEVICE_NAME}'" + xcrun simctl list devicetypes + end_group + exit 1 + fi + log_notice "Found device type ID: $DEVICE_TYPE_ID" + NEW_UDID=$(xcrun simctl create "${DEVICE_NAME}" "$DEVICE_TYPE_ID" "$RUNTIME_ID") +fi + +if [[ -z "$NEW_UDID" ]]; then + log_error "Failed to create simulator for '${DEVICE_NAME}' (${SIMCTL_PLATFORM} ${OS_VERSION})" + end_group + exit 1 +fi + +log_notice "Created simulator '${DEVICE_NAME}' (${SIMCTL_PLATFORM} ${OS_VERSION}) with UDID: $NEW_UDID" +end_group diff --git a/scripts/ci-diagnostics.sh b/scripts/ci-diagnostics.sh new file mode 100755 index 00000000000..1029d0572a0 --- /dev/null +++ b/scripts/ci-diagnostics.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Disable SC1091 because it won't work with pre-commit +# shellcheck source=./scripts/ci-utils.sh disable=SC1091 +source "$(cd "$(dirname "$0")" && pwd)/ci-utils.sh" + +log_notice "Starting Xcode/macOS environment diagnostics" + +begin_group "System information" +echo "Date (UTC): $(date -u)" +echo "uname: $(uname -a)" +if command -v sw_vers >/dev/null 2>&1; then + sw_vers +fi +end_group + +begin_group "Developer directory" +echo "DEVELOPER_DIR=${DEVELOPER_DIR:-}" +if command -v xcode-select >/dev/null 2>&1; then + xcode-select -p +fi +end_group + +begin_group "Installed Xcode applications" +if compgen -G "/Applications/Xcode*" > /dev/null; then + for app in /Applications/Xcode*; do + basename "$app" + done +else + log_warning "No Xcode apps found in /Applications" +fi +end_group + +begin_group "Active Xcode" +if command -v xcodebuild >/dev/null 2>&1; then + xcodebuild -version || true +else + log_warning "xcodebuild not found in PATH" +fi +end_group + +begin_group "Installed SDKs (xcodebuild -showsdks)" +if command -v xcodebuild >/dev/null 2>&1; then + xcodebuild -showsdks || true +fi +end_group + +begin_group "SDK details (xcodebuild -version -sdk)" +if command -v xcodebuild >/dev/null 2>&1; then + xcodebuild -version -sdk || true +fi +end_group + +begin_group "Available simulator runtimes" +if command -v xcrun >/dev/null 2>&1; then + xcrun simctl list runtimes || true +fi +end_group + +begin_group "Available simulator device types" +if command -v xcrun >/dev/null 2>&1; then + xcrun simctl list devicetypes || true +fi +end_group + +begin_group "Available simulator devices" +if command -v xcrun >/dev/null 2>&1; then + xcrun simctl list devices available || true +fi +end_group + +begin_group "Available destinations (best effort)" +if [ -d "Sentry.xcworkspace" ] && command -v xcodebuild >/dev/null 2>&1; then + # Do not fail if scheme isn't configured; this is best-effort + xcodebuild -workspace Sentry.xcworkspace -scheme Sentry -showdestinations 2>/dev/null || true +else + log_warning "Skipping: workspace or xcodebuild not available" +fi +end_group + +begin_group "Hardware summary" +if command -v system_profiler >/dev/null 2>&1; then + system_profiler SPHardwareDataType | sed -e 's/^[[:space:]]*//' || true +fi +end_group + +begin_group "Disk space" +df -h || true +end_group + +log_notice "Completed Xcode/macOS environment diagnostics" diff --git a/scripts/ci-enable-permissions.sh b/scripts/ci-enable-permissions.sh new file mode 100755 index 00000000000..b93bdd45872 --- /dev/null +++ b/scripts/ci-enable-permissions.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +set -e pipefail + +if csrutil status | grep -q 'disabled'; then + epochdate=$(($(date +'%s * 1000 + %-N / 1000000'))) + macos_major_version=$(sw_vers -productVersion | awk -F. '{ print $1 }') + if [[ $macos_major_version -le 10 ]]; then + tcc_update="replace into access (service,client,client_type,allowed,prompt_count,indirect_object_identifier,flags,last_modified) values (\"kTCCServiceScreenCapture\",\"/bin/bash\",0,1,1,\"UNUSED\",0,$epochdate);" + else + tcc_update="replace into access (service,client,client_type,auth_value,auth_reason,auth_version,indirect_object_identifier,flags,last_modified) values (\"kTCCServiceScreenCapture\",\"/bin/bash\",0,2,1,1,\"UNUSED\",0,$epochdate);" + fi + sudo sqlite3 "/Library/Application Support/com.apple.TCC/TCC.db" "$tcc_update" + sudo sqlite3 "/Users/$USER/Library/Application Support/com.apple.TCC/TCC.db" "$tcc_update" +else + echo "Unable to add permissions! System Integrity Protection is enabled on this image" + exit 1 +fi + +defaults write ~/Library/Group\ Containers/group.com.apple.replayd/ScreenCaptureApprovals.plist "/bin/bash" -date "3024-09-23 12:00:00 +0000" diff --git a/scripts/ci-install-xOS-26-platforms.sh b/scripts/ci-install-xOS-26-platforms.sh new file mode 100755 index 00000000000..641c6201505 --- /dev/null +++ b/scripts/ci-install-xOS-26-platforms.sh @@ -0,0 +1,88 @@ +#!/bin/bash + +# This script installs required platform simulators for Xcode 26 + +# GH actions doesn't include the beta simulators because according to them they cause too many problems: https://github.com/actions/runner-images/issues/12904#issuecomment-3242706088 +# Therefore we have manually downloaded them and now install them here as suggested in the comment. +# Once GH actions includes the beta simulators, we can should remove this script. + +set -euo pipefail + +# Disable SC1091 because it won't work with pre-commit +# shellcheck source=./scripts/ci-utils.sh disable=SC1091 +source "$(cd "$(dirname "$0")" && pwd)/ci-utils.sh" + +log_notice "Installing required platform simulators for Xcode 26" + +# Parse named arguments +PLATFORMS="" + +usage() { + echo "Usage: $0 --platforms " + echo " Available platforms: iOS,tvOS,visionOS,watchOS" + echo " Example: $0 --platforms iOS,tvOS,visionOS,watchOS" + exit 1 +} + +while [[ $# -gt 0 ]]; do + case $1 in + --platforms) + PLATFORMS="$2" + shift 2 + ;; + *) + echo "Unknown argument: $1" + usage + ;; + esac +done + +if [ -z "$PLATFORMS" ]; then + echo "Error: --platforms argument is required" + usage +fi + +# Split platforms by comma +IFS=',' read -ra PLATFORM_ARRAY <<< "$PLATFORMS" + +for platform in "${PLATFORM_ARRAY[@]}"; do + case "$platform" in + "iOS") + begin_group "Installing iOS 26.0 simulator" + xcodebuild -downloadPlatform iOS -quiet || { + log_warning "Failed to download iOS platform, continuing..." + } + end_group + ;; + "tvOS") + begin_group "Installing tvOS 26.0 simulator" + xcodebuild -downloadPlatform tvOS -quiet || { + log_warning "Failed to download tvOS platform, continuing..." + } + end_group + ;; + "visionOS") + begin_group "Installing visionOS 26.0 simulator" + xcodebuild -downloadPlatform visionOS -quiet || { + log_warning "Failed to download visionOS platform, continuing..." + } + end_group + ;; + "watchOS") + begin_group "Installing watchOS 26.0 simulator" + xcodebuild -downloadPlatform watchOS -quiet || { + log_warning "Failed to download watchOS platform, continuing..." + } + end_group + ;; + *) + log_warning "Unknown platform: $platform, skipping..." + ;; + esac +done + +log_notice "Platform installation completed" + +begin_group "List Available Simulators" +xcrun simctl list +end_group diff --git a/scripts/ci-select-xcode.sh b/scripts/ci-select-xcode.sh index ad6b81715d1..294a82ed8e5 100755 --- a/scripts/ci-select-xcode.sh +++ b/scripts/ci-select-xcode.sh @@ -7,9 +7,33 @@ set -euo pipefail +# Disable SC1091 because it won't work with pre-commit +# shellcheck source=./scripts/ci-utils.sh disable=SC1091 +source "$(cd "$(dirname "$0")" && pwd)/ci-utils.sh" + XCODE_VERSION="${1}" # We prefer this over calling `sudo xcode-select` because it will fail if the Xcode version # is not installed. Also xcodes is preinstalled on the GH runners. xcodes select "$XCODE_VERSION" swiftc --version + + +begin_group "List Available Simulators" + +# On GH actions this command should cause the GH actions to recache and detect missing runtimes, as pointed out in +# https://github.com/actions/runner-images/issues/12948#issuecomment-3248563014 +# The command is fast and should avoids problems we had with GH actions not having specific simulators installed +# see https://github.com/getsentry/sentry-cocoa/pull/6053. + +start_time=$(date +%s) + +xcrun simctl list + +end_time=$(date +%s) +xcrun_simctl_list_duration=$((end_time - start_time)) + +end_group + +# We want to log the duration after the group, because otherwise it's hidden at the end of the group. +echo "List Available Simulators completed in ${xcrun_simctl_list_duration} seconds" diff --git a/scripts/ci-utils.sh b/scripts/ci-utils.sh new file mode 100644 index 00000000000..b01b2701d15 --- /dev/null +++ b/scripts/ci-utils.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# Utility functions for CI logging and grouping. +# This file is intended to be sourced from other scripts. + +# Detect if we are running on GitHub Actions +if [ "${GITHUB_ACTIONS:-}" = "true" ]; then + IS_GITHUB_ACTIONS=true +else + IS_GITHUB_ACTIONS=false +fi + +log_notice() { + if $IS_GITHUB_ACTIONS; then + echo "::notice::${1}" + else + echo "[notice] ${1}" + fi +} + +log_warning() { + if $IS_GITHUB_ACTIONS; then + echo "::warning::${1}" + else + echo "[warning] ${1}" + fi +} + +log_error() { + if $IS_GITHUB_ACTIONS; then + echo "::error::${1}" + else + echo "[error] ${1}" + fi +} + +begin_group() { + local title="$1" + if $IS_GITHUB_ACTIONS; then + echo "::group::${title}" + else + echo + echo "== ${title} ==" + fi +} + +end_group() { + if $IS_GITHUB_ACTIONS; then + echo "::endgroup::" + fi +} diff --git a/scripts/create-cherry-pick-branch.sh b/scripts/create-cherry-pick-branch.sh index f0b3231ee50..d26ad249708 100755 --- a/scripts/create-cherry-pick-branch.sh +++ b/scripts/create-cherry-pick-branch.sh @@ -25,4 +25,3 @@ git cherry-pick "$commit_hash" git push origin "$hotfix_branch" echo "Hotfix branch $hotfix_branch created and pushed successfully." - diff --git a/scripts/generate-classes.sh b/scripts/generate-classes.sh index dbea603af5d..4defb2cae36 100755 --- a/scripts/generate-classes.sh +++ b/scripts/generate-classes.sh @@ -81,4 +81,4 @@ do }" >> $dsnStorage done - \ No newline at end of file + diff --git a/scripts/generate_release_matrix.sh b/scripts/generate_release_matrix.sh new file mode 100755 index 00000000000..46dddf95bdc --- /dev/null +++ b/scripts/generate_release_matrix.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# This script is used to generate the matrix combinations for the release workflow. +# Rewritten to use jq as much as possible for maintainability. + +set -euo pipefail + +# Slices and Variants only needed on PRs +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"} +]' +BASE_VARIANTS_JSON='[ + {"scheme": "Sentry", "macho-type": "mh_dylib", "suffix": "-Dynamic", "id": "sentry-dynamic", "excluded-archs": "arm64e"}, + {"scheme": "Sentry", "macho-type": "staticlib", "id": "sentry-static"}, + {"scheme": "SentrySwiftUI", "macho-type": "mh_dylib", "id": "sentry-swiftui"}, + {"scheme": "Sentry", "macho-type": "mh_dylib", "suffix": "-WithoutUIKitOrAppKit", "configuration-suffix": "WithoutUIKit", "id": "sentry-withoutuikit-dynamic", "excluded-archs": "arm64e"} +]' +BASE_SDKS_JSON='[ + "iphoneos", + "iphonesimulator", + "macosx", + "maccatalyst", + "appletvos", + "watchos", + "xros" +]' + +# Slices and Variants only needed on main or release +ADDITIONAL_VARIANTS_JSON='[ + {"scheme": "Sentry", "macho-type": "mh_dylib", "suffix": "-Dynamic", "id": "sentry-dynamic", "override-name": "Sentry-Dynamic-WithARM64e"}, + {"scheme": "Sentry", "macho-type": "mh_dylib", "suffix": "-WithoutUIKitOrAppKit", "configuration-suffix": "WithoutUIKit", "id": "sentry-withoutuikit-dynamic", "override-name": "Sentry-WithoutUIKitOrAppKit-WithARM64e"} +]' +ADDITIONAL_SDKS_JSON='[ + "appletvsimulator", + "watchsimulator", + "xrsimulator" +]' + +if [ "$EVENT_NAME" = "pull_request" ]; then + SLICES_COMBINATIONS="$BASE_SLICES_JSON" + VARIANTS_COMBINATIONS="$BASE_VARIANTS_JSON" + SDK_LIST="$BASE_SDKS_JSON" +else + SLICES_COMBINATIONS="$BASE_SLICES_JSON" + VARIANTS_COMBINATIONS=$(jq -c -s '.[0] + .[1]' <(echo "$BASE_VARIANTS_JSON") <(echo "$ADDITIONAL_VARIANTS_JSON")) + SDK_LIST=$(jq -c -s '.[0] + .[1]' <(echo "$BASE_SDKS_JSON") <(echo "$ADDITIONAL_SDKS_JSON")) +fi + +{ + echo "slices=$(echo "$SLICES_COMBINATIONS" | jq -c '.')" + echo "variants=$(echo "$VARIANTS_COMBINATIONS" | jq -c '.')" + echo "sdk-list-array=$(echo "$SDK_LIST" | jq -c '.')" + echo "sdk-list-string=$(echo "$SDK_LIST" | jq -r 'join(",")')" +} >> "$GITHUB_OUTPUT" diff --git a/scripts/remove-architectures.sh b/scripts/remove-architectures.sh new file mode 100755 index 00000000000..6368d94e775 --- /dev/null +++ b/scripts/remove-architectures.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +# Script to remove specific architectures from framework binaries in XCFramework slices +# Usage: ./scripts/remove-architectures.sh +# Example: ./scripts/remove-architectures.sh xcframework-slices/iphoneos.xcarchive "arm64" + +set -e + +# Check if required arguments are provided +if [ $# -ne 2 ]; then + echo "Usage: $0 " + echo "Example: $0 xcframework-slices/iphoneos.xcarchive \"arm64e\"" + exit 1 +fi + +XCARCHIVE_PATH="$1" +EXCLUDED_ARCH="$2" + +# Validate that the xcarchive path exists +if [ ! -d "$XCARCHIVE_PATH" ]; then + echo "Error: XCArchive path does not exist: $XCARCHIVE_PATH" + exit 1 +fi + +# Check if excluded architectures are provided +if [ -z "$EXCLUDED_ARCH" ]; then + echo "Warning: No excluded architecture specified. Nothing to do." + exit 0 +fi + +echo "Removing architectures from frameworks in: $XCARCHIVE_PATH" +echo "Excluded architectures: $EXCLUDED_ARCH" + +# Find all framework directories and process their binaries +find "$XCARCHIVE_PATH" -name "*.framework" -type d | while read -r framework_path; do + binary_path="$framework_path/$(basename "$framework_path" .framework)" + if [ -L "$binary_path" ]; then + echo "Resolving symlink at path: $binary_path" + binary_path=$(readlink -f "$binary_path") + fi + if [ -f "$binary_path" ]; then + echo "Processing binary: $binary_path" + + # Check what architectures are currently in the binary + echo "Current architectures in binary:" + lipo -info "$binary_path" + + should_remove="" + + # Check if the excluded architectures are actually present + if lipo -info "$binary_path" | grep -q "$EXCLUDED_ARCH"; then + echo "Architecture '$EXCLUDED_ARCH' found in binary, will remove it" + should_remove=true + else + echo "Warning: Architecture '$EXCLUDED_ARCH' not found in binary, skipping removal" + fi + + # Only perform removal if there are architectures to remove + if [ -n "$should_remove" ]; then + echo "Removing architectures:$EXCLUDED_ARCH" + temp_binary="${binary_path}.tmp" + lipo -remove "$EXCLUDED_ARCH" "$binary_path" -output "$temp_binary" + mv "$temp_binary" "$binary_path" + echo "Updated binary: $binary_path" + else + echo "No architectures to remove for this binary" + fi + fi +done + +echo "Architecture removal completed successfully." diff --git a/scripts/sentry-xcodebuild.sh b/scripts/sentry-xcodebuild.sh index a6de0d9263f..e67da685fcb 100755 --- a/scripts/sentry-xcodebuild.sh +++ b/scripts/sentry-xcodebuild.sh @@ -13,7 +13,7 @@ PLATFORM="" OS="latest" REF_NAME="HEAD" COMMAND="test" -DEVICE="iPhone 14" +DEVICE="iPhone 14 Pro" CONFIGURATION_OVERRIDE="" DERIVED_DATA_PATH="" TEST_SCHEME="Sentry" @@ -24,7 +24,7 @@ usage() { echo " -o|--os OS version (default: latest)" echo " -r|--ref Reference name (default: HEAD)" echo " -c|--command Command (build/build-for-testing/test-without-building/test)" - echo " -d|--device Device name (default: iPhone 14)" + echo " -d|--device Device name (default: iPhone 14 Pro)" echo " -C|--configuration Configuration override" echo " -D|--derived-data Derived data path" echo " -s|--scheme Test scheme (default: Sentry)" @@ -141,10 +141,9 @@ if [ $RUN_BUILD == true ]; then -configuration "$CONFIGURATION" \ -destination "$DESTINATION" \ -derivedDataPath "$DERIVED_DATA_PATH" \ - -quiet \ build 2>&1 | tee raw-build-output.log | - xcbeautify + xcbeautify --preserve-unbeautified fi if [ $RUN_BUILD_FOR_TESTING == true ]; then @@ -153,10 +152,9 @@ if [ $RUN_BUILD_FOR_TESTING == true ]; then -scheme "$TEST_SCHEME" \ -configuration "$CONFIGURATION" \ -destination "$DESTINATION" \ - -quiet \ build-for-testing 2>&1 | tee raw-build-for-testing-output.log | - xcbeautify + xcbeautify --preserve-unbeautified fi if [ $RUN_TEST_WITHOUT_BUILDING == true ]; then @@ -167,6 +165,5 @@ if [ $RUN_TEST_WITHOUT_BUILDING == true ]; then -destination "$DESTINATION" \ test-without-building 2>&1 | tee raw-test-output.log | - xcbeautify --report junit && - slather coverage --configuration "$CONFIGURATION" --scheme "$TEST_SCHEME" + xcbeautify --report junit fi diff --git a/scripts/tests-with-thread-sanitizer.sh b/scripts/tests-with-thread-sanitizer.sh index 611713e5176..0cfe63a5a3a 100755 --- a/scripts/tests-with-thread-sanitizer.sh +++ b/scripts/tests-with-thread-sanitizer.sh @@ -10,7 +10,7 @@ set -o pipefail && NSUnbufferedIO=YES CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRE -scheme Sentry \ -configuration Test \ -enableThreadSanitizer YES \ - -destination "platform=iOS Simulator,OS=latest,name=iPhone 16" \ + -destination "platform=iOS Simulator,OS=18.4,name=iPhone 16 Pro" \ -skip-testing:"SentryProfilerTests" \ test 2>&1 | tee thread-sanitizer.log | diff --git a/scripts/update-api.sh b/scripts/update-api.sh index deb6ecffa9f..77a7ba90a60 100755 --- a/scripts/update-api.sh +++ b/scripts/update-api.sh @@ -1,15 +1,34 @@ #!/bin/bash set -euo pipefail -./scripts/build-xcframework-local.sh iOSOnly DynamicOnly +configuration_suffix="${1-}" + +./scripts/build-xcframework-slice.sh "iphoneos" "Sentry" "-Dynamic" "mh_dylib" "$configuration_suffix" + +./scripts/assemble-xcframework.sh "Sentry" "-Dynamic" "" "iphoneos" "$(pwd)/Carthage/archive/Sentry-Dynamic/SDK_NAME.xcarchive" # Delete private .swiftinterface files before running swift-api-digester # This ensures only public interfaces are analyzed find ./Sentry-Dynamic.xcframework -name "*.private.swiftinterface" -type f -delete +if [ "$configuration_suffix" = "V9" ]; then + FWROOT="./Sentry-Dynamic.xcframework/ios-arm64_arm64e/Sentry.framework" + for FRAME in Headers PrivateHeaders; do + HDRDIR="$FWROOT/${FRAME}" + for H in "$HDRDIR"/*.h; do + # unifdef will: + # - keep code under #if SDK_V9 (because of -D) + # - remove code under #else + # - strip away the #if/#else/#endif lines themselves + unifdef -D SDK_V9 -x 2 "$H" > "$H.tmp" + mv "$H.tmp" "$H" + done + done +fi + xcrun --sdk iphoneos swift-api-digester \ -dump-sdk \ - -o sdk_api.json \ + -o sdk_api${configuration_suffix:+"_${configuration_suffix}"}.json \ -abort-on-module-fail \ -avoid-tool-args \ -avoid-location \ diff --git a/scripts/update-package-sha.sh b/scripts/update-package-sha.sh index 22043cca6b8..b327d6f2e4d 100755 --- a/scripts/update-package-sha.sh +++ b/scripts/update-package-sha.sh @@ -6,18 +6,37 @@ if [ -z "$GITHUB_RUN_ID" ]; then exit 1 fi +PACKAGE_FILES=$(find . -maxdepth 1 -name "Package.swift" -o -name "Package@swift-*.swift" | sort) + +if [ -z "$PACKAGE_FILES" ]; then + echo "::error::No Package.swift or Package@swift-*.swift files found" + exit 1 +fi + NEW_CHECKSUM_STATIC=$(shasum -a 256 Carthage/Sentry.xcframework.zip | awk '{print $1}') NEW_CHECKSUM_DYNAMIC=$(shasum -a 256 Carthage/Sentry-Dynamic.xcframework.zip | awk '{print $1}') +NEW_CHECKSUM_DYNAMIC_WITH_ARM64E=$(shasum -a 256 Carthage/Sentry-Dynamic-WithARM64e.xcframework.zip | awk '{print $1}') +NEW_CHECKSUM_WITHOUT_UIKIT_OR_APPKIT=$(shasum -a 256 Carthage/Sentry-WithoutUIKitOrAppKit.xcframework.zip | awk '{print $1}') +NEW_CHECKSUM_WITHOUT_UIKIT_OR_APPKIT_WITH_ARM64E=$(shasum -a 256 Carthage/Sentry-WithoutUIKitOrAppKit-WithARM64e.xcframework.zip | awk '{print $1}') os=$(uname) -# Craft pre-release command runs on an ubuntu machine -# and `sed` needs an extra argument for macOS -if [ "$os" == "Linux" ]; then - sed -i "s/checksum: \".*\" \/\/Sentry-Static/checksum: \"$NEW_CHECKSUM_STATIC\" \/\/Sentry-Static/" Package.swift - sed -i "s/checksum: \".*\" \/\/Sentry-Dynamic/checksum: \"$NEW_CHECKSUM_DYNAMIC\" \/\/Sentry-Dynamic/" Package.swift -else - sed -i "" "s/checksum: \".*\" \/\/Sentry-Static/checksum: \"$NEW_CHECKSUM_STATIC\" \/\/Sentry-Static/" Package.swift - sed -i "" "s/checksum: \".*\" \/\/Sentry-Dynamic/checksum: \"$NEW_CHECKSUM_DYNAMIC\" \/\/Sentry-Dynamic/" Package.swift -fi + +for package_file in $PACKAGE_FILES; do + # Craft pre-release command runs on an ubuntu machine + # and `sed` needs an extra argument for macOS + if [ "$os" == "Linux" ]; then + sed -i "s/checksum: \".*\" \/\/Sentry-Static/checksum: \"$NEW_CHECKSUM_STATIC\" \/\/Sentry-Static/" "$package_file" + sed -i "s/checksum: \".*\" \/\/Sentry-Dynamic/checksum: \"$NEW_CHECKSUM_DYNAMIC\" \/\/Sentry-Dynamic/" "$package_file" + sed -i "s/checksum: \".*\" \/\/Sentry-Dynamic-WithARM64e/checksum: \"$NEW_CHECKSUM_DYNAMIC_WITH_ARM64E\" \/\/Sentry-Dynamic-WithARM64e/" "$package_file" + sed -i "s/checksum: \".*\" \/\/Sentry-WithoutUIKitOrAppKit/checksum: \"$NEW_CHECKSUM_WITHOUT_UIKIT_OR_APPKIT\" \/\/Sentry-WithoutUIKitOrAppKit/" "$package_file" + sed -i "s/checksum: \".*\" \/\/Sentry-WithoutUIKitOrAppKit-WithARM64e/checksum: \"$NEW_CHECKSUM_WITHOUT_UIKIT_OR_APPKIT_WITH_ARM64E\" \/\/Sentry-WithoutUIKitOrAppKit-WithARM64e/" "$package_file" + else + sed -i "" "s/checksum: \".*\" \/\/Sentry-Static/checksum: \"$NEW_CHECKSUM_STATIC\" \/\/Sentry-Static/" "$package_file" + sed -i "" "s/checksum: \".*\" \/\/Sentry-Dynamic/checksum: \"$NEW_CHECKSUM_DYNAMIC\" \/\/Sentry-Dynamic/" "$package_file" + sed -i "" "s/checksum: \".*\" \/\/Sentry-Dynamic-WithARM64e/checksum: \"$NEW_CHECKSUM_DYNAMIC_WITH_ARM64E\" \/\/Sentry-Dynamic-WithARM64e/" "$package_file" + sed -i "" "s/checksum: \".*\" \/\/Sentry-WithoutUIKitOrAppKit/checksum: \"$NEW_CHECKSUM_WITHOUT_UIKIT_OR_APPKIT\" \/\/Sentry-WithoutUIKitOrAppKit/" "$package_file" + sed -i "" "s/checksum: \".*\" \/\/Sentry-WithoutUIKitOrAppKit-WithARM64e/checksum: \"$NEW_CHECKSUM_WITHOUT_UIKIT_OR_APPKIT_WITH_ARM64E\" \/\/Sentry-WithoutUIKitOrAppKit-WithARM64e/" "$package_file" + fi +done echo "$GITHUB_RUN_ID" > .github/last-release-runid diff --git a/scripts/validate-xcframework-format.sh b/scripts/validate-xcframework-format.sh new file mode 100755 index 00000000000..f90c1a00e64 --- /dev/null +++ b/scripts/validate-xcframework-format.sh @@ -0,0 +1,172 @@ +#!/bin/bash + +# Script to validate the format of XCFramework bundles +# Usage: ./scripts/validate-xcframework-format.sh +# Example: ./scripts/validate-xcframework-format.sh Sentry.xcframework + +set -e + +# Check if required arguments are provided +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "Example: $0 Sentry.xcframework" + exit 1 +fi + +XCFRAMEWORK_PATH="$1" + +# Validate that the xcframework path exists +if [ ! -d "$XCFRAMEWORK_PATH" ]; then + echo "Error: XCFramework path does not exist: $XCFRAMEWORK_PATH" + exit 1 +fi + +# Check if it's actually an xcframework +if [ ! -f "$XCFRAMEWORK_PATH/Info.plist" ]; then + echo "Error: $XCFRAMEWORK_PATH is not a valid XCFramework (missing Info.plist)" + exit 1 +fi + +echo "Validating XCFramework format: $XCFRAMEWORK_PATH" + +# Track validation results +validation_errors=0 + +# Function to check if a path is a symlink +is_symlink() { + [ -L "$1" ] +} + +# Function to check if a symlink is valid (points to existing target) +is_valid_symlink() { + if is_symlink "$1"; then + target=$(readlink "$1") + [ -e "$(dirname "$1")/$target" ] + else + false + fi +} + +# Function to validate framework structure +validate_framework() { + local framework_path="$1" + local framework_name + framework_name=$(basename "$framework_path" .framework) + local binary_path="$framework_path/$framework_name" + + echo " Validating framework: $framework_name" + + # Check if framework has a Versions directory + if [ -d "$framework_path/Versions" ]; then + echo " Framework is versioned" + + # Check if the main binary is a symlink + if is_symlink "$binary_path"; then + echo " ✅ Main binary is a symlink" + + # Check if the symlink is valid + if is_valid_symlink "$binary_path"; then + echo " ✅ Symlink is valid" + + # Get the target of the symlink + symlink_target=$(readlink "$binary_path") + echo " ✅ Symlink points to: $symlink_target" + + # Verify the target exists in Versions + if [ -f "$framework_path/$symlink_target" ]; then + echo " ✅ Symlink target exists" + else + echo " ❌ Symlink target does not exist: $framework_path/$symlink_target" + ((validation_errors++)) + fi + else + echo " ❌ Symlink is broken (target does not exist)" + ((validation_errors++)) + fi + else + echo " ❌ Main binary should be a symlink when Versions directory exists" + ((validation_errors++)) + fi + + # Check Versions directory structure + if [ -d "$framework_path/Versions/Current" ]; then + echo " Found Versions/Current directory" + + # Check if Current is a symlink + if is_symlink "$framework_path/Versions/Current"; then + echo " ✅ Versions/Current is a symlink" + + if is_valid_symlink "$framework_path/Versions/Current"; then + echo " ✅ Versions/Current symlink is valid" + else + echo " ❌ Versions/Current symlink is broken" + ((validation_errors++)) + fi + else + echo " ❌ Versions/Current should be a symlink" + ((validation_errors++)) + fi + else + echo " ❌ Versions/Current directory not found" + ((validation_errors++)) + fi + else + echo " No Versions directory found (standard framework structure)" + + # For frameworks without Versions, the binary should be a regular file + if [ -f "$binary_path" ] && ! is_symlink "$binary_path"; then + echo " ✅ Main binary is not a symlink" + else + echo " ❌ Main binary is a symlink or does not exist: $binary_path" + ((validation_errors++)) + fi + fi +} + +# Find all platform-specific directories in the xcframework +platform_dirs=$(find "$XCFRAMEWORK_PATH" -maxdepth 1 -type d -not -name "*.xcframework" -not -name "." | grep -v "Info.plist" | sort) + +if [ -z "$platform_dirs" ]; then + echo "Error: No platform directories found in XCFramework" + exit 1 +fi + +echo "Found platform directories:" +echo "${platform_dirs//^/ }" + +echo "" +echo "Validating framework structures..." + +# Validate each platform directory +while IFS= read -r platform_dir; do + if [ -n "$platform_dir" ]; then + echo "" + echo "Platform: $(basename "$platform_dir")" + + # Find all .framework directories in this platform + frameworks=$(find "$platform_dir" -name "*.framework" -type d) + + if [ -z "$frameworks" ]; then + echo " ⚠️ No .framework directories found" + else + while IFS= read -r framework; do + if [ -n "$framework" ]; then + validate_framework "$framework" + fi + done <<< "$frameworks" + fi + fi +done <<< "$platform_dirs" + +echo "" +echo "==========================================" +echo "Validation Summary:" + +if [ $validation_errors -eq 0 ]; then + echo "✅ All validations passed! XCFramework format is correct." + exit 0 +else + echo "❌ Validation failed with $validation_errors error(s)." + echo "Please fix the errors before using this XCFramework." + exit 1 +fi diff --git a/scripts/verify-package-sha.sh b/scripts/verify-package-sha.sh index 566e73fa5c8..6f5ebcd437d 100755 --- a/scripts/verify-package-sha.sh +++ b/scripts/verify-package-sha.sh @@ -8,6 +8,9 @@ set -euo pipefail # Parse command line arguments EXPECTED_STATIC_CHECKSUM="" EXPECTED_DYNAMIC_CHECKSUM="" +EXPECTED_DYNAMIC_WITH_ARM64E_CHECKSUM="" +EXPECTED_WITHOUT_UIKIT_OR_APPKIT_CHECKSUM="" +EXPECTED_WITHOUT_UIKIT_OR_APPKIT_WITH_ARM64E_CHECKSUM="" EXPECTED_LAST_RELEASE_RUNID="" while [[ $# -gt 0 ]]; do @@ -20,6 +23,18 @@ while [[ $# -gt 0 ]]; do EXPECTED_DYNAMIC_CHECKSUM="$2" shift 2 ;; + --dynamic-with-arm64e-checksum) + EXPECTED_DYNAMIC_WITH_ARM64E_CHECKSUM="$2" + shift 2 + ;; + --without-uikit-or-appkit-checksum) + EXPECTED_WITHOUT_UIKIT_OR_APPKIT_CHECKSUM="$2" + shift 2 + ;; + --without-uikit-or-appkit-with-arm64e-checksum) + EXPECTED_WITHOUT_UIKIT_OR_APPKIT_WITH_ARM64E_CHECKSUM="$2" + shift 2 + ;; --last-release-runid) EXPECTED_LAST_RELEASE_RUNID="$2" shift 2 @@ -42,25 +57,78 @@ if [ -z "$EXPECTED_DYNAMIC_CHECKSUM" ]; then exit 1 fi -if [ -z "$EXPECTED_LAST_RELEASE_RUNID" ]; then - echo "Error: --last-release-runid is required" +if [ -z "$EXPECTED_DYNAMIC_WITH_ARM64E_CHECKSUM" ]; then + echo "Error: --dynamic-with-arm64e-checksum is required" exit 1 fi -echo "Verify checksum of static xcframework in Package.swift" -UPDATED_PACKAGE_SHA=$(grep "checksum.*Sentry-Static" Package.swift | cut -d '"' -f 2) -if [ "$UPDATED_PACKAGE_SHA" != "$EXPECTED_STATIC_CHECKSUM" ]; then - echo "::error::Expected checksum to be $EXPECTED_STATIC_CHECKSUM but got $UPDATED_PACKAGE_SHA" +if [ -z "$EXPECTED_WITHOUT_UIKIT_OR_APPKIT_CHECKSUM" ]; then + echo "Error: --without-uikit-or-appkit-checksum is required" exit 1 fi -echo "Verify checksum of dynamic xcframework in Package.swift" -UPDATED_PACKAGE_SHA=$(grep "checksum.*Sentry-Dynamic" Package.swift | cut -d '"' -f 2) -if [ "$UPDATED_PACKAGE_SHA" != "$EXPECTED_DYNAMIC_CHECKSUM" ]; then - echo "::error::Expected checksum to be $EXPECTED_DYNAMIC_CHECKSUM but got $UPDATED_PACKAGE_SHA" +if [ -z "$EXPECTED_WITHOUT_UIKIT_OR_APPKIT_WITH_ARM64E_CHECKSUM" ]; then + echo "Error: --without-uikit-or-appkit-with-arm64e-checksum is required" exit 1 fi +if [ -z "$EXPECTED_LAST_RELEASE_RUNID" ]; then + echo "Error: --last-release-runid is required" + exit 1 +fi + +# Find all Package.swift and Package@swift-*.swift files +PACKAGE_FILES=$(find . -maxdepth 1 -name "Package.swift" -o -name "Package@swift-*.swift" | sort) + +if [ -z "$PACKAGE_FILES" ]; then + echo "::error::No Package.swift or Package@swift-*.swift files found" + exit 1 +fi + +# Verify checksums in each Package file +for package_file in $PACKAGE_FILES; do + echo "Verifying checksums in $package_file" + + # Verify static checksum + UPDATED_PACKAGE_SHA=$(grep "checksum.*Sentry-Static" "$package_file" | cut -d '"' -f 2) + if [ "$UPDATED_PACKAGE_SHA" != "$EXPECTED_STATIC_CHECKSUM" ]; then + echo "::error::Expected static checksum to be $EXPECTED_STATIC_CHECKSUM but got $UPDATED_PACKAGE_SHA in $package_file" + exit 1 + fi + + # Verify dynamic checksum + UPDATED_PACKAGE_SHA=$(grep "checksum.*Sentry-Dynamic" "$package_file" | cut -d '"' -f 2 | head -n 1) + if [ "$UPDATED_PACKAGE_SHA" != "$EXPECTED_DYNAMIC_CHECKSUM" ]; then + echo "::error::Expected dynamic checksum to be $EXPECTED_DYNAMIC_CHECKSUM but got $UPDATED_PACKAGE_SHA in $package_file" + exit 1 + fi + + # Verify dynamic with arm64e checksum + UPDATED_PACKAGE_SHA=$(grep "checksum.*Sentry-Dynamic-WithARM64e" "$package_file" | cut -d '"' -f 2) + if [ "$UPDATED_PACKAGE_SHA" != "$EXPECTED_DYNAMIC_WITH_ARM64E_CHECKSUM" ]; then + echo "::error::Expected checksum to be $EXPECTED_DYNAMIC_WITH_ARM64E_CHECKSUM but got $UPDATED_PACKAGE_SHA in $package_file" + exit 1 + fi + + # Verify without uikit or appkit checksum + UPDATED_PACKAGE_SHA=$(grep "checksum.*Sentry-WithoutUIKitOrAppKit" "$package_file" | cut -d '"' -f 2 | head -n 1) + if [ "$UPDATED_PACKAGE_SHA" != "$EXPECTED_WITHOUT_UIKIT_OR_APPKIT_CHECKSUM" ]; then + echo "::error::Expected checksum to be $EXPECTED_WITHOUT_UIKIT_OR_APPKIT_CHECKSUM but got $UPDATED_PACKAGE_SHA in $package_file" + exit 1 + fi + + # Verify without uikit or appkit with arm64e checksum + UPDATED_PACKAGE_SHA=$(grep "checksum.*Sentry-WithoutUIKitOrAppKit-WithARM64e" "$package_file" | cut -d '"' -f 2) + if [ "$UPDATED_PACKAGE_SHA" != "$EXPECTED_WITHOUT_UIKIT_OR_APPKIT_WITH_ARM64E_CHECKSUM" ]; then + echo "::error::Expected checksum to be $EXPECTED_WITHOUT_UIKIT_OR_APPKIT_WITH_ARM64E_CHECKSUM but got $UPDATED_PACKAGE_SHA in $package_file" + exit 1 + fi + + echo "✓ All checksums verified in $package_file" +done + + + echo "Verify last-release-runid" LAST_RELEASE_RUNID=$(cat .github/last-release-runid) if [ "$LAST_RELEASE_RUNID" != "$EXPECTED_LAST_RELEASE_RUNID" ]; then diff --git a/scripts/xcode-slowest-tests.sh b/scripts/xcode-slowest-tests.sh deleted file mode 100755 index 21e7390a75c..00000000000 --- a/scripts/xcode-slowest-tests.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -set -eu - -# Finds the x amount of slowest test cases in the raw-test-output.log file. -# Logic copied from https://stanislaw.github.io/2016/08/04/how-to-find-the-slowest-xctest.html. - -RAW_TEST_OUTPUT_LOG=${1:-raw-test-output.log} -NUMBER_OF_SLOWEST_TEST="${2:-20}" - -echo "The $NUMBER_OF_SLOWEST_TEST slowest test cases:" -grep 'Test\ Case.*seconds' "$RAW_TEST_OUTPUT_LOG" | awk -F '[()]' '{print $2 " -> " $1}' | sort -rn | head -n "$NUMBER_OF_SLOWEST_TEST" diff --git a/scripts/xcodegen.rb b/scripts/xcodegen.rb new file mode 100644 index 00000000000..7f58837b39f --- /dev/null +++ b/scripts/xcodegen.rb @@ -0,0 +1,48 @@ +# This file must have the name `xcodegen.rb` or brew wont accept it. +class Xcodegen < Formula + desc "Generate your Xcode project from a spec file and your folder structure" + homepage "https://github.com/yonaskolb/XcodeGen" + url "https://github.com/yonaskolb/XcodeGen/archive/refs/tags/2.43.0.tar.gz" + sha256 "d79a89ea056ccc3cf84b736ee52c7b5184a560e54808e51f418f34d292869d66" + license "MIT" + head "https://github.com/yonaskolb/XcodeGen.git", branch: "master" + + bottle do + sha256 cellar: :any_skip_relocation, arm64_sequoia: "1d08e16ea70ce5f323dd53197ed1204c6a78be04e629bb8e8cd11329b5d13c5d" + sha256 cellar: :any_skip_relocation, arm64_sonoma: "b52935ffdb916dcfa90efef93419cbc050764f0d29e139ef951b8b994ee492c3" + sha256 cellar: :any_skip_relocation, arm64_ventura: "db60cd9e7757912208a1ba128f1652f9dd49beac21d7b83bfd9d16d59bc6241f" + sha256 cellar: :any_skip_relocation, sonoma: "58ca67427dc960bc75413e651a476926eeed167e10dec790dfd16d560334fa70" + sha256 cellar: :any_skip_relocation, ventura: "6efa069b3f9ade5e77b7d0dd1fa76b3dae8d3914d45a3da5ff48a8e79e3a5f75" + end + + depends_on xcode: ["14.0", :build] + depends_on :macos + + uses_from_macos "swift" + + def install + system "swift", "build", "--disable-sandbox", "-c", "release" + bin.install ".build/release/#{name}" + pkgshare.install "SettingPresets" + end + + test do + (testpath/"xcodegen.yml").write <<~YAML + name: GeneratedProject + options: + bundleIdPrefix: com.project + targets: + TestProject: + type: application + platform: iOS + sources: TestProject + YAML + (testpath/"TestProject").mkpath + system bin/"xcodegen", "--spec", testpath/"xcodegen.yml" + assert_path_exists testpath/"GeneratedProject.xcodeproj" + assert_path_exists testpath/"GeneratedProject.xcodeproj/project.pbxproj" + output = (testpath/"GeneratedProject.xcodeproj/project.pbxproj").read + assert_match "name = TestProject", output + assert_match "isa = PBXNativeTarget", output + end +end diff --git a/sdk_api.json b/sdk_api.json index ab07bef9150..6285ce95494 100644 --- a/sdk_api.json +++ b/sdk_api.json @@ -284,16 +284,6 @@ "Exported" ] }, - { - "kind": "Import", - "name": "Sentry.SentrySDK", - "printedName": "Sentry.SentrySDK", - "declKind": "Import", - "moduleName": "Sentry", - "declAttributes": [ - "Exported" - ] - }, { "kind": "Import", "name": "Sentry.SentrySampleDecision", @@ -9451,31 +9441,30 @@ }, { "kind": "Var", - "name": "inApp", - "printedName": "inApp", + "name": "contextLine", + "printedName": "contextLine", "children": [ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Foundation.NSNumber?", + "printedName": "Swift.String?", "children": [ { "kind": "TypeNominal", - "name": "NSNumber", - "printedName": "Foundation.NSNumber", - "usr": "c:objc(cs)NSNumber" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "usr": "s:Sq" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryFrame(py)inApp", + "usr": "c:objc(cs)SentryFrame(py)contextLine", "moduleName": "Sentry", "isOpen": true, - "objc_name": "inApp", + "objc_name": "contextLine", "declAttributes": [ - "NSCopying", "ObjC", "Dynamic" ], @@ -9488,23 +9477,23 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Foundation.NSNumber?", + "printedName": "Swift.String?", "children": [ { "kind": "TypeNominal", - "name": "NSNumber", - "printedName": "Foundation.NSNumber", - "usr": "c:objc(cs)NSNumber" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryFrame(im)inApp", + "usr": "c:objc(cs)SentryFrame(im)contextLine", "moduleName": "Sentry", "isOpen": true, - "objc_name": "inApp", + "objc_name": "contextLine", "declAttributes": [ "DiscardableResult", "ObjC", @@ -9532,23 +9521,23 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Foundation.NSNumber?", + "printedName": "Swift.String?", "children": [ { "kind": "TypeNominal", - "name": "NSNumber", - "printedName": "Foundation.NSNumber", - "usr": "c:objc(cs)NSNumber" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryFrame(im)setInApp:", + "usr": "c:objc(cs)SentryFrame(im)setContextLine:", "moduleName": "Sentry", "isOpen": true, - "objc_name": "setInApp:", + "objc_name": "setContextLine:", "declAttributes": [ "ObjC", "Dynamic" @@ -9559,31 +9548,38 @@ }, { "kind": "Var", - "name": "stackStart", - "printedName": "stackStart", + "name": "preContext", + "printedName": "preContext", "children": [ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Foundation.NSNumber?", + "printedName": "[Swift.String]?", "children": [ { "kind": "TypeNominal", - "name": "NSNumber", - "printedName": "Foundation.NSNumber", - "usr": "c:objc(cs)NSNumber" + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" } ], "usr": "s:Sq" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryFrame(py)stackStart", + "usr": "c:objc(cs)SentryFrame(py)preContext", "moduleName": "Sentry", "isOpen": true, - "objc_name": "stackStart", + "objc_name": "preContext", "declAttributes": [ - "NSCopying", "ObjC", "Dynamic" ], @@ -9596,23 +9592,31 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Foundation.NSNumber?", + "printedName": "[Swift.String]?", "children": [ { "kind": "TypeNominal", - "name": "NSNumber", - "printedName": "Foundation.NSNumber", - "usr": "c:objc(cs)NSNumber" + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" } ], "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryFrame(im)stackStart", + "usr": "c:objc(cs)SentryFrame(im)preContext", "moduleName": "Sentry", "isOpen": true, - "objc_name": "stackStart", + "objc_name": "preContext", "declAttributes": [ "DiscardableResult", "ObjC", @@ -9640,23 +9644,31 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Foundation.NSNumber?", + "printedName": "[Swift.String]?", "children": [ { "kind": "TypeNominal", - "name": "NSNumber", - "printedName": "Foundation.NSNumber", - "usr": "c:objc(cs)NSNumber" + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" } ], "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryFrame(im)setStackStart:", + "usr": "c:objc(cs)SentryFrame(im)setPreContext:", "moduleName": "Sentry", "isOpen": true, - "objc_name": "setStackStart:", + "objc_name": "setPreContext:", "declAttributes": [ "ObjC", "Dynamic" @@ -9665,176 +9677,39 @@ } ] }, - { - "kind": "Constructor", - "name": "init", - "printedName": "init()", - "children": [ - { - "kind": "TypeNominal", - "name": "Frame", - "printedName": "Sentry.Frame", - "usr": "c:objc(cs)SentryFrame" - } - ], - "declKind": "Constructor", - "usr": "c:objc(cs)SentryFrame(im)init", - "moduleName": "Sentry", - "overriding": true, - "objc_name": "init", - "declAttributes": [ - "Override", - "Required", - "ObjC", - "Dynamic" - ], - "init_kind": "Designated" - }, - { - "kind": "Constructor", - "name": "init", - "printedName": "init(from:)", - "children": [ - { - "kind": "TypeNominal", - "name": "Frame", - "printedName": "Sentry.Frame", - "usr": "c:objc(cs)SentryFrame" - }, - { - "kind": "TypeNominal", - "name": "Decoder", - "printedName": "any Swift.Decoder", - "usr": "s:s7DecoderP" - } - ], - "declKind": "Constructor", - "usr": "s:So11SentryFrameC0A0E4fromABs7Decoder_p_tKcfc", - "mangledName": "$sSo11SentryFrameC0A0E4fromABs7Decoder_p_tKcfc", - "moduleName": "Sentry", - "declAttributes": [ - "Required" - ], - "isFromExtension": true, - "throwing": true, - "init_kind": "Convenience" - } - ], - "declKind": "Class", - "usr": "c:objc(cs)SentryFrame", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "SentryFrame", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "superclassUsr": "c:objc(cs)NSObject", - "inheritsConvenienceInitializers": true, - "superclassNames": [ - "ObjectiveC.NSObject" - ], - "conformances": [ - { - "kind": "Conformance", - "name": "SentrySerializable", - "printedName": "SentrySerializable", - "usr": "c:objc(pl)SentrySerializable" - }, - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "NSObjectProtocol", - "printedName": "NSObjectProtocol", - "usr": "c:objc(pl)NSObject" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "CVarArg", - "printedName": "CVarArg", - "usr": "s:s7CVarArgP", - "mangledName": "$ss7CVarArgP" - }, - { - "kind": "Conformance", - "name": "CustomStringConvertible", - "printedName": "CustomStringConvertible", - "usr": "s:s23CustomStringConvertibleP", - "mangledName": "$ss23CustomStringConvertibleP" - }, - { - "kind": "Conformance", - "name": "CustomDebugStringConvertible", - "printedName": "CustomDebugStringConvertible", - "usr": "s:s28CustomDebugStringConvertibleP", - "mangledName": "$ss28CustomDebugStringConvertibleP" - }, - { - "kind": "Conformance", - "name": "Decodable", - "printedName": "Decodable", - "usr": "s:Se", - "mangledName": "$sSe" - } - ] - }, - { - "kind": "TypeDecl", - "name": "Geo", - "printedName": "Geo", - "children": [ { "kind": "Var", - "name": "city", - "printedName": "city", + "name": "postContext", + "printedName": "postContext", "children": [ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Swift.String?", + "printedName": "[Swift.String]?", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" } ], "usr": "s:Sq" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryGeo(py)city", + "usr": "c:objc(cs)SentryFrame(py)postContext", "moduleName": "Sentry", "isOpen": true, - "objc_name": "city", + "objc_name": "postContext", "declAttributes": [ "ObjC", "Dynamic" @@ -9848,23 +9723,31 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Swift.String?", + "printedName": "[Swift.String]?", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" } ], "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryGeo(im)city", + "usr": "c:objc(cs)SentryFrame(im)postContext", "moduleName": "Sentry", "isOpen": true, - "objc_name": "city", + "objc_name": "postContext", "declAttributes": [ "DiscardableResult", "ObjC", @@ -9892,23 +9775,31 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Swift.String?", + "printedName": "[Swift.String]?", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" } ], "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryGeo(im)setCity:", + "usr": "c:objc(cs)SentryFrame(im)setPostContext:", "moduleName": "Sentry", "isOpen": true, - "objc_name": "setCity:", + "objc_name": "setPostContext:", "declAttributes": [ "ObjC", "Dynamic" @@ -9919,30 +9810,31 @@ }, { "kind": "Var", - "name": "countryCode", - "printedName": "countryCode", + "name": "inApp", + "printedName": "inApp", "children": [ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Swift.String?", + "printedName": "Foundation.NSNumber?", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } ], "usr": "s:Sq" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryGeo(py)countryCode", + "usr": "c:objc(cs)SentryFrame(py)inApp", "moduleName": "Sentry", "isOpen": true, - "objc_name": "countryCode", + "objc_name": "inApp", "declAttributes": [ + "NSCopying", "ObjC", "Dynamic" ], @@ -9955,23 +9847,23 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Swift.String?", + "printedName": "Foundation.NSNumber?", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } ], "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryGeo(im)countryCode", + "usr": "c:objc(cs)SentryFrame(im)inApp", "moduleName": "Sentry", "isOpen": true, - "objc_name": "countryCode", + "objc_name": "inApp", "declAttributes": [ "DiscardableResult", "ObjC", @@ -9999,23 +9891,23 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Swift.String?", + "printedName": "Foundation.NSNumber?", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } ], "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryGeo(im)setCountryCode:", + "usr": "c:objc(cs)SentryFrame(im)setInApp:", "moduleName": "Sentry", "isOpen": true, - "objc_name": "setCountryCode:", + "objc_name": "setInApp:", "declAttributes": [ "ObjC", "Dynamic" @@ -10026,30 +9918,31 @@ }, { "kind": "Var", - "name": "region", - "printedName": "region", + "name": "stackStart", + "printedName": "stackStart", "children": [ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Swift.String?", + "printedName": "Foundation.NSNumber?", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } ], "usr": "s:Sq" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryGeo(py)region", + "usr": "c:objc(cs)SentryFrame(py)stackStart", "moduleName": "Sentry", "isOpen": true, - "objc_name": "region", + "objc_name": "stackStart", "declAttributes": [ + "NSCopying", "ObjC", "Dynamic" ], @@ -10062,23 +9955,23 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Swift.String?", + "printedName": "Foundation.NSNumber?", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } ], "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryGeo(im)region", + "usr": "c:objc(cs)SentryFrame(im)stackStart", "moduleName": "Sentry", "isOpen": true, - "objc_name": "region", + "objc_name": "stackStart", "declAttributes": [ "DiscardableResult", "ObjC", @@ -10106,23 +9999,23 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Swift.String?", + "printedName": "Foundation.NSNumber?", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } ], "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryGeo(im)setRegion:", + "usr": "c:objc(cs)SentryFrame(im)setStackStart:", "moduleName": "Sentry", "isOpen": true, - "objc_name": "setRegion:", + "objc_name": "setStackStart:", "declAttributes": [ "ObjC", "Dynamic" @@ -10132,97 +10025,150 @@ ] }, { - "kind": "Function", - "name": "isEqual", - "printedName": "isEqual(_:)", + "kind": "Var", + "name": "vars", + "printedName": "vars", "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - }, { "kind": "TypeNominal", "name": "Optional", - "printedName": "Any?", + "printedName": "[Swift.String : Any]?", "children": [ { "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "Any" + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" } ], "usr": "s:Sq" } ], - "declKind": "Func", - "usr": "c:objc(cs)SentryGeo(im)isEqual:", + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)vars", "moduleName": "Sentry", - "overriding": true, "isOpen": true, - "objc_name": "isEqual:", + "objc_name": "vars", "declAttributes": [ - "DiscardableResult", - "Override", "ObjC", "Dynamic" ], - "funcSelfKind": "NonMutating" - }, - { - "kind": "Function", - "name": "isEqual", - "printedName": "isEqual(to:)", - "children": [ + "accessors": [ { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)vars", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "vars", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" }, { - "kind": "TypeNominal", - "name": "Geo", - "printedName": "Sentry.Geo", - "usr": "c:objc(cs)SentryGeo" - } - ], - "declKind": "Func", - "usr": "c:objc(cs)SentryGeo(im)isEqualToGeo:", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "isEqualToGeo:", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" - }, - { - "kind": "Function", - "name": "hash", - "printedName": "hash()", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setVars:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setVars:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" } - ], - "declKind": "Func", - "usr": "c:objc(cs)SentryGeo(im)hash", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "hash", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + ] }, { "kind": "Constructor", @@ -10231,19 +10177,19 @@ "children": [ { "kind": "TypeNominal", - "name": "Geo", - "printedName": "Sentry.Geo", - "usr": "c:objc(cs)SentryGeo" + "name": "Frame", + "printedName": "Sentry.Frame", + "usr": "c:objc(cs)SentryFrame" } ], "declKind": "Constructor", - "usr": "c:objc(cs)NSObject(im)init", + "usr": "c:objc(cs)SentryFrame(im)init", "moduleName": "Sentry", "overriding": true, - "implicit": true, "objc_name": "init", "declAttributes": [ "Override", + "Required", "ObjC", "Dynamic" ], @@ -10256,9 +10202,9 @@ "children": [ { "kind": "TypeNominal", - "name": "Geo", - "printedName": "Sentry.Geo", - "usr": "c:objc(cs)SentryGeo" + "name": "Frame", + "printedName": "Sentry.Frame", + "usr": "c:objc(cs)SentryFrame" }, { "kind": "TypeNominal", @@ -10268,8 +10214,8 @@ } ], "declKind": "Constructor", - "usr": "s:So9SentryGeoC0A0E4fromABs7Decoder_p_tKcfc", - "mangledName": "$sSo9SentryGeoC0A0E4fromABs7Decoder_p_tKcfc", + "usr": "s:So11SentryFrameC0A0E4fromABs7Decoder_p_tKcfc", + "mangledName": "$sSo11SentryFrameC0A0E4fromABs7Decoder_p_tKcfc", "moduleName": "Sentry", "declAttributes": [ "Required" @@ -10280,10 +10226,10 @@ } ], "declKind": "Class", - "usr": "c:objc(cs)SentryGeo", + "usr": "c:objc(cs)SentryFrame", "moduleName": "Sentry", "isOpen": true, - "objc_name": "SentryGeo", + "objc_name": "SentryFrame", "declAttributes": [ "ObjC", "Dynamic" @@ -10300,12 +10246,6 @@ "printedName": "SentrySerializable", "usr": "c:objc(pl)SentrySerializable" }, - { - "kind": "Conformance", - "name": "NSCopying", - "printedName": "NSCopying", - "usr": "c:objc(pl)NSCopying" - }, { "kind": "Conformance", "name": "Copyable", @@ -10372,26 +10312,34 @@ }, { "kind": "TypeDecl", - "name": "HttpStatusCodeRange", - "printedName": "HttpStatusCodeRange", + "name": "Geo", + "printedName": "Geo", "children": [ { "kind": "Var", - "name": "min", - "printedName": "min", + "name": "city", + "printedName": "city", "children": [ { "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryHttpStatusCodeRange(py)min", + "usr": "c:objc(cs)SentryGeo(py)city", "moduleName": "Sentry", "isOpen": true, - "objc_name": "min", + "objc_name": "city", "declAttributes": [ "ObjC", "Dynamic" @@ -10404,42 +10352,101 @@ "children": [ { "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryHttpStatusCodeRange(im)min", + "usr": "c:objc(cs)SentryGeo(im)city", "moduleName": "Sentry", "isOpen": true, - "objc_name": "min", + "objc_name": "city", "declAttributes": [ "DiscardableResult", "ObjC", "Dynamic" ], "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryGeo(im)setCity:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setCity:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" } ] }, { "kind": "Var", - "name": "max", - "printedName": "max", + "name": "countryCode", + "printedName": "countryCode", "children": [ { "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryHttpStatusCodeRange(py)max", + "usr": "c:objc(cs)SentryGeo(py)countryCode", "moduleName": "Sentry", "isOpen": true, - "objc_name": "max", + "objc_name": "countryCode", "declAttributes": [ "ObjC", "Dynamic" @@ -10452,70 +10459,257 @@ "children": [ { "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryHttpStatusCodeRange(im)max", + "usr": "c:objc(cs)SentryGeo(im)countryCode", "moduleName": "Sentry", "isOpen": true, - "objc_name": "max", + "objc_name": "countryCode", "declAttributes": [ "DiscardableResult", "ObjC", "Dynamic" ], "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryGeo(im)setCountryCode:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setCountryCode:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" } ] }, { - "kind": "Constructor", - "name": "init", - "printedName": "init(min:max:)", + "kind": "Var", + "name": "region", + "printedName": "region", "children": [ { "kind": "TypeNominal", - "name": "HttpStatusCodeRange", - "printedName": "Sentry.HttpStatusCodeRange", - "usr": "c:objc(cs)SentryHttpStatusCodeRange" - }, - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - }, - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ], - "declKind": "Constructor", - "usr": "c:objc(cs)SentryHttpStatusCodeRange(im)initWithMin:max:", - "moduleName": "Sentry", - "objc_name": "initWithMin:max:", - "declAttributes": [ - "ObjC", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryGeo(py)region", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "region", + "declAttributes": [ + "ObjC", "Dynamic" ], - "init_kind": "Designated" + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryGeo(im)region", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "region", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryGeo(im)setRegion:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setRegion:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] }, { - "kind": "Constructor", - "name": "init", - "printedName": "init(statusCode:)", + "kind": "Function", + "name": "isEqual", + "printedName": "isEqual(_:)", "children": [ { "kind": "TypeNominal", - "name": "HttpStatusCodeRange", - "printedName": "Sentry.HttpStatusCodeRange", - "usr": "c:objc(cs)SentryHttpStatusCodeRange" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Any?", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryGeo(im)isEqual:", + "moduleName": "Sentry", + "overriding": true, + "isOpen": true, + "objc_name": "isEqual:", + "declAttributes": [ + "DiscardableResult", + "Override", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "isEqual", + "printedName": "isEqual(to:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" }, + { + "kind": "TypeNominal", + "name": "Geo", + "printedName": "Sentry.Geo", + "usr": "c:objc(cs)SentryGeo" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryGeo(im)isEqualToGeo:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "isEqualToGeo:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "hash", + "printedName": "hash()", + "children": [ { "kind": "TypeNominal", "name": "Int", @@ -10523,22 +10717,78 @@ "usr": "s:Si" } ], + "declKind": "Func", + "usr": "c:objc(cs)SentryGeo(im)hash", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "hash", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "Geo", + "printedName": "Sentry.Geo", + "usr": "c:objc(cs)SentryGeo" + } + ], "declKind": "Constructor", - "usr": "c:objc(cs)SentryHttpStatusCodeRange(im)initWithStatusCode:", + "usr": "c:objc(cs)NSObject(im)init", "moduleName": "Sentry", - "objc_name": "initWithStatusCode:", + "overriding": true, + "implicit": true, + "objc_name": "init", "declAttributes": [ + "Override", "ObjC", "Dynamic" ], "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(from:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Geo", + "printedName": "Sentry.Geo", + "usr": "c:objc(cs)SentryGeo" + }, + { + "kind": "TypeNominal", + "name": "Decoder", + "printedName": "any Swift.Decoder", + "usr": "s:s7DecoderP" + } + ], + "declKind": "Constructor", + "usr": "s:So9SentryGeoC0A0E4fromABs7Decoder_p_tKcfc", + "mangledName": "$sSo9SentryGeoC0A0E4fromABs7Decoder_p_tKcfc", + "moduleName": "Sentry", + "declAttributes": [ + "Required" + ], + "isFromExtension": true, + "throwing": true, + "init_kind": "Convenience" } ], "declKind": "Class", - "usr": "c:objc(cs)SentryHttpStatusCodeRange", + "usr": "c:objc(cs)SentryGeo", "moduleName": "Sentry", "isOpen": true, - "objc_name": "SentryHttpStatusCodeRange", + "objc_name": "SentryGeo", "declAttributes": [ "ObjC", "Dynamic" @@ -10549,6 +10799,18 @@ "ObjectiveC.NSObject" ], "conformances": [ + { + "kind": "Conformance", + "name": "SentrySerializable", + "printedName": "SentrySerializable", + "usr": "c:objc(pl)SentrySerializable" + }, + { + "kind": "Conformance", + "name": "NSCopying", + "printedName": "NSCopying", + "usr": "c:objc(pl)NSCopying" + }, { "kind": "Conformance", "name": "Copyable", @@ -10603,59 +10865,38 @@ "printedName": "CustomDebugStringConvertible", "usr": "s:s28CustomDebugStringConvertibleP", "mangledName": "$ss28CustomDebugStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "Decodable", + "printedName": "Decodable", + "usr": "s:Se", + "mangledName": "$sSe" } ] }, { "kind": "TypeDecl", - "name": "MeasurementUnit", - "printedName": "MeasurementUnit", + "name": "HttpStatusCodeRange", + "printedName": "HttpStatusCodeRange", "children": [ - { - "kind": "Constructor", - "name": "init", - "printedName": "init(unit:)", - "children": [ - { - "kind": "TypeNominal", - "name": "MeasurementUnit", - "printedName": "Sentry.MeasurementUnit", - "usr": "c:objc(cs)SentryMeasurementUnit" - }, - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - } - ], - "declKind": "Constructor", - "usr": "c:objc(cs)SentryMeasurementUnit(im)initWithUnit:", - "moduleName": "Sentry", - "objc_name": "initWithUnit:", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "init_kind": "Designated" - }, { "kind": "Var", - "name": "unit", - "printedName": "unit", + "name": "min", + "printedName": "min", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryMeasurementUnit(py)unit", + "usr": "c:objc(cs)SentryHttpStatusCodeRange(py)min", "moduleName": "Sentry", "isOpen": true, - "objc_name": "unit", + "objc_name": "min", "declAttributes": [ "ObjC", "Dynamic" @@ -10668,16 +10909,16 @@ "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryMeasurementUnit(im)unit", + "usr": "c:objc(cs)SentryHttpStatusCodeRange(im)min", "moduleName": "Sentry", "isOpen": true, - "objc_name": "unit", + "objc_name": "min", "declAttributes": [ "DiscardableResult", "ObjC", @@ -10689,24 +10930,22 @@ }, { "kind": "Var", - "name": "none", - "printedName": "none", + "name": "max", + "printedName": "max", "children": [ { "kind": "TypeNominal", - "name": "MeasurementUnit", - "printedName": "Sentry.MeasurementUnit", - "usr": "c:objc(cs)SentryMeasurementUnit" + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryMeasurementUnit(cpy)none", + "usr": "c:objc(cs)SentryHttpStatusCodeRange(py)max", "moduleName": "Sentry", - "static": true, "isOpen": true, - "objc_name": "none", + "objc_name": "max", "declAttributes": [ - "NSCopying", "ObjC", "Dynamic" ], @@ -10718,17 +10957,16 @@ "children": [ { "kind": "TypeNominal", - "name": "MeasurementUnit", - "printedName": "Sentry.MeasurementUnit", - "usr": "c:objc(cs)SentryMeasurementUnit" + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryMeasurementUnit(cm)none", + "usr": "c:objc(cs)SentryHttpStatusCodeRange(im)max", "moduleName": "Sentry", - "static": true, "isOpen": true, - "objc_name": "none", + "objc_name": "max", "declAttributes": [ "DiscardableResult", "ObjC", @@ -10737,13 +10975,75 @@ "accessorKind": "get" } ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(min:max:)", + "children": [ + { + "kind": "TypeNominal", + "name": "HttpStatusCodeRange", + "printedName": "Sentry.HttpStatusCodeRange", + "usr": "c:objc(cs)SentryHttpStatusCodeRange" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryHttpStatusCodeRange(im)initWithMin:max:", + "moduleName": "Sentry", + "objc_name": "initWithMin:max:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(statusCode:)", + "children": [ + { + "kind": "TypeNominal", + "name": "HttpStatusCodeRange", + "printedName": "Sentry.HttpStatusCodeRange", + "usr": "c:objc(cs)SentryHttpStatusCodeRange" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryHttpStatusCodeRange(im)initWithStatusCode:", + "moduleName": "Sentry", + "objc_name": "initWithStatusCode:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" } ], "declKind": "Class", - "usr": "c:objc(cs)SentryMeasurementUnit", + "usr": "c:objc(cs)SentryHttpStatusCodeRange", "moduleName": "Sentry", "isOpen": true, - "objc_name": "SentryMeasurementUnit", + "objc_name": "SentryHttpStatusCodeRange", "declAttributes": [ "ObjC", "Dynamic" @@ -10754,12 +11054,6 @@ "ObjectiveC.NSObject" ], "conformances": [ - { - "kind": "Conformance", - "name": "NSCopying", - "printedName": "NSCopying", - "usr": "c:objc(pl)NSCopying" - }, { "kind": "Conformance", "name": "Copyable", @@ -10819,83 +11113,59 @@ }, { "kind": "TypeDecl", - "name": "MeasurementUnitDuration", - "printedName": "MeasurementUnitDuration", + "name": "Level", + "printedName": "Level", "children": [ { - "kind": "Var", - "name": "nanosecond", - "printedName": "nanosecond", + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", "children": [ { "kind": "TypeNominal", - "name": "MeasurementUnitDuration", - "printedName": "Sentry.MeasurementUnitDuration", - "usr": "c:objc(cs)SentryMeasurementUnitDuration" - } - ], - "declKind": "Var", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)nanosecond", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "nanosecond", - "declAttributes": [ - "NSCopying", - "ObjC", - "Dynamic" - ], - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "name": "Optional", + "printedName": "Sentry.Level?", "children": [ { "kind": "TypeNominal", - "name": "MeasurementUnitDuration", - "printedName": "Sentry.MeasurementUnitDuration", - "usr": "c:objc(cs)SentryMeasurementUnitDuration" + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" } ], - "declKind": "Accessor", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)nanosecond", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "nanosecond", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "accessorKind": "get" + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" } - ] + ], + "declKind": "Constructor", + "usr": "s:So24SentryStructuredLogLevelV8rawValueABSgSi_tcfc", + "mangledName": "$sSo24SentryStructuredLogLevelV8rawValueABSgSi_tcfc", + "moduleName": "Sentry", + "implicit": true, + "init_kind": "Designated" }, { "kind": "Var", - "name": "microsecond", - "printedName": "microsecond", + "name": "rawValue", + "printedName": "rawValue", "children": [ { "kind": "TypeNominal", - "name": "MeasurementUnitDuration", - "printedName": "Sentry.MeasurementUnitDuration", - "usr": "c:objc(cs)SentryMeasurementUnitDuration" + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)microsecond", + "usr": "s:So24SentryStructuredLogLevelV8rawValueSivp", + "mangledName": "$sSo24SentryStructuredLogLevelV8rawValueSivp", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "microsecond", - "declAttributes": [ - "NSCopying", - "ObjC", - "Dynamic" - ], + "implicit": true, "accessors": [ { "kind": "Accessor", @@ -10904,46 +11174,403 @@ "children": [ { "kind": "TypeNominal", - "name": "MeasurementUnitDuration", - "printedName": "Sentry.MeasurementUnitDuration", - "usr": "c:objc(cs)SentryMeasurementUnitDuration" + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)microsecond", + "usr": "s:So24SentryStructuredLogLevelV8rawValueSivg", + "mangledName": "$sSo24SentryStructuredLogLevelV8rawValueSivg", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "microsecond", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], + "implicit": true, "accessorKind": "get" } ] }, { - "kind": "Var", - "name": "millisecond", - "printedName": "millisecond", + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", "children": [ { "kind": "TypeNominal", - "name": "MeasurementUnitDuration", - "printedName": "Sentry.MeasurementUnitDuration", - "usr": "c:objc(cs)SentryMeasurementUnitDuration" + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:So24SentryStructuredLogLevelV8RawValuea", + "mangledName": "$sSo24SentryStructuredLogLevelV8RawValuea", + "moduleName": "Sentry", + "implicit": true + }, + { + "kind": "Var", + "name": "trace", + "printedName": "trace", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Level.Type) -> Sentry.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel@SentryStructuredLogLevelTrace", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "debug", + "printedName": "debug", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Level.Type) -> Sentry.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel@SentryStructuredLogLevelDebug", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "info", + "printedName": "info", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Level.Type) -> Sentry.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel@SentryStructuredLogLevelInfo", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "warn", + "printedName": "warn", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Level.Type) -> Sentry.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel@SentryStructuredLogLevelWarn", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "error", + "printedName": "error", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Level.Type) -> Sentry.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel@SentryStructuredLogLevelError", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "fatal", + "printedName": "fatal", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Level.Type) -> Sentry.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel@SentryStructuredLogLevelFatal", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel", + "moduleName": "Sentry", + "objc_name": "SentryStructuredLogLevel", + "declAttributes": [ + "SynthesizedProtocol", + "ObjC", + "SynthesizedProtocol", + "Sendable", + "Dynamic" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.Level.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + }, + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + } + ] + }, + { + "kind": "TypeDecl", + "name": "MeasurementUnit", + "printedName": "MeasurementUnit", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(unit:)", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnit", + "printedName": "Sentry.MeasurementUnit", + "usr": "c:objc(cs)SentryMeasurementUnit" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryMeasurementUnit(im)initWithUnit:", + "moduleName": "Sentry", + "objc_name": "initWithUnit:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "unit", + "printedName": "unit", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)millisecond", + "usr": "c:objc(cs)SentryMeasurementUnit(py)unit", "moduleName": "Sentry", - "static": true, "isOpen": true, - "objc_name": "millisecond", + "objc_name": "unit", "declAttributes": [ - "NSCopying", "ObjC", "Dynamic" ], @@ -10955,17 +11582,16 @@ "children": [ { "kind": "TypeNominal", - "name": "MeasurementUnitDuration", - "printedName": "Sentry.MeasurementUnitDuration", - "usr": "c:objc(cs)SentryMeasurementUnitDuration" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)millisecond", + "usr": "c:objc(cs)SentryMeasurementUnit(im)unit", "moduleName": "Sentry", - "static": true, "isOpen": true, - "objc_name": "millisecond", + "objc_name": "unit", "declAttributes": [ "DiscardableResult", "ObjC", @@ -10977,22 +11603,22 @@ }, { "kind": "Var", - "name": "second", - "printedName": "second", + "name": "none", + "printedName": "none", "children": [ { "kind": "TypeNominal", - "name": "MeasurementUnitDuration", - "printedName": "Sentry.MeasurementUnitDuration", - "usr": "c:objc(cs)SentryMeasurementUnitDuration" + "name": "MeasurementUnit", + "printedName": "Sentry.MeasurementUnit", + "usr": "c:objc(cs)SentryMeasurementUnit" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)second", + "usr": "c:objc(cs)SentryMeasurementUnit(cpy)none", "moduleName": "Sentry", "static": true, "isOpen": true, - "objc_name": "second", + "objc_name": "none", "declAttributes": [ "NSCopying", "ObjC", @@ -11006,17 +11632,17 @@ "children": [ { "kind": "TypeNominal", - "name": "MeasurementUnitDuration", - "printedName": "Sentry.MeasurementUnitDuration", - "usr": "c:objc(cs)SentryMeasurementUnitDuration" + "name": "MeasurementUnit", + "printedName": "Sentry.MeasurementUnit", + "usr": "c:objc(cs)SentryMeasurementUnit" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)second", + "usr": "c:objc(cs)SentryMeasurementUnit(cm)none", "moduleName": "Sentry", "static": true, "isOpen": true, - "objc_name": "second", + "objc_name": "none", "declAttributes": [ "DiscardableResult", "ObjC", @@ -11025,11 +11651,95 @@ "accessorKind": "get" } ] + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryMeasurementUnit", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryMeasurementUnit", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "NSCopying", + "printedName": "NSCopying", + "usr": "c:objc(pl)NSCopying" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "MeasurementUnitDuration", + "printedName": "MeasurementUnitDuration", + "children": [ { "kind": "Var", - "name": "minute", - "printedName": "minute", + "name": "nanosecond", + "printedName": "nanosecond", "children": [ { "kind": "TypeNominal", @@ -11039,11 +11749,11 @@ } ], "declKind": "Var", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)minute", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)nanosecond", "moduleName": "Sentry", "static": true, "isOpen": true, - "objc_name": "minute", + "objc_name": "nanosecond", "declAttributes": [ "NSCopying", "ObjC", @@ -11063,11 +11773,11 @@ } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)minute", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)nanosecond", "moduleName": "Sentry", "static": true, "isOpen": true, - "objc_name": "minute", + "objc_name": "nanosecond", "declAttributes": [ "DiscardableResult", "ObjC", @@ -11079,8 +11789,8 @@ }, { "kind": "Var", - "name": "hour", - "printedName": "hour", + "name": "microsecond", + "printedName": "microsecond", "children": [ { "kind": "TypeNominal", @@ -11090,11 +11800,11 @@ } ], "declKind": "Var", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)hour", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)microsecond", "moduleName": "Sentry", "static": true, "isOpen": true, - "objc_name": "hour", + "objc_name": "microsecond", "declAttributes": [ "NSCopying", "ObjC", @@ -11114,11 +11824,11 @@ } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)hour", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)microsecond", "moduleName": "Sentry", "static": true, "isOpen": true, - "objc_name": "hour", + "objc_name": "microsecond", "declAttributes": [ "DiscardableResult", "ObjC", @@ -11130,8 +11840,8 @@ }, { "kind": "Var", - "name": "day", - "printedName": "day", + "name": "millisecond", + "printedName": "millisecond", "children": [ { "kind": "TypeNominal", @@ -11141,11 +11851,11 @@ } ], "declKind": "Var", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)day", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)millisecond", "moduleName": "Sentry", "static": true, "isOpen": true, - "objc_name": "day", + "objc_name": "millisecond", "declAttributes": [ "NSCopying", "ObjC", @@ -11165,11 +11875,11 @@ } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)day", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)millisecond", "moduleName": "Sentry", "static": true, "isOpen": true, - "objc_name": "day", + "objc_name": "millisecond", "declAttributes": [ "DiscardableResult", "ObjC", @@ -11181,8 +11891,8 @@ }, { "kind": "Var", - "name": "week", - "printedName": "week", + "name": "second", + "printedName": "second", "children": [ { "kind": "TypeNominal", @@ -11192,11 +11902,11 @@ } ], "declKind": "Var", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)week", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)second", "moduleName": "Sentry", "static": true, "isOpen": true, - "objc_name": "week", + "objc_name": "second", "declAttributes": [ "NSCopying", "ObjC", @@ -11216,11 +11926,11 @@ } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)week", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)second", "moduleName": "Sentry", "static": true, "isOpen": true, - "objc_name": "week", + "objc_name": "second", "declAttributes": [ "DiscardableResult", "ObjC", @@ -11231,31 +11941,235 @@ ] }, { - "kind": "Constructor", - "name": "init", - "printedName": "init(unit:)", + "kind": "Var", + "name": "minute", + "printedName": "minute", "children": [ { "kind": "TypeNominal", "name": "MeasurementUnitDuration", "printedName": "Sentry.MeasurementUnitDuration", "usr": "c:objc(cs)SentryMeasurementUnitDuration" - }, - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" } ], - "declKind": "Constructor", - "usr": "c:objc(cs)SentryMeasurementUnit(im)initWithUnit:", + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)minute", "moduleName": "Sentry", - "overriding": true, - "implicit": true, - "objc_name": "initWithUnit:", + "static": true, + "isOpen": true, + "objc_name": "minute", "declAttributes": [ - "Override", + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)minute", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "minute", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "hour", + "printedName": "hour", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)hour", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "hour", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)hour", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "hour", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "day", + "printedName": "day", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)day", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "day", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)day", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "day", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "week", + "printedName": "week", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)week", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "week", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)week", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "week", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(unit:)", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryMeasurementUnit(im)initWithUnit:", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "initWithUnit:", + "declAttributes": [ + "Override", "ObjC", "Dynamic" ], @@ -15658,38 +16572,38 @@ }, { "kind": "Var", - "name": "beforeBreadcrumb", - "printedName": "beforeBreadcrumb", + "name": "beforeSendLog", + "printedName": "beforeSendLog", "children": [ { "kind": "TypeNominal", "name": "Optional", - "printedName": "((Sentry.Breadcrumb) -> Sentry.Breadcrumb?)?", + "printedName": "((Sentry.SentryLog) -> Sentry.SentryLog?)?", "children": [ { "kind": "TypeFunc", "name": "Function", - "printedName": "(Sentry.Breadcrumb) -> Sentry.Breadcrumb?", + "printedName": "(Sentry.SentryLog) -> Sentry.SentryLog?", "children": [ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Sentry.Breadcrumb?", + "printedName": "Sentry.SentryLog?", "children": [ { "kind": "TypeNominal", - "name": "Breadcrumb", - "printedName": "Sentry.Breadcrumb", - "usr": "c:objc(cs)SentryBreadcrumb" + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" } ], "usr": "s:Sq" }, { "kind": "TypeNominal", - "name": "Breadcrumb", - "printedName": "Sentry.Breadcrumb", - "usr": "c:objc(cs)SentryBreadcrumb" + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" } ] } @@ -15698,10 +16612,10 @@ } ], "declKind": "Var", - "usr": "c:objc(cs)SentryOptions(py)beforeBreadcrumb", + "usr": "c:objc(cs)SentryOptions(py)beforeSendLog", "moduleName": "Sentry", "isOpen": true, - "objc_name": "beforeBreadcrumb", + "objc_name": "beforeSendLog", "declAttributes": [ "ObjC", "Dynamic" @@ -15715,32 +16629,32 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "((Sentry.Breadcrumb) -> Sentry.Breadcrumb?)?", + "printedName": "((Sentry.SentryLog) -> Sentry.SentryLog?)?", "children": [ { "kind": "TypeFunc", "name": "Function", - "printedName": "(Sentry.Breadcrumb) -> Sentry.Breadcrumb?", + "printedName": "(Sentry.SentryLog) -> Sentry.SentryLog?", "children": [ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Sentry.Breadcrumb?", + "printedName": "Sentry.SentryLog?", "children": [ { "kind": "TypeNominal", - "name": "Breadcrumb", - "printedName": "Sentry.Breadcrumb", - "usr": "c:objc(cs)SentryBreadcrumb" + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" } ], "usr": "s:Sq" }, { "kind": "TypeNominal", - "name": "Breadcrumb", - "printedName": "Sentry.Breadcrumb", - "usr": "c:objc(cs)SentryBreadcrumb" + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" } ] } @@ -15749,10 +16663,10 @@ } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryOptions(im)beforeBreadcrumb", + "usr": "c:objc(cs)SentryOptions(im)beforeSendLog", "moduleName": "Sentry", "isOpen": true, - "objc_name": "beforeBreadcrumb", + "objc_name": "beforeSendLog", "declAttributes": [ "DiscardableResult", "ObjC", @@ -15780,32 +16694,32 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "((Sentry.Breadcrumb) -> Sentry.Breadcrumb?)?", + "printedName": "((Sentry.SentryLog) -> Sentry.SentryLog?)?", "children": [ { "kind": "TypeFunc", "name": "Function", - "printedName": "(Sentry.Breadcrumb) -> Sentry.Breadcrumb?", + "printedName": "(Sentry.SentryLog) -> Sentry.SentryLog?", "children": [ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Sentry.Breadcrumb?", + "printedName": "Sentry.SentryLog?", "children": [ { "kind": "TypeNominal", - "name": "Breadcrumb", - "printedName": "Sentry.Breadcrumb", - "usr": "c:objc(cs)SentryBreadcrumb" + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" } ], "usr": "s:Sq" }, { "kind": "TypeNominal", - "name": "Breadcrumb", - "printedName": "Sentry.Breadcrumb", - "usr": "c:objc(cs)SentryBreadcrumb" + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" } ] } @@ -15814,10 +16728,10 @@ } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryOptions(im)setBeforeBreadcrumb:", + "usr": "c:objc(cs)SentryOptions(im)setBeforeSendLog:", "moduleName": "Sentry", "isOpen": true, - "objc_name": "setBeforeBreadcrumb:", + "objc_name": "setBeforeSendLog:", "declAttributes": [ "ObjC", "Dynamic" @@ -15828,30 +16742,38 @@ }, { "kind": "Var", - "name": "beforeCaptureScreenshot", - "printedName": "beforeCaptureScreenshot", + "name": "beforeBreadcrumb", + "printedName": "beforeBreadcrumb", "children": [ { "kind": "TypeNominal", "name": "Optional", - "printedName": "((Sentry.Event) -> Swift.Bool)?", + "printedName": "((Sentry.Breadcrumb) -> Sentry.Breadcrumb?)?", "children": [ { "kind": "TypeFunc", "name": "Function", - "printedName": "(Sentry.Event) -> Swift.Bool", + "printedName": "(Sentry.Breadcrumb) -> Sentry.Breadcrumb?", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "Optional", + "printedName": "Sentry.Breadcrumb?", + "children": [ + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "usr": "s:Sq" }, { "kind": "TypeNominal", - "name": "Event", - "printedName": "Sentry.Event", - "usr": "c:objc(cs)SentryEvent" + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" } ] } @@ -15860,10 +16782,10 @@ } ], "declKind": "Var", - "usr": "c:objc(cs)SentryOptions(py)beforeCaptureScreenshot", + "usr": "c:objc(cs)SentryOptions(py)beforeBreadcrumb", "moduleName": "Sentry", "isOpen": true, - "objc_name": "beforeCaptureScreenshot", + "objc_name": "beforeBreadcrumb", "declAttributes": [ "ObjC", "Dynamic" @@ -15877,24 +16799,32 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "((Sentry.Event) -> Swift.Bool)?", + "printedName": "((Sentry.Breadcrumb) -> Sentry.Breadcrumb?)?", "children": [ { "kind": "TypeFunc", "name": "Function", - "printedName": "(Sentry.Event) -> Swift.Bool", + "printedName": "(Sentry.Breadcrumb) -> Sentry.Breadcrumb?", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "Optional", + "printedName": "Sentry.Breadcrumb?", + "children": [ + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "usr": "s:Sq" }, { "kind": "TypeNominal", - "name": "Event", - "printedName": "Sentry.Event", - "usr": "c:objc(cs)SentryEvent" + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" } ] } @@ -15903,10 +16833,164 @@ } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryOptions(im)beforeCaptureScreenshot", + "usr": "c:objc(cs)SentryOptions(im)beforeBreadcrumb", "moduleName": "Sentry", "isOpen": true, - "objc_name": "beforeCaptureScreenshot", + "objc_name": "beforeBreadcrumb", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Breadcrumb) -> Sentry.Breadcrumb?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Breadcrumb) -> Sentry.Breadcrumb?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Breadcrumb?", + "children": [ + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setBeforeBreadcrumb:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setBeforeBreadcrumb:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "beforeCaptureScreenshot", + "printedName": "beforeCaptureScreenshot", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Swift.Bool)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Bool", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)beforeCaptureScreenshot", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeCaptureScreenshot", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Swift.Bool)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Bool", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)beforeCaptureScreenshot", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeCaptureScreenshot", "declAttributes": [ "DiscardableResult", "ObjC", @@ -16313,9 +17397,11 @@ "declKind": "Var", "usr": "c:objc(cs)SentryOptions(py)integrations", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "integrations", "declAttributes": [ + "Available", "ObjC", "Dynamic" ], @@ -16351,10 +17437,12 @@ "declKind": "Accessor", "usr": "c:objc(cs)SentryOptions(im)integrations", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "integrations", "declAttributes": [ "DiscardableResult", + "Available", "ObjC", "Dynamic" ], @@ -16403,9 +17491,11 @@ "declKind": "Accessor", "usr": "c:objc(cs)SentryOptions(im)setIntegrations:", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "setIntegrations:", "declAttributes": [ + "Available", "ObjC", "Dynamic" ], @@ -17672,6 +18762,89 @@ } ] }, + { + "kind": "Var", + "name": "screenshot", + "printedName": "screenshot", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryViewScreenshotOptions", + "printedName": "Sentry.SentryViewScreenshotOptions", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)screenshot", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "screenshot", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryViewScreenshotOptions", + "printedName": "Sentry.SentryViewScreenshotOptions", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)screenshot", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "screenshot", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryViewScreenshotOptions", + "printedName": "Sentry.SentryViewScreenshotOptions", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setScreenshot:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setScreenshot:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, { "kind": "Var", "name": "attachViewHierarchy", @@ -19649,9 +20822,11 @@ "declKind": "Var", "usr": "c:objc(cs)SentryOptions(py)enableAppLaunchProfiling", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "enableAppLaunchProfiling", "declAttributes": [ + "Available", "ObjC", "Dynamic" ], @@ -19671,10 +20846,12 @@ "declKind": "Accessor", "usr": "c:objc(cs)SentryOptions(im)enableAppLaunchProfiling", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "enableAppLaunchProfiling", "declAttributes": [ "DiscardableResult", + "Available", "ObjC", "Dynamic" ], @@ -19707,9 +20884,11 @@ "declKind": "Accessor", "usr": "c:objc(cs)SentryOptions(im)setEnableAppLaunchProfiling:", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "setEnableAppLaunchProfiling:", "declAttributes": [ + "Available", "ObjC", "Dynamic" ], @@ -19740,9 +20919,11 @@ "declKind": "Var", "usr": "c:objc(cs)SentryOptions(py)profilesSampleRate", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "profilesSampleRate", "declAttributes": [ + "Available", "ObjC", "Dynamic" ], @@ -19770,10 +20951,12 @@ "declKind": "Accessor", "usr": "c:objc(cs)SentryOptions(im)profilesSampleRate", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "profilesSampleRate", "declAttributes": [ "DiscardableResult", + "Available", "ObjC", "Dynamic" ], @@ -19814,9 +20997,11 @@ "declKind": "Accessor", "usr": "c:objc(cs)SentryOptions(im)setProfilesSampleRate:", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "setProfilesSampleRate:", "declAttributes": [ + "Available", "ObjC", "Dynamic" ], @@ -19868,9 +21053,11 @@ "declKind": "Var", "usr": "c:objc(cs)SentryOptions(py)profilesSampler", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "profilesSampler", "declAttributes": [ + "Available", "ObjC", "Dynamic" ], @@ -19919,10 +21106,12 @@ "declKind": "Accessor", "usr": "c:objc(cs)SentryOptions(im)profilesSampler", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "profilesSampler", "declAttributes": [ "DiscardableResult", + "Available", "ObjC", "Dynamic" ], @@ -19984,9 +21173,11 @@ "declKind": "Accessor", "usr": "c:objc(cs)SentryOptions(im)setProfilesSampler:", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "setProfilesSampler:", "declAttributes": [ + "Available", "ObjC", "Dynamic" ], @@ -20009,9 +21200,11 @@ "declKind": "Var", "usr": "c:objc(cs)SentryOptions(py)isProfilingEnabled", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "isProfilingEnabled", "declAttributes": [ + "Available", "ObjC", "Dynamic" ], @@ -20031,10 +21224,12 @@ "declKind": "Accessor", "usr": "c:objc(cs)SentryOptions(im)isProfilingEnabled", "moduleName": "Sentry", + "deprecated": true, "isOpen": true, "objc_name": "isProfilingEnabled", "declAttributes": [ "DiscardableResult", + "Available", "ObjC", "Dynamic" ], @@ -24269,6 +25464,43 @@ "usr": "c:@T@SentryBeforeSendEventCallback", "moduleName": "Sentry" }, + { + "kind": "TypeAlias", + "name": "SentryBeforeSendLogCallback", + "printedName": "SentryBeforeSendLogCallback", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog) -> Sentry.SentryLog?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryLog?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryBeforeSendLogCallback", + "moduleName": "Sentry" + }, { "kind": "TypeAlias", "name": "SentryBeforeSendSpanCallback", @@ -26963,10 +28195,8 @@ "usr": "c:objc(cs)SentryFeedbackAPI", "moduleName": "Sentry", "isOpen": true, - "intro_iOS": "13.0", "objc_name": "SentryFeedbackAPI", "declAttributes": [ - "Available", "ObjC", "Dynamic" ], @@ -32074,97 +33304,59 @@ }, { "kind": "TypeDecl", - "name": "SentrySDK", - "printedName": "SentrySDK", + "name": "SentrySampleDecision", + "printedName": "SentrySampleDecision", "children": [ { - "kind": "Var", - "name": "span", - "printedName": "span", + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", "children": [ { "kind": "TypeNominal", "name": "Optional", - "printedName": "(any Sentry.Span)?", + "printedName": "Sentry.SentrySampleDecision?", "children": [ { "kind": "TypeNominal", - "name": "Span", - "printedName": "any Sentry.Span", - "usr": "c:objc(pl)SentrySpan" + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" } ], "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" } ], - "declKind": "Var", - "usr": "c:objc(cs)SentrySDK(cpy)span", + "declKind": "Constructor", + "usr": "s:So20SentrySampleDecisionV8rawValueABSgSu_tcfc", + "mangledName": "$sSo20SentrySampleDecisionV8rawValueABSgSu_tcfc", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "span", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "(any Sentry.Span)?", - "children": [ - { - "kind": "TypeNominal", - "name": "Span", - "printedName": "any Sentry.Span", - "usr": "c:objc(pl)SentrySpan" - } - ], - "usr": "s:Sq" - } - ], - "declKind": "Accessor", - "usr": "c:objc(cs)SentrySDK(cm)span", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "span", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "accessorKind": "get" - } - ] + "implicit": true, + "init_kind": "Designated" }, { "kind": "Var", - "name": "isEnabled", - "printedName": "isEnabled", + "name": "rawValue", + "printedName": "rawValue", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" } ], "declKind": "Var", - "usr": "c:objc(cs)SentrySDK(cpy)isEnabled", + "usr": "s:So20SentrySampleDecisionV8rawValueSuvp", + "mangledName": "$sSo20SentrySampleDecisionV8rawValueSuvp", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "isEnabled", - "declAttributes": [ - "ObjC", - "Dynamic" - ], + "implicit": true, "accessors": [ { "kind": "Accessor", @@ -32173,456 +33365,653 @@ "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentrySDK(cm)isEnabled", + "usr": "s:So20SentrySampleDecisionV8rawValueSuvg", + "mangledName": "$sSo20SentrySampleDecisionV8rawValueSuvg", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "isEnabled", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], + "implicit": true, "accessorKind": "get" } ] }, { - "kind": "Var", - "name": "replay", - "printedName": "replay", + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", "children": [ { "kind": "TypeNominal", - "name": "SentryReplayApi", - "printedName": "Sentry.SentryReplayApi", - "usr": "c:objc(cs)SentryReplayApi" + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" } ], - "declKind": "Var", - "usr": "c:objc(cs)SentrySDK(cpy)replay", + "declKind": "TypeAlias", + "usr": "s:So20SentrySampleDecisionV8RawValuea", + "mangledName": "$sSo20SentrySampleDecisionV8RawValuea", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "replay", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "accessors": [ + "implicit": true + }, + { + "kind": "Var", + "name": "undecided", + "printedName": "undecided", + "children": [ { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySampleDecision.Type) -> Sentry.SentrySampleDecision", "children": [ { "kind": "TypeNominal", - "name": "SentryReplayApi", - "printedName": "Sentry.SentryReplayApi", - "usr": "c:objc(cs)SentryReplayApi" + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySampleDecision.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ] } - ], - "declKind": "Accessor", - "usr": "c:objc(cs)SentrySDK(cm)replay", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "replay", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "accessorKind": "get" + ] } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySampleDecision@kSentrySampleDecisionUndecided", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" ] }, { - "kind": "Function", - "name": "start", - "printedName": "start(options:)", + "kind": "Var", + "name": "yes", + "printedName": "yes", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySampleDecision.Type) -> Sentry.SentrySampleDecision", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySampleDecision.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ] } ] - }, - { - "kind": "TypeNominal", - "name": "Options", - "printedName": "Sentry.Options", - "usr": "c:objc(cs)SentryOptions" } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)startWithOptions:", + "declKind": "EnumElement", + "usr": "c:@E@SentrySampleDecision@kSentrySampleDecisionYes", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "startWithOptions:", "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "start", - "printedName": "start(configureOptions:)", + "kind": "Var", + "name": "no", + "printedName": "no", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySampleDecision.Type) -> Sentry.SentrySampleDecision", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySampleDecision.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ] } ] - }, + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySampleDecision@kSentrySampleDecisionNo", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + } + ], + "declKind": "Enum", + "usr": "c:@E@SentrySampleDecision", + "moduleName": "Sentry", + "objc_name": "SentrySampleDecision", + "declAttributes": [ + "SynthesizedProtocol", + "ObjC", + "SynthesizedProtocol", + "Sendable", + "Dynamic" + ], + "enumRawTypeName": "UInt", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.Options) -> Swift.Void", + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", "children": [ { "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "name": "RawValue", + "printedName": "Sentry.SentrySampleDecision.RawValue", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" } ] - }, - { - "kind": "TypeNominal", - "name": "Options", - "printedName": "Sentry.Options", - "usr": "c:objc(cs)SentryOptions" } ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)startWithConfigureOptions:", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "startWithConfigureOptions:", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "usr": "s:SY", + "mangledName": "$sSY" + }, + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentrySerializable", + "printedName": "SentrySerializable", + "children": [ { "kind": "Function", - "name": "capture", - "printedName": "capture(event:)", + "name": "serialize", + "printedName": "serialize()", "children": [ { "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - }, - { - "kind": "TypeNominal", - "name": "Event", - "printedName": "Sentry.Event", - "usr": "c:objc(cs)SentryEvent" + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" } ], "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureEvent:", + "usr": "c:objc(pl)SentrySerializable(im)serialize", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "captureEvent:", + "genericSig": "", + "protocolReq": true, + "objc_name": "serialize", "declAttributes": [ "DiscardableResult", "ObjC", "Dynamic" ], + "reqNewWitnessTableEntry": true, "funcSelfKind": "NonMutating" + } + ], + "declKind": "Protocol", + "usr": "c:objc(pl)SentrySerializable", + "moduleName": "Sentry", + "genericSig": "", + "objc_name": "SentrySerializable", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" }, { - "kind": "Function", - "name": "capture", - "printedName": "capture(event:scope:)", + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentrySessionStatus", + "printedName": "SentrySessionStatus", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", "children": [ { "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - }, - { - "kind": "TypeNominal", - "name": "Event", - "printedName": "Sentry.Event", - "usr": "c:objc(cs)SentryEvent" + "name": "Optional", + "printedName": "Sentry.SentrySessionStatus?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + } + ], + "usr": "s:Sq" }, { "kind": "TypeNominal", - "name": "Scope", - "printedName": "Sentry.Scope", - "usr": "c:objc(cs)SentryScope" + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureEvent:withScope:", + "declKind": "Constructor", + "usr": "s:So19SentrySessionStatusV8rawValueABSgSu_tcfc", + "mangledName": "$sSo19SentrySessionStatusV8rawValueABSgSu_tcfc", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "captureEvent:withScope:", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "implicit": true, + "init_kind": "Designated" }, { - "kind": "Function", - "name": "capture", - "printedName": "capture(event:block:)", + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", "children": [ { "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - }, - { - "kind": "TypeNominal", - "name": "Event", - "printedName": "Sentry.Event", - "usr": "c:objc(cs)SentryEvent" - }, + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Var", + "usr": "s:So19SentrySessionStatusV8rawValueSuvp", + "mangledName": "$sSo19SentrySessionStatusV8rawValueSuvp", + "moduleName": "Sentry", + "implicit": true, + "accessors": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.Scope) -> Swift.Void", + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Accessor", + "usr": "s:So19SentrySessionStatusV8rawValueSuvg", + "mangledName": "$sSo19SentrySessionStatusV8rawValueSuvg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "TypeAlias", + "usr": "s:So19SentrySessionStatusV8RawValuea", + "mangledName": "$sSo19SentrySessionStatusV8RawValuea", + "moduleName": "Sentry", + "implicit": true + }, + { + "kind": "Var", + "name": "ok", + "printedName": "ok", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySessionStatus.Type) -> Sentry.SentrySessionStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySessionStatus.Type", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" } ] - }, - { - "kind": "TypeNominal", - "name": "Scope", - "printedName": "Sentry.Scope", - "usr": "c:objc(cs)SentryScope" } ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureEvent:withScopeBlock:", + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentrySessionStatus@SentrySessionStatusOk", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "captureEvent:withScopeBlock:", "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "startTransaction", - "printedName": "startTransaction(name:operation:)", + "kind": "Var", + "name": "exited", + "printedName": "exited", "children": [ { - "kind": "TypeNominal", - "name": "Span", - "printedName": "any Sentry.Span", - "usr": "c:objc(pl)SentrySpan" - }, - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySessionStatus.Type) -> Sentry.SentrySessionStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySessionStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + } + ] + } + ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)startTransactionWithName:operation:", + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentrySessionStatus@SentrySessionStatusExited", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "startTransactionWithName:operation:", "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "startTransaction", - "printedName": "startTransaction(name:operation:bindToScope:)", + "kind": "Var", + "name": "crashed", + "printedName": "crashed", "children": [ { - "kind": "TypeNominal", - "name": "Span", - "printedName": "any Sentry.Span", - "usr": "c:objc(pl)SentrySpan" - }, - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySessionStatus.Type) -> Sentry.SentrySessionStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySessionStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + } + ] + } + ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)startTransactionWithName:operation:bindToScope:", + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentrySessionStatus@SentrySessionStatusCrashed", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "startTransactionWithName:operation:bindToScope:", "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "startTransaction", - "printedName": "startTransaction(transactionContext:)", + "kind": "Var", + "name": "abnormal", + "printedName": "abnormal", "children": [ { - "kind": "TypeNominal", - "name": "Span", - "printedName": "any Sentry.Span", - "usr": "c:objc(pl)SentrySpan" - }, - { - "kind": "TypeNominal", - "name": "TransactionContext", - "printedName": "Sentry.TransactionContext", - "usr": "c:objc(cs)SentryTransactionContext" + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySessionStatus.Type) -> Sentry.SentrySessionStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySessionStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + } + ] + } + ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)startTransactionWithContext:", + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentrySessionStatus@SentrySessionStatusAbnormal", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "startTransactionWithContext:", "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentrySessionStatus", + "moduleName": "Sentry", + "objc_name": "SentrySessionStatus", + "declAttributes": [ + "SynthesizedProtocol", + "ObjC", + "SynthesizedProtocol", + "Sendable", + "Dynamic" + ], + "enumRawTypeName": "UInt", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" }, { - "kind": "Function", - "name": "startTransaction", - "printedName": "startTransaction(transactionContext:bindToScope:)", + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", "children": [ { - "kind": "TypeNominal", - "name": "Span", - "printedName": "any Sentry.Span", - "usr": "c:objc(pl)SentrySpan" - }, - { - "kind": "TypeNominal", - "name": "TransactionContext", - "printedName": "Sentry.TransactionContext", - "usr": "c:objc(cs)SentryTransactionContext" - }, - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentrySessionStatus.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ] + } + ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)startTransactionWithContext:bindToScope:", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "startTransactionWithContext:bindToScope:", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "usr": "s:SY", + "mangledName": "$sSY" }, { - "kind": "Function", - "name": "startTransaction", - "printedName": "startTransaction(transactionContext:bindToScope:customSamplingContext:)", + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + } + ] + }, + { + "kind": "TypeAlias", + "name": "SentryShouldQueueEvent", + "printedName": "SentryShouldQueueEvent", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Foundation.HTTPURLResponse?, (any Swift.Error)?) -> Swift.Bool", "children": [ - { - "kind": "TypeNominal", - "name": "Span", - "printedName": "any Sentry.Span", - "usr": "c:objc(pl)SentrySpan" - }, - { - "kind": "TypeNominal", - "name": "TransactionContext", - "printedName": "Sentry.TransactionContext", - "usr": "c:objc(cs)SentryTransactionContext" - }, { "kind": "TypeNominal", "name": "Bool", @@ -32631,1415 +34020,881 @@ }, { "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Any]", + "name": "Tuple", + "printedName": "(Foundation.HTTPURLResponse?, (any Swift.Error)?)", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Optional", + "printedName": "Foundation.HTTPURLResponse?", + "children": [ + { + "kind": "TypeNominal", + "name": "HTTPURLResponse", + "printedName": "Foundation.HTTPURLResponse", + "usr": "c:objc(cs)NSHTTPURLResponse" + } + ], + "usr": "s:Sq" }, { "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "Any" + "name": "Optional", + "printedName": "(any Swift.Error)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "usr": "s:Sq" } - ], - "usr": "s:SD" + ] } - ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)startTransactionWithContext:bindToScope:customSamplingContext:", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "startTransactionWithContext:bindToScope:customSamplingContext:", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" - }, + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryShouldQueueEvent", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "SentrySpanCallback", + "printedName": "SentrySpanCallback", + "children": [ { - "kind": "Function", - "name": "startTransaction", - "printedName": "startTransaction(transactionContext:customSamplingContext:)", + "kind": "TypeFunc", + "name": "Function", + "printedName": "((any Sentry.Span)?) -> Swift.Void", "children": [ { - "kind": "TypeNominal", - "name": "Span", - "printedName": "any Sentry.Span", - "usr": "c:objc(pl)SentrySpan" - }, - { - "kind": "TypeNominal", - "name": "TransactionContext", - "printedName": "Sentry.TransactionContext", - "usr": "c:objc(cs)SentryTransactionContext" + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] }, { "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Any]", + "name": "Optional", + "printedName": "(any Sentry.Span)?", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "Any" + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" } ], - "usr": "s:SD" + "usr": "s:Sq" } - ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)startTransactionWithContext:customSamplingContext:", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "startTransactionWithContext:customSamplingContext:", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" - }, + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentrySpanCallback", + "moduleName": "Sentry" + }, + { + "kind": "TypeDecl", + "name": "SentrySpanStatus", + "printedName": "SentrySpanStatus", + "children": [ { - "kind": "Function", - "name": "capture", - "printedName": "capture(error:)", + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", "children": [ { "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" + "name": "Optional", + "printedName": "Sentry.SentrySpanStatus?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ], + "usr": "s:Sq" }, { "kind": "TypeNominal", - "name": "Error", - "printedName": "any Swift.Error", - "usr": "s:s5ErrorP" + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureError:", + "declKind": "Constructor", + "usr": "s:So16SentrySpanStatusV8rawValueABSgSu_tcfc", + "mangledName": "$sSo16SentrySpanStatusV8rawValueABSgSu_tcfc", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "captureError:", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "implicit": true, + "init_kind": "Designated" }, { - "kind": "Function", - "name": "capture", - "printedName": "capture(error:scope:)", + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", "children": [ { "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - }, + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Var", + "usr": "s:So16SentrySpanStatusV8rawValueSuvp", + "mangledName": "$sSo16SentrySpanStatusV8rawValueSuvp", + "moduleName": "Sentry", + "implicit": true, + "accessors": [ { - "kind": "TypeNominal", - "name": "Error", - "printedName": "any Swift.Error", - "usr": "s:s5ErrorP" - }, + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Accessor", + "usr": "s:So16SentrySpanStatusV8rawValueSuvg", + "mangledName": "$sSo16SentrySpanStatusV8rawValueSuvg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ { "kind": "TypeNominal", - "name": "Scope", - "printedName": "Sentry.Scope", - "usr": "c:objc(cs)SentryScope" + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureError:withScope:", + "declKind": "TypeAlias", + "usr": "s:So16SentrySpanStatusV8RawValuea", + "mangledName": "$sSo16SentrySpanStatusV8RawValuea", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "captureError:withScope:", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "implicit": true }, { - "kind": "Function", - "name": "capture", - "printedName": "capture(error:block:)", + "kind": "Var", + "name": "undefined", + "printedName": "undefined", "children": [ - { - "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - }, - { - "kind": "TypeNominal", - "name": "Error", - "printedName": "any Swift.Error", - "usr": "s:s5ErrorP" - }, { "kind": "TypeFunc", "name": "Function", - "printedName": "(Sentry.Scope) -> Swift.Void", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" } ] - }, - { - "kind": "TypeNominal", - "name": "Scope", - "printedName": "Sentry.Scope", - "usr": "c:objc(cs)SentryScope" } ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureError:withScopeBlock:", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUndefined", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "captureError:withScopeBlock:", "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "capture", - "printedName": "capture(exception:)", + "kind": "Var", + "name": "ok", + "printedName": "ok", "children": [ { - "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - }, - { - "kind": "TypeNominal", - "name": "NSException", - "printedName": "Foundation.NSException", - "usr": "c:objc(cs)NSException" + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureException:", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusOk", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "captureException:", "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "capture", - "printedName": "capture(exception:scope:)", + "kind": "Var", + "name": "deadlineExceeded", + "printedName": "deadlineExceeded", "children": [ { - "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - }, - { - "kind": "TypeNominal", - "name": "NSException", - "printedName": "Foundation.NSException", - "usr": "c:objc(cs)NSException" - }, - { - "kind": "TypeNominal", - "name": "Scope", - "printedName": "Sentry.Scope", - "usr": "c:objc(cs)SentryScope" + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureException:withScope:", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusDeadlineExceeded", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "captureException:withScope:", "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "capture", - "printedName": "capture(exception:block:)", + "kind": "Var", + "name": "unauthenticated", + "printedName": "unauthenticated", "children": [ - { - "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - }, - { - "kind": "TypeNominal", - "name": "NSException", - "printedName": "Foundation.NSException", - "usr": "c:objc(cs)NSException" - }, { "kind": "TypeFunc", "name": "Function", - "printedName": "(Sentry.Scope) -> Swift.Void", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" } ] - }, - { - "kind": "TypeNominal", - "name": "Scope", - "printedName": "Sentry.Scope", - "usr": "c:objc(cs)SentryScope" } ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureException:withScopeBlock:", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUnauthenticated", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "captureException:withScopeBlock:", "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "capture", - "printedName": "capture(message:)", + "kind": "Var", + "name": "permissionDenied", + "printedName": "permissionDenied", "children": [ { - "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - }, - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureMessage:", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusPermissionDenied", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "captureMessage:", "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "capture", - "printedName": "capture(message:scope:)", + "kind": "Var", + "name": "notFound", + "printedName": "notFound", "children": [ { - "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - }, - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "Scope", - "printedName": "Sentry.Scope", - "usr": "c:objc(cs)SentryScope" + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureMessage:withScope:", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusNotFound", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "captureMessage:withScope:", "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "capture", - "printedName": "capture(message:block:)", + "kind": "Var", + "name": "resourceExhausted", + "printedName": "resourceExhausted", "children": [ - { - "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - }, - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, { "kind": "TypeFunc", "name": "Function", - "printedName": "(Sentry.Scope) -> Swift.Void", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" } ] - }, - { - "kind": "TypeNominal", - "name": "Scope", - "printedName": "Sentry.Scope", - "usr": "c:objc(cs)SentryScope" } ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureMessage:withScopeBlock:", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusResourceExhausted", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "captureMessage:withScopeBlock:", "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "capture", - "printedName": "capture(userFeedback:)", + "kind": "Var", + "name": "invalidArgument", + "printedName": "invalidArgument", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] } ] - }, - { - "kind": "TypeNominal", - "name": "UserFeedback", - "printedName": "Sentry.UserFeedback", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback" } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureUserFeedback:", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusInvalidArgument", "moduleName": "Sentry", - "static": true, - "deprecated": true, - "isOpen": true, - "objc_name": "captureUserFeedback:", "declAttributes": [ - "Available", - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "capture", - "printedName": "capture(feedback:)", + "kind": "Var", + "name": "unimplemented", + "printedName": "unimplemented", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] } ] - }, - { - "kind": "TypeNominal", - "name": "SentryFeedback", - "printedName": "Sentry.SentryFeedback", - "usr": "c:@M@Sentry@objc(cs)SentryFeedback" } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)captureFeedback:", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUnimplemented", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "captureFeedback:", "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { "kind": "Var", - "name": "feedback", - "printedName": "feedback", + "name": "unavailable", + "printedName": "unavailable", "children": [ { - "kind": "TypeNominal", - "name": "SentryFeedbackAPI", - "printedName": "Sentry.SentryFeedbackAPI", - "usr": "c:objc(cs)SentryFeedbackAPI" - } - ], - "declKind": "Var", - "usr": "c:objc(cs)SentrySDK(cpy)feedback", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "intro_iOS": "13.0", - "objc_name": "feedback", - "declAttributes": [ - "Available", - "ObjC", - "Dynamic" - ], - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { "kind": "TypeNominal", - "name": "SentryFeedbackAPI", - "printedName": "Sentry.SentryFeedbackAPI", - "usr": "c:objc(cs)SentryFeedbackAPI" + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] } - ], - "declKind": "Accessor", - "usr": "c:objc(cs)SentrySDK(cm)feedback", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "intro_iOS": "13.0", - "objc_name": "feedback", - "declAttributes": [ - "DiscardableResult", - "Available", - "ObjC", - "Dynamic" - ], - "accessorKind": "get" + ] } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUnavailable", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" ] }, { - "kind": "Function", - "name": "addBreadcrumb", - "printedName": "addBreadcrumb(_:)", + "kind": "Var", + "name": "internalError", + "printedName": "internalError", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] } ] - }, - { - "kind": "TypeNominal", - "name": "Breadcrumb", - "printedName": "Sentry.Breadcrumb", - "usr": "c:objc(cs)SentryBreadcrumb" } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)addBreadcrumb:", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusInternalError", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "addBreadcrumb:", "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "configureScope", - "printedName": "configureScope(_:)", + "kind": "Var", + "name": "unknownError", + "printedName": "unknownError", "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, { "kind": "TypeFunc", "name": "Function", - "printedName": "(Sentry.Scope) -> Swift.Void", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" } ] - }, - { - "kind": "TypeNominal", - "name": "Scope", - "printedName": "Sentry.Scope", - "usr": "c:objc(cs)SentryScope" } ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)configureScope:", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUnknownError", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "configureScope:", "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { "kind": "Var", - "name": "crashedLastRun", - "printedName": "crashedLastRun", + "name": "cancelled", + "printedName": "cancelled", "children": [ { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "c:objc(cs)SentrySDK(cpy)crashedLastRun", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "crashedLastRun", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] } - ], - "declKind": "Accessor", - "usr": "c:objc(cs)SentrySDK(cm)crashedLastRun", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "crashedLastRun", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "accessorKind": "get" + ] } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusCancelled", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" ] }, { "kind": "Var", - "name": "detectedStartUpCrash", - "printedName": "detectedStartUpCrash", + "name": "alreadyExists", + "printedName": "alreadyExists", "children": [ { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "c:objc(cs)SentrySDK(cpy)detectedStartUpCrash", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "detectedStartUpCrash", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] } - ], - "declKind": "Accessor", - "usr": "c:objc(cs)SentrySDK(cm)detectedStartUpCrash", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "detectedStartUpCrash", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "accessorKind": "get" + ] } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusAlreadyExists", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" ] }, { - "kind": "Function", - "name": "setUser", - "printedName": "setUser(_:)", + "kind": "Var", + "name": "failedPrecondition", + "printedName": "failedPrecondition", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Sentry.User?", - "children": [ + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, { "kind": "TypeNominal", - "name": "User", - "printedName": "Sentry.User", - "usr": "c:objc(cs)SentryUser" + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] } - ], - "usr": "s:Sq" + ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)setUser:", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusFailedPrecondition", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "setUser:", "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "startSession", - "printedName": "startSession()", + "kind": "Var", + "name": "aborted", + "printedName": "aborted", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] } ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)startSession", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusAborted", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "startSession", "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "endSession", - "printedName": "endSession()", + "kind": "Var", + "name": "outOfRange", + "printedName": "outOfRange", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] } ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)endSession", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusOutOfRange", "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "endSession", "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" + "ObjC" + ] }, { - "kind": "Function", - "name": "crash", - "printedName": "crash()", + "kind": "Var", + "name": "dataLoss", + "printedName": "dataLoss", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] } ] } ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)crash", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "crash", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" - }, - { - "kind": "Function", - "name": "reportFullyDisplayed", - "printedName": "reportFullyDisplayed()", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - } - ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)reportFullyDisplayed", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "reportFullyDisplayed", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" - }, - { - "kind": "Function", - "name": "pauseAppHangTracking", - "printedName": "pauseAppHangTracking()", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - } - ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)pauseAppHangTracking", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "pauseAppHangTracking", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" - }, - { - "kind": "Function", - "name": "resumeAppHangTracking", - "printedName": "resumeAppHangTracking()", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - } - ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)resumeAppHangTracking", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "resumeAppHangTracking", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" - }, - { - "kind": "Function", - "name": "flush", - "printedName": "flush(timeout:)", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNameAlias", - "name": "TimeInterval", - "printedName": "Foundation.TimeInterval", - "children": [ - { - "kind": "TypeNominal", - "name": "Double", - "printedName": "Swift.Double", - "usr": "s:Sd" - } - ] - } - ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)flush:", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "flush:", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" - }, - { - "kind": "Function", - "name": "close", - "printedName": "close()", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - } - ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)close", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "close", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" - }, - { - "kind": "Function", - "name": "startProfiler", - "printedName": "startProfiler()", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - } - ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)startProfiler", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "startProfiler", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" - }, - { - "kind": "Function", - "name": "stopProfiler", - "printedName": "stopProfiler()", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - } - ], - "declKind": "Func", - "usr": "c:objc(cs)SentrySDK(cm)stopProfiler", - "moduleName": "Sentry", - "static": true, - "isOpen": true, - "objc_name": "stopProfiler", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" - } - ], - "declKind": "Class", - "usr": "c:objc(cs)SentrySDK", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "SentrySDK", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "superclassUsr": "c:objc(cs)NSObject", - "inheritsConvenienceInitializers": true, - "superclassNames": [ - "ObjectiveC.NSObject" - ], - "conformances": [ - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "NSObjectProtocol", - "printedName": "NSObjectProtocol", - "usr": "c:objc(pl)NSObject" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "CVarArg", - "printedName": "CVarArg", - "usr": "s:s7CVarArgP", - "mangledName": "$ss7CVarArgP" - }, - { - "kind": "Conformance", - "name": "CustomStringConvertible", - "printedName": "CustomStringConvertible", - "usr": "s:s23CustomStringConvertibleP", - "mangledName": "$ss23CustomStringConvertibleP" - }, - { - "kind": "Conformance", - "name": "CustomDebugStringConvertible", - "printedName": "CustomDebugStringConvertible", - "usr": "s:s28CustomDebugStringConvertibleP", - "mangledName": "$ss28CustomDebugStringConvertibleP" - } - ] - }, - { - "kind": "TypeDecl", - "name": "SentrySampleDecision", - "printedName": "SentrySampleDecision", - "children": [ - { - "kind": "Constructor", - "name": "init", - "printedName": "init(rawValue:)", - "children": [ - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Sentry.SentrySampleDecision?", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySampleDecision", - "printedName": "Sentry.SentrySampleDecision", - "usr": "c:@E@SentrySampleDecision" - } - ], - "usr": "s:Sq" - }, - { - "kind": "TypeNominal", - "name": "UInt", - "printedName": "Swift.UInt", - "usr": "s:Su" - } - ], - "declKind": "Constructor", - "usr": "s:So20SentrySampleDecisionV8rawValueABSgSu_tcfc", - "mangledName": "$sSo20SentrySampleDecisionV8rawValueABSgSu_tcfc", - "moduleName": "Sentry", - "implicit": true, - "init_kind": "Designated" - }, - { - "kind": "Var", - "name": "rawValue", - "printedName": "rawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "UInt", - "printedName": "Swift.UInt", - "usr": "s:Su" - } - ], - "declKind": "Var", - "usr": "s:So20SentrySampleDecisionV8rawValueSuvp", - "mangledName": "$sSo20SentrySampleDecisionV8rawValueSuvp", - "moduleName": "Sentry", - "implicit": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "UInt", - "printedName": "Swift.UInt", - "usr": "s:Su" - } - ], - "declKind": "Accessor", - "usr": "s:So20SentrySampleDecisionV8rawValueSuvg", - "mangledName": "$sSo20SentrySampleDecisionV8rawValueSuvg", - "moduleName": "Sentry", - "implicit": true, - "accessorKind": "get" - } - ] - }, - { - "kind": "TypeAlias", - "name": "RawValue", - "printedName": "RawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "UInt", - "printedName": "Swift.UInt", - "usr": "s:Su" - } - ], - "declKind": "TypeAlias", - "usr": "s:So20SentrySampleDecisionV8RawValuea", - "mangledName": "$sSo20SentrySampleDecisionV8RawValuea", - "moduleName": "Sentry", - "implicit": true - }, - { - "kind": "Var", - "name": "undecided", - "printedName": "undecided", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySampleDecision.Type) -> Sentry.SentrySampleDecision", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySampleDecision", - "printedName": "Sentry.SentrySampleDecision", - "usr": "c:@E@SentrySampleDecision" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySampleDecision.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySampleDecision", - "printedName": "Sentry.SentrySampleDecision", - "usr": "c:@E@SentrySampleDecision" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySampleDecision@kSentrySampleDecisionUndecided", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "yes", - "printedName": "yes", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySampleDecision.Type) -> Sentry.SentrySampleDecision", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySampleDecision", - "printedName": "Sentry.SentrySampleDecision", - "usr": "c:@E@SentrySampleDecision" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySampleDecision.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySampleDecision", - "printedName": "Sentry.SentrySampleDecision", - "usr": "c:@E@SentrySampleDecision" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySampleDecision@kSentrySampleDecisionYes", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "no", - "printedName": "no", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySampleDecision.Type) -> Sentry.SentrySampleDecision", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySampleDecision", - "printedName": "Sentry.SentrySampleDecision", - "usr": "c:@E@SentrySampleDecision" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySampleDecision.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySampleDecision", - "printedName": "Sentry.SentrySampleDecision", - "usr": "c:@E@SentrySampleDecision" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySampleDecision@kSentrySampleDecisionNo", + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusDataLoss", "moduleName": "Sentry", "declAttributes": [ "ObjC" @@ -34047,9 +34902,9 @@ } ], "declKind": "Enum", - "usr": "c:@E@SentrySampleDecision", + "usr": "c:@E@SentrySpanStatus", "moduleName": "Sentry", - "objc_name": "SentrySampleDecision", + "objc_name": "SentrySpanStatus", "declAttributes": [ "SynthesizedProtocol", "ObjC", @@ -34086,7 +34941,7 @@ { "kind": "TypeNameAlias", "name": "RawValue", - "printedName": "Sentry.SentrySampleDecision.RawValue", + "printedName": "Sentry.SentrySpanStatus.RawValue", "children": [ { "kind": "TypeNominal", @@ -34126,238 +34981,170 @@ ] }, { - "kind": "TypeDecl", - "name": "SentrySerializable", - "printedName": "SentrySerializable", + "kind": "Var", + "name": "SentrySpanStatusNames", + "printedName": "SentrySpanStatusNames", "children": [ { - "kind": "Function", - "name": "serialize", - "printedName": "serialize()", + "kind": "TypeNominal", + "name": "Tuple", + "printedName": "(Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString)", "children": [ { "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Any]", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "Any" - } - ], - "usr": "s:SD" - } - ], - "declKind": "Func", - "usr": "c:objc(pl)SentrySerializable(im)serialize", - "moduleName": "Sentry", - "genericSig": "", - "protocolReq": true, - "objc_name": "serialize", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "reqNewWitnessTableEntry": true, - "funcSelfKind": "NonMutating" - } - ], - "declKind": "Protocol", - "usr": "c:objc(pl)SentrySerializable", - "moduleName": "Sentry", - "genericSig": "", - "objc_name": "SentrySerializable", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "conformances": [ - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "NSObjectProtocol", - "printedName": "NSObjectProtocol", - "usr": "c:objc(pl)NSObject" - } - ] - }, - { - "kind": "TypeAlias", - "name": "SentryShouldQueueEvent", - "printedName": "SentryShouldQueueEvent", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Foundation.HTTPURLResponse?, (any Swift.Error)?) -> Swift.Bool", - "children": [ + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" }, { "kind": "TypeNominal", - "name": "Tuple", - "printedName": "(Foundation.HTTPURLResponse?, (any Swift.Error)?)", - "children": [ - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Foundation.HTTPURLResponse?", - "children": [ - { - "kind": "TypeNominal", - "name": "HTTPURLResponse", - "printedName": "Foundation.HTTPURLResponse", - "usr": "c:objc(cs)NSHTTPURLResponse" - } - ], - "usr": "s:Sq" - }, - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "(any Swift.Error)?", - "children": [ - { - "kind": "TypeNominal", - "name": "Error", - "printedName": "any Swift.Error", - "usr": "s:s5ErrorP" - } - ], - "usr": "s:Sq" - } - ] - } - ] - } - ], - "declKind": "TypeAlias", - "usr": "c:@T@SentryShouldQueueEvent", - "moduleName": "Sentry" - }, - { - "kind": "TypeAlias", - "name": "SentrySpanCallback", - "printedName": "SentrySpanCallback", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "((any Sentry.Span)?) -> Swift.Void", - "children": [ + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" }, { "kind": "TypeNominal", - "name": "Optional", - "printedName": "(any Sentry.Span)?", - "children": [ - { - "kind": "TypeNominal", - "name": "Span", - "printedName": "any Sentry.Span", - "usr": "c:objc(pl)SentrySpan" - } - ], - "usr": "s:Sq" + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" } ] } ], - "declKind": "TypeAlias", - "usr": "c:@T@SentrySpanCallback", - "moduleName": "Sentry" + "declKind": "Var", + "usr": "c:@SentrySpanStatusNames", + "moduleName": "Sentry", + "deprecated": true, + "declAttributes": [ + "Available" + ], + "isLet": true, + "hasStorage": true }, { "kind": "TypeDecl", - "name": "SentrySpanStatus", - "printedName": "SentrySpanStatus", + "name": "SentryStacktrace", + "printedName": "SentryStacktrace", "children": [ { - "kind": "Constructor", - "name": "init", - "printedName": "init(rawValue:)", + "kind": "Var", + "name": "frames", + "printedName": "frames", "children": [ { "kind": "TypeNominal", - "name": "Optional", - "printedName": "Sentry.SentrySpanStatus?", + "name": "Array", + "printedName": "[Sentry.Frame]", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" + "name": "Frame", + "printedName": "Sentry.Frame", + "usr": "c:objc(cs)SentryFrame" } ], - "usr": "s:Sq" - }, - { - "kind": "TypeNominal", - "name": "UInt", - "printedName": "Swift.UInt", - "usr": "s:Su" - } - ], - "declKind": "Constructor", - "usr": "s:So16SentrySpanStatusV8rawValueABSgSu_tcfc", - "mangledName": "$sSo16SentrySpanStatusV8rawValueABSgSu_tcfc", - "moduleName": "Sentry", - "implicit": true, - "init_kind": "Designated" - }, - { - "kind": "Var", - "name": "rawValue", - "printedName": "rawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "UInt", - "printedName": "Swift.UInt", - "usr": "s:Su" + "usr": "s:Sa" } ], "declKind": "Var", - "usr": "s:So16SentrySpanStatusV8rawValueSuvp", - "mangledName": "$sSo16SentrySpanStatusV8rawValueSuvp", + "usr": "c:objc(cs)SentryStacktrace(py)frames", "moduleName": "Sentry", - "implicit": true, + "isOpen": true, + "objc_name": "frames", + "declAttributes": [ + "ObjC", + "Dynamic" + ], "accessors": [ { "kind": "Accessor", @@ -34366,754 +35153,445 @@ "children": [ { "kind": "TypeNominal", - "name": "UInt", - "printedName": "Swift.UInt", - "usr": "s:Su" + "name": "Array", + "printedName": "[Sentry.Frame]", + "children": [ + { + "kind": "TypeNominal", + "name": "Frame", + "printedName": "Sentry.Frame", + "usr": "c:objc(cs)SentryFrame" + } + ], + "usr": "s:Sa" } ], "declKind": "Accessor", - "usr": "s:So16SentrySpanStatusV8rawValueSuvg", - "mangledName": "$sSo16SentrySpanStatusV8rawValueSuvg", + "usr": "c:objc(cs)SentryStacktrace(im)frames", "moduleName": "Sentry", - "implicit": true, + "isOpen": true, + "objc_name": "frames", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], "accessorKind": "get" - } - ] - }, - { - "kind": "TypeAlias", - "name": "RawValue", - "printedName": "RawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "UInt", - "printedName": "Swift.UInt", - "usr": "s:Su" - } - ], - "declKind": "TypeAlias", - "usr": "s:So16SentrySpanStatusV8RawValuea", - "mangledName": "$sSo16SentrySpanStatusV8RawValuea", - "moduleName": "Sentry", - "implicit": true - }, - { - "kind": "Var", - "name": "undefined", - "printedName": "undefined", - "children": [ + }, { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", "children": [ { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" + "name": "Void", + "printedName": "()" } ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUndefined", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "ok", - "printedName": "ok", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" }, { "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", + "name": "Array", + "printedName": "[Sentry.Frame]", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" + "name": "Frame", + "printedName": "Sentry.Frame", + "usr": "c:objc(cs)SentryFrame" } - ] + ], + "usr": "s:Sa" } - ] + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryStacktrace(im)setFrames:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setFrames:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusOk", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" ] }, { "kind": "Var", - "name": "deadlineExceeded", - "printedName": "deadlineExceeded", + "name": "registers", + "printedName": "registers", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" }, { "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - } - ] + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } - ] + ], + "usr": "s:SD" } ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusDeadlineExceeded", + "declKind": "Var", + "usr": "c:objc(cs)SentryStacktrace(py)registers", "moduleName": "Sentry", + "isOpen": true, + "objc_name": "registers", "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "unauthenticated", - "printedName": "unauthenticated", - "children": [ + "ObjC", + "Dynamic" + ], + "accessors": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } - ] + ], + "usr": "s:SD" } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUnauthenticated", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "permissionDenied", - "printedName": "permissionDenied", - "children": [ + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryStacktrace(im)registers", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "registers", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", "children": [ { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" + "name": "Void", + "printedName": "()" } ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusPermissionDenied", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "notFound", - "printedName": "notFound", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" }, { "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } - ] + ], + "usr": "s:SD" } - ] + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryStacktrace(im)setRegisters:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setRegisters:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusNotFound", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" ] }, { "kind": "Var", - "name": "resourceExhausted", - "printedName": "resourceExhausted", + "name": "snapshot", + "printedName": "snapshot", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - } - ] + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } - ] + ], + "usr": "s:Sq" } ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusResourceExhausted", + "declKind": "Var", + "usr": "c:objc(cs)SentryStacktrace(py)snapshot", "moduleName": "Sentry", + "isOpen": true, + "objc_name": "snapshot", "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "invalidArgument", - "printedName": "invalidArgument", - "children": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", + "name": "Optional", + "printedName": "Foundation.NSNumber?", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } - ] + ], + "usr": "s:Sq" } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusInvalidArgument", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "unimplemented", - "printedName": "unimplemented", - "children": [ + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryStacktrace(im)snapshot", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "snapshot", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", "children": [ { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" + "name": "Void", + "printedName": "()" } ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUnimplemented", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "unavailable", - "printedName": "unavailable", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" }, { "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", + "name": "Optional", + "printedName": "Foundation.NSNumber?", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } - ] + ], + "usr": "s:Sq" } - ] + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryStacktrace(im)setSnapshot:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSnapshot:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUnavailable", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" ] }, { - "kind": "Var", - "name": "internalError", - "printedName": "internalError", + "kind": "Constructor", + "name": "init", + "printedName": "init(frames:registers:)", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "kind": "TypeNominal", + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.Frame]", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - } - ] + "name": "Frame", + "printedName": "Sentry.Frame", + "usr": "c:objc(cs)SentryFrame" } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusInternalError", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "unknownError", - "printedName": "unknownError", - "children": [ + ], + "usr": "s:Sa" + }, { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" }, { "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - } - ] + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } - ] + ], + "usr": "s:SD" } ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUnknownError", + "declKind": "Constructor", + "usr": "c:objc(cs)SentryStacktrace(im)initWithFrames:registers:", "moduleName": "Sentry", + "objc_name": "initWithFrames:registers:", "declAttributes": [ - "ObjC" - ] + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" }, { - "kind": "Var", - "name": "cancelled", - "printedName": "cancelled", + "kind": "Function", + "name": "fixDuplicateFrames", + "printedName": "fixDuplicateFrames()", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", "children": [ { "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - } - ] + "name": "Void", + "printedName": "()" } ] } ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusCancelled", + "declKind": "Func", + "usr": "c:objc(cs)SentryStacktrace(im)fixDuplicateFrames", "moduleName": "Sentry", + "isOpen": true, + "objc_name": "fixDuplicateFrames", "declAttributes": [ - "ObjC" - ] + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" }, { - "kind": "Var", - "name": "alreadyExists", - "printedName": "alreadyExists", + "kind": "Constructor", + "name": "init", + "printedName": "init(from:)", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - } - ] - } - ] + "kind": "TypeNominal", + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" + }, + { + "kind": "TypeNominal", + "name": "Decoder", + "printedName": "any Swift.Decoder", + "usr": "s:s7DecoderP" } ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusAlreadyExists", + "declKind": "Constructor", + "usr": "s:So16SentryStacktraceC0A0E4fromABs7Decoder_p_tKcfc", + "mangledName": "$sSo16SentryStacktraceC0A0E4fromABs7Decoder_p_tKcfc", "moduleName": "Sentry", "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "failedPrecondition", - "printedName": "failedPrecondition", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusFailedPrecondition", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "aborted", - "printedName": "aborted", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusAborted", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "outOfRange", - "printedName": "outOfRange", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - } - ] - } - ] - } - ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusOutOfRange", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "dataLoss", - "printedName": "dataLoss", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentrySpanStatus.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentrySpanStatus", - "printedName": "Sentry.SentrySpanStatus", - "usr": "c:@E@SentrySpanStatus" - } - ] - } - ] - } + "Required" ], - "declKind": "EnumElement", - "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusDataLoss", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] + "isFromExtension": true, + "throwing": true, + "init_kind": "Convenience" } ], - "declKind": "Enum", - "usr": "c:@E@SentrySpanStatus", + "declKind": "Class", + "usr": "c:objc(cs)SentryStacktrace", "moduleName": "Sentry", - "objc_name": "SentrySpanStatus", + "isOpen": true, + "objc_name": "SentryStacktrace", "declAttributes": [ - "SynthesizedProtocol", "ObjC", - "SynthesizedProtocol", - "Sendable", "Dynamic" ], - "enumRawTypeName": "UInt", + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], "conformances": [ + { + "kind": "Conformance", + "name": "SentrySerializable", + "printedName": "SentrySerializable", + "usr": "c:objc(pl)SentrySerializable" + }, { "kind": "Conformance", "name": "Copyable", @@ -35130,39 +35608,9 @@ }, { "kind": "Conformance", - "name": "RawRepresentable", - "printedName": "RawRepresentable", - "children": [ - { - "kind": "TypeWitness", - "name": "RawValue", - "printedName": "RawValue", - "children": [ - { - "kind": "TypeNameAlias", - "name": "RawValue", - "printedName": "Sentry.SentrySpanStatus.RawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "UInt", - "printedName": "Swift.UInt", - "usr": "s:Su" - } - ] - } - ] - } - ], - "usr": "s:SY", - "mangledName": "$sSY" - }, - { - "kind": "Conformance", - "name": "Sendable", - "printedName": "Sendable", - "usr": "s:s8SendableP", - "mangledName": "$ss8SendableP" + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" }, { "kind": "Conformance", @@ -35177,171 +35625,61 @@ "printedName": "Hashable", "usr": "s:SH", "mangledName": "$sSH" - } - ] - }, - { - "kind": "Var", - "name": "SentrySpanStatusNames", - "printedName": "SentrySpanStatusNames", - "children": [ + }, { - "kind": "TypeNominal", - "name": "Tuple", - "printedName": "(Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString)", - "children": [ - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - }, - { - "kind": "TypeNominal", - "name": "NSString", - "printedName": "Foundation.NSString", - "usr": "c:objc(cs)NSString" - } - ] + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "Decodable", + "printedName": "Decodable", + "usr": "s:Se", + "mangledName": "$sSe" } - ], - "declKind": "Var", - "usr": "c:@SentrySpanStatusNames", - "moduleName": "Sentry", - "deprecated": true, - "declAttributes": [ - "Available" - ], - "isLet": true, - "hasStorage": true + ] }, { "kind": "TypeDecl", - "name": "SentryStacktrace", - "printedName": "SentryStacktrace", + "name": "SentryThread", + "printedName": "SentryThread", "children": [ { "kind": "Var", - "name": "frames", - "printedName": "frames", + "name": "threadId", + "printedName": "threadId", "children": [ { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Sentry.Frame]", - "children": [ - { - "kind": "TypeNominal", - "name": "Frame", - "printedName": "Sentry.Frame", - "usr": "c:objc(cs)SentryFrame" - } - ], - "usr": "s:Sa" + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryStacktrace(py)frames", + "usr": "c:objc(cs)SentryThread(py)threadId", "moduleName": "Sentry", "isOpen": true, - "objc_name": "frames", + "objc_name": "threadId", "declAttributes": [ + "NSCopying", "ObjC", "Dynamic" ], @@ -35353,24 +35691,16 @@ "children": [ { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Sentry.Frame]", - "children": [ - { - "kind": "TypeNominal", - "name": "Frame", - "printedName": "Sentry.Frame", - "usr": "c:objc(cs)SentryFrame" - } - ], - "usr": "s:Sa" + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryStacktrace(im)frames", + "usr": "c:objc(cs)SentryThread(im)threadId", "moduleName": "Sentry", "isOpen": true, - "objc_name": "frames", + "objc_name": "threadId", "declAttributes": [ "DiscardableResult", "ObjC", @@ -35397,24 +35727,16 @@ }, { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Sentry.Frame]", - "children": [ - { - "kind": "TypeNominal", - "name": "Frame", - "printedName": "Sentry.Frame", - "usr": "c:objc(cs)SentryFrame" - } - ], - "usr": "s:Sa" + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryStacktrace(im)setFrames:", + "usr": "c:objc(cs)SentryThread(im)setThreadId:", "moduleName": "Sentry", "isOpen": true, - "objc_name": "setFrames:", + "objc_name": "setThreadId:", "declAttributes": [ "ObjC", "Dynamic" @@ -35425,20 +35747,14 @@ }, { "kind": "Var", - "name": "registers", - "printedName": "registers", + "name": "name", + "printedName": "name", "children": [ { "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Swift.String]", + "name": "Optional", + "printedName": "Swift.String?", "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, { "kind": "TypeNominal", "name": "String", @@ -35446,14 +35762,14 @@ "usr": "s:SS" } ], - "usr": "s:SD" + "usr": "s:Sq" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryStacktrace(py)registers", + "usr": "c:objc(cs)SentryThread(py)name", "moduleName": "Sentry", "isOpen": true, - "objc_name": "registers", + "objc_name": "name", "declAttributes": [ "ObjC", "Dynamic" @@ -35466,15 +35782,9 @@ "children": [ { "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Swift.String]", + "name": "Optional", + "printedName": "Swift.String?", "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, { "kind": "TypeNominal", "name": "String", @@ -35482,14 +35792,14 @@ "usr": "s:SS" } ], - "usr": "s:SD" + "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryStacktrace(im)registers", + "usr": "c:objc(cs)SentryThread(im)name", "moduleName": "Sentry", "isOpen": true, - "objc_name": "registers", + "objc_name": "name", "declAttributes": [ "DiscardableResult", "ObjC", @@ -35516,15 +35826,9 @@ }, { "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Swift.String]", + "name": "Optional", + "printedName": "Swift.String?", "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, { "kind": "TypeNominal", "name": "String", @@ -35532,14 +35836,14 @@ "usr": "s:SS" } ], - "usr": "s:SD" + "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryStacktrace(im)setRegisters:", + "usr": "c:objc(cs)SentryThread(im)setName:", "moduleName": "Sentry", "isOpen": true, - "objc_name": "setRegisters:", + "objc_name": "setName:", "declAttributes": [ "ObjC", "Dynamic" @@ -35550,31 +35854,30 @@ }, { "kind": "Var", - "name": "snapshot", - "printedName": "snapshot", + "name": "stacktrace", + "printedName": "stacktrace", "children": [ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Foundation.NSNumber?", + "printedName": "Sentry.SentryStacktrace?", "children": [ { "kind": "TypeNominal", - "name": "NSNumber", - "printedName": "Foundation.NSNumber", - "usr": "c:objc(cs)NSNumber" + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" } ], "usr": "s:Sq" } ], "declKind": "Var", - "usr": "c:objc(cs)SentryStacktrace(py)snapshot", + "usr": "c:objc(cs)SentryThread(py)stacktrace", "moduleName": "Sentry", "isOpen": true, - "objc_name": "snapshot", + "objc_name": "stacktrace", "declAttributes": [ - "NSCopying", "ObjC", "Dynamic" ], @@ -35587,23 +35890,23 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Foundation.NSNumber?", + "printedName": "Sentry.SentryStacktrace?", "children": [ { "kind": "TypeNominal", - "name": "NSNumber", - "printedName": "Foundation.NSNumber", - "usr": "c:objc(cs)NSNumber" + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" } ], "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:objc(cs)SentryStacktrace(im)snapshot", + "usr": "c:objc(cs)SentryThread(im)stacktrace", "moduleName": "Sentry", "isOpen": true, - "objc_name": "snapshot", + "objc_name": "stacktrace", "declAttributes": [ "DiscardableResult", "ObjC", @@ -35631,516 +35934,13 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Foundation.NSNumber?", + "printedName": "Sentry.SentryStacktrace?", "children": [ { "kind": "TypeNominal", - "name": "NSNumber", - "printedName": "Foundation.NSNumber", - "usr": "c:objc(cs)NSNumber" - } - ], - "usr": "s:Sq" - } - ], - "declKind": "Accessor", - "usr": "c:objc(cs)SentryStacktrace(im)setSnapshot:", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "setSnapshot:", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Constructor", - "name": "init", - "printedName": "init(frames:registers:)", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryStacktrace", - "printedName": "Sentry.SentryStacktrace", - "usr": "c:objc(cs)SentryStacktrace" - }, - { - "kind": "TypeNominal", - "name": "Array", - "printedName": "[Sentry.Frame]", - "children": [ - { - "kind": "TypeNominal", - "name": "Frame", - "printedName": "Sentry.Frame", - "usr": "c:objc(cs)SentryFrame" - } - ], - "usr": "s:Sa" - }, - { - "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Swift.String]", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - } - ], - "usr": "s:SD" - } - ], - "declKind": "Constructor", - "usr": "c:objc(cs)SentryStacktrace(im)initWithFrames:registers:", - "moduleName": "Sentry", - "objc_name": "initWithFrames:registers:", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "init_kind": "Designated" - }, - { - "kind": "Function", - "name": "fixDuplicateFrames", - "printedName": "fixDuplicateFrames()", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - } - ], - "declKind": "Func", - "usr": "c:objc(cs)SentryStacktrace(im)fixDuplicateFrames", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "fixDuplicateFrames", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "funcSelfKind": "NonMutating" - }, - { - "kind": "Constructor", - "name": "init", - "printedName": "init(from:)", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryStacktrace", - "printedName": "Sentry.SentryStacktrace", - "usr": "c:objc(cs)SentryStacktrace" - }, - { - "kind": "TypeNominal", - "name": "Decoder", - "printedName": "any Swift.Decoder", - "usr": "s:s7DecoderP" - } - ], - "declKind": "Constructor", - "usr": "s:So16SentryStacktraceC0A0E4fromABs7Decoder_p_tKcfc", - "mangledName": "$sSo16SentryStacktraceC0A0E4fromABs7Decoder_p_tKcfc", - "moduleName": "Sentry", - "declAttributes": [ - "Required" - ], - "isFromExtension": true, - "throwing": true, - "init_kind": "Convenience" - } - ], - "declKind": "Class", - "usr": "c:objc(cs)SentryStacktrace", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "SentryStacktrace", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "superclassUsr": "c:objc(cs)NSObject", - "inheritsConvenienceInitializers": true, - "superclassNames": [ - "ObjectiveC.NSObject" - ], - "conformances": [ - { - "kind": "Conformance", - "name": "SentrySerializable", - "printedName": "SentrySerializable", - "usr": "c:objc(pl)SentrySerializable" - }, - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "NSObjectProtocol", - "printedName": "NSObjectProtocol", - "usr": "c:objc(pl)NSObject" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "CVarArg", - "printedName": "CVarArg", - "usr": "s:s7CVarArgP", - "mangledName": "$ss7CVarArgP" - }, - { - "kind": "Conformance", - "name": "CustomStringConvertible", - "printedName": "CustomStringConvertible", - "usr": "s:s23CustomStringConvertibleP", - "mangledName": "$ss23CustomStringConvertibleP" - }, - { - "kind": "Conformance", - "name": "CustomDebugStringConvertible", - "printedName": "CustomDebugStringConvertible", - "usr": "s:s28CustomDebugStringConvertibleP", - "mangledName": "$ss28CustomDebugStringConvertibleP" - }, - { - "kind": "Conformance", - "name": "Decodable", - "printedName": "Decodable", - "usr": "s:Se", - "mangledName": "$sSe" - } - ] - }, - { - "kind": "TypeDecl", - "name": "SentryThread", - "printedName": "SentryThread", - "children": [ - { - "kind": "Var", - "name": "threadId", - "printedName": "threadId", - "children": [ - { - "kind": "TypeNominal", - "name": "NSNumber", - "printedName": "Foundation.NSNumber", - "usr": "c:objc(cs)NSNumber" - } - ], - "declKind": "Var", - "usr": "c:objc(cs)SentryThread(py)threadId", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "threadId", - "declAttributes": [ - "NSCopying", - "ObjC", - "Dynamic" - ], - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "NSNumber", - "printedName": "Foundation.NSNumber", - "usr": "c:objc(cs)NSNumber" - } - ], - "declKind": "Accessor", - "usr": "c:objc(cs)SentryThread(im)threadId", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "threadId", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "accessorKind": "get" - }, - { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "NSNumber", - "printedName": "Foundation.NSNumber", - "usr": "c:objc(cs)NSNumber" - } - ], - "declKind": "Accessor", - "usr": "c:objc(cs)SentryThread(im)setThreadId:", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "setThreadId:", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Var", - "name": "name", - "printedName": "name", - "children": [ - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Swift.String?", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - } - ], - "usr": "s:Sq" - } - ], - "declKind": "Var", - "usr": "c:objc(cs)SentryThread(py)name", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "name", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Swift.String?", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - } - ], - "usr": "s:Sq" - } - ], - "declKind": "Accessor", - "usr": "c:objc(cs)SentryThread(im)name", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "name", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "accessorKind": "get" - }, - { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Swift.String?", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - } - ], - "usr": "s:Sq" - } - ], - "declKind": "Accessor", - "usr": "c:objc(cs)SentryThread(im)setName:", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "setName:", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Var", - "name": "stacktrace", - "printedName": "stacktrace", - "children": [ - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Sentry.SentryStacktrace?", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryStacktrace", - "printedName": "Sentry.SentryStacktrace", - "usr": "c:objc(cs)SentryStacktrace" - } - ], - "usr": "s:Sq" - } - ], - "declKind": "Var", - "usr": "c:objc(cs)SentryThread(py)stacktrace", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "stacktrace", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Sentry.SentryStacktrace?", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryStacktrace", - "printedName": "Sentry.SentryStacktrace", - "usr": "c:objc(cs)SentryStacktrace" - } - ], - "usr": "s:Sq" - } - ], - "declKind": "Accessor", - "usr": "c:objc(cs)SentryThread(im)stacktrace", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "stacktrace", - "declAttributes": [ - "DiscardableResult", - "ObjC", - "Dynamic" - ], - "accessorKind": "get" - }, - { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Sentry.SentryStacktrace?", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryStacktrace", - "printedName": "Sentry.SentryStacktrace", - "usr": "c:objc(cs)SentryStacktrace" + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" } ], "usr": "s:Sq" @@ -37636,6 +37436,45 @@ ], "reqNewWitnessTableEntry": true, "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "serialize", + "printedName": "serialize()", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)serialize", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "serialize", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" } ], "declKind": "Protocol", @@ -43396,6 +43235,13 @@ "declKind": "Import", "moduleName": "Sentry" }, + { + "kind": "Import", + "name": "Darwin", + "printedName": "Darwin", + "declKind": "Import", + "moduleName": "Sentry" + }, { "kind": "Import", "name": "Foundation", @@ -43403,6 +43249,13 @@ "declKind": "Import", "moduleName": "Sentry" }, + { + "kind": "Import", + "name": "MachO", + "printedName": "MachO", + "declKind": "Import", + "moduleName": "Sentry" + }, { "kind": "Import", "name": "MetricKit", @@ -43424,6 +43277,13 @@ "declKind": "Import", "moduleName": "Sentry" }, + { + "kind": "Import", + "name": "PDFKit", + "printedName": "PDFKit", + "declKind": "Import", + "moduleName": "Sentry" + }, { "kind": "Import", "name": "Sentry", @@ -43469,32 +43329,46 @@ "declKind": "Import", "moduleName": "Sentry" }, + { + "kind": "Import", + "name": "ObjectiveC.runtime", + "printedName": "ObjectiveC.runtime", + "declKind": "Import", + "moduleName": "Sentry" + }, { "kind": "TypeDecl", - "name": "SentryFeedback", - "printedName": "SentryFeedback", + "name": "SentryViewScreenshotOptions", + "printedName": "SentryViewScreenshotOptions", "children": [ { "kind": "TypeDecl", - "name": "SentryFeedbackSource", - "printedName": "SentryFeedbackSource", + "name": "DefaultValues", + "printedName": "DefaultValues", "children": [ { "kind": "Var", - "name": "serialize", - "printedName": "serialize", + "name": "enableViewRendererV2", + "printedName": "enableViewRendererV2", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Var", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO9serializeSSvp", - "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO9serializeSSvp", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvpZ", "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, "accessors": [ { "kind": "Accessor", @@ -43503,164 +43377,348 @@ "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Accessor", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO9serializeSSvg", - "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO9serializeSSvg", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvgZ", "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], "accessorKind": "get" } ] }, { "kind": "Var", - "name": "widget", - "printedName": "widget", + "name": "enableFastViewRendering", + "printedName": "enableFastViewRendering", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryFeedback.SentryFeedbackSource.Type) -> Sentry.SentryFeedback.SentryFeedbackSource", + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", "children": [ { "kind": "TypeNominal", - "name": "SentryFeedbackSource", - "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryFeedback.SentryFeedbackSource.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryFeedbackSource", - "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" - } - ] + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } - ] + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" } - ], - "declKind": "EnumElement", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO6widgetyA2EmF", - "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO6widgetyA2EmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" ] }, { "kind": "Var", - "name": "custom", - "printedName": "custom", + "name": "maskAllText", + "printedName": "maskAllText", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryFeedback.SentryFeedbackSource.Type) -> Sentry.SentryFeedback.SentryFeedbackSource", + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", "children": [ { "kind": "TypeNominal", - "name": "SentryFeedbackSource", - "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryFeedback.SentryFeedbackSource.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryFeedbackSource", - "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" - } - ] + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } - ] + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" } - ], - "declKind": "EnumElement", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO6customyA2EmF", - "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO6customyA2EmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" ] }, { - "kind": "Constructor", - "name": "init", - "printedName": "init(rawValue:)", + "kind": "Var", + "name": "maskAllImages", + "printedName": "maskAllImages", "children": [ { "kind": "TypeNominal", - "name": "Optional", - "printedName": "Sentry.SentryFeedback.SentryFeedbackSource?", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", "children": [ { "kind": "TypeNominal", - "name": "SentryFeedbackSource", - "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], - "usr": "s:Sq" - }, - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" } - ], - "declKind": "Constructor", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO8rawValueAESgSi_tcfc", - "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO8rawValueAESgSi_tcfc", - "moduleName": "Sentry", - "init_kind": "Designated" + ] }, { - "kind": "TypeAlias", - "name": "RawValue", - "printedName": "RawValue", + "kind": "Var", + "name": "maskedViewClasses", + "printedName": "maskedViewClasses", "children": [ { "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" } ], - "declKind": "TypeAlias", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO8RawValuea", - "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO8RawValuea", - "moduleName": "Sentry" + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] }, { "kind": "Var", - "name": "rawValue", - "printedName": "rawValue", + "name": "unmaskedViewClasses", + "printedName": "unmaskedViewClasses", "children": [ { "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" } ], "declKind": "Var", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO8rawValueSivp", - "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO8rawValueSivp", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvpZ", "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, "accessors": [ { "kind": "Accessor", @@ -43669,28 +43727,65 @@ "children": [ { "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" } ], "declKind": "Accessor", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO8rawValueSivg", - "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO8rawValueSivg", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvgZ", "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], "accessorKind": "get" } ] } ], - "declKind": "Enum", - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO", - "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO", + "declKind": "Class", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC", "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ], - "enumRawTypeName": "Int", + "hasMissingDesignatedInitializers": true, "conformances": [ { "kind": "Conformance", @@ -43705,478 +43800,98 @@ "printedName": "Escapable", "usr": "s:s9EscapableP", "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "RawRepresentable", - "printedName": "RawRepresentable", - "children": [ - { - "kind": "TypeWitness", - "name": "RawValue", - "printedName": "RawValue", - "children": [ - { - "kind": "TypeNameAlias", - "name": "RawValue", - "printedName": "Sentry.SentryFeedback.SentryFeedbackSource.RawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ] - } - ] - } - ], - "usr": "s:SY", - "mangledName": "$sSY" } ] }, { - "kind": "Constructor", - "name": "init", - "printedName": "init(message:name:email:source:associatedEventId:attachments:)", + "kind": "Var", + "name": "enableViewRendererV2", + "printedName": "enableViewRendererV2", "children": [ { "kind": "TypeNominal", - "name": "SentryFeedback", - "printedName": "Sentry.SentryFeedback", - "usr": "c:@M@Sentry@objc(cs)SentryFeedback" - }, - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Swift.String?", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - } - ], - "usr": "s:Sq" - }, - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Swift.String?", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - } - ], - "usr": "s:Sq" - }, - { - "kind": "TypeNominal", - "name": "SentryFeedbackSource", - "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", - "hasDefaultArg": true, - "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" - }, - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "Sentry.SentryId?", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - } - ], - "hasDefaultArg": true, - "usr": "s:Sq" - }, - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "[Foundation.Data]?", - "children": [ - { - "kind": "TypeNominal", - "name": "Array", - "printedName": "[Foundation.Data]", - "children": [ - { - "kind": "TypeNominal", - "name": "Data", - "printedName": "Foundation.Data", - "usr": "s:10Foundation4DataV" - } - ], - "usr": "s:Sa" - } - ], - "hasDefaultArg": true, - "usr": "s:Sq" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], - "declKind": "Constructor", - "usr": "c:@M@Sentry@objc(cs)SentryFeedback(im)initWithMessage:name:email:source:associatedEventId:attachments:", - "mangledName": "$s6Sentry0A8FeedbackC7message4name5email6source17associatedEventId11attachmentsACSS_SSSgAjC0aB6SourceOAA0aI0CSgSay10Foundation4DataVGSgtcfc", + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)enableViewRendererV2", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvp", "moduleName": "Sentry", - "objc_name": "initWithMessage:name:email:source:associatedEventId:attachments:", "declAttributes": [ - "ObjC" + "ObjC", + "HasStorage" ], - "init_kind": "Designated" - }, - { - "kind": "Function", - "name": "serialize", - "printedName": "serialize()", - "children": [ + "hasStorage": true, + "accessors": [ { - "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Any]", + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "Any" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], - "usr": "s:SD" - } - ], - "declKind": "Func", - "usr": "c:@CM@Sentry@objc(cs)SentryFeedback(im)serialize", - "mangledName": "$s6Sentry0A8FeedbackC9serializeSDySSypGyF", - "moduleName": "Sentry", - "objc_name": "serialize", - "declAttributes": [ - "ObjC", - "Dynamic" - ], - "isFromExtension": true, - "funcSelfKind": "NonMutating" - } - ], - "declKind": "Class", - "usr": "c:@M@Sentry@objc(cs)SentryFeedback", - "mangledName": "$s6Sentry0A8FeedbackC", - "moduleName": "Sentry", - "declAttributes": [ - "ObjCMembers", - "ObjC" - ], - "superclassUsr": "c:objc(cs)NSObject", - "superclassNames": [ - "ObjectiveC.NSObject" - ], - "conformances": [ - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "NSObjectProtocol", - "printedName": "NSObjectProtocol", - "usr": "c:objc(pl)NSObject" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "CVarArg", - "printedName": "CVarArg", - "usr": "s:s7CVarArgP", - "mangledName": "$ss7CVarArgP" - }, - { - "kind": "Conformance", - "name": "CustomStringConvertible", - "printedName": "CustomStringConvertible", - "usr": "s:s23CustomStringConvertibleP", - "mangledName": "$ss23CustomStringConvertibleP" - }, - { - "kind": "Conformance", - "name": "CustomDebugStringConvertible", - "printedName": "CustomDebugStringConvertible", - "usr": "s:s28CustomDebugStringConvertibleP", - "mangledName": "$ss28CustomDebugStringConvertibleP" - }, - { - "kind": "Conformance", - "name": "SentrySerializable", - "printedName": "SentrySerializable", - "usr": "c:objc(pl)SentrySerializable" - } - ] - }, - { - "kind": "TypeDecl", - "name": "SentryEventDecodable", - "printedName": "SentryEventDecodable", - "children": [ - { - "kind": "Constructor", - "name": "init", - "printedName": "init(from:)", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryEventDecodable", - "printedName": "Sentry.SentryEventDecodable", - "usr": "c:@M@Sentry@objc(cs)SentryEventDecodable" + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)enableViewRendererV2", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" }, - { - "kind": "TypeNominal", - "name": "Decoder", - "printedName": "any Swift.Decoder", - "usr": "s:s7DecoderP" - } - ], - "declKind": "Constructor", - "usr": "s:6Sentry0A14EventDecodableC4fromACs7Decoder_p_tKcfc", - "mangledName": "$s6Sentry0A14EventDecodableC4fromACs7Decoder_p_tKcfc", - "moduleName": "Sentry", - "declAttributes": [ - "Required" - ], - "throwing": true, - "init_kind": "Convenience" - }, - { - "kind": "Constructor", - "name": "init", - "printedName": "init()", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryEventDecodable", - "printedName": "Sentry.SentryEventDecodable", - "usr": "c:@M@Sentry@objc(cs)SentryEventDecodable" - } - ], - "declKind": "Constructor", - "usr": "c:@M@Sentry@objc(cs)SentryEventDecodable(im)init", - "mangledName": "$s6Sentry0A14EventDecodableCACycfc", - "moduleName": "Sentry", - "overriding": true, - "objc_name": "init", - "declAttributes": [ - "ObjC", - "Dynamic", - "Required" - ], - "init_kind": "Designated" - } - ], - "declKind": "Class", - "usr": "c:@M@Sentry@objc(cs)SentryEventDecodable", - "mangledName": "$s6Sentry0A14EventDecodableC", - "moduleName": "Sentry", - "isOpen": true, - "objc_name": "SentryEventDecodable", - "declAttributes": [ - "ObjC" - ], - "superclassUsr": "c:objc(cs)SentryEvent", - "superclassNames": [ - "Sentry.Event", - "ObjectiveC.NSObject" - ], - "conformances": [ - { - "kind": "Conformance", - "name": "Decodable", - "printedName": "Decodable", - "usr": "s:Se", - "mangledName": "$sSe" - }, - { - "kind": "Conformance", - "name": "SentrySerializable", - "printedName": "SentrySerializable", - "usr": "c:objc(pl)SentrySerializable" - }, - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "NSObjectProtocol", - "printedName": "NSObjectProtocol", - "usr": "c:objc(pl)NSObject" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "CVarArg", - "printedName": "CVarArg", - "usr": "s:s7CVarArgP", - "mangledName": "$ss7CVarArgP" - }, - { - "kind": "Conformance", - "name": "CustomStringConvertible", - "printedName": "CustomStringConvertible", - "usr": "s:s23CustomStringConvertibleP", - "mangledName": "$ss23CustomStringConvertibleP" - }, - { - "kind": "Conformance", - "name": "CustomDebugStringConvertible", - "printedName": "CustomDebugStringConvertible", - "usr": "s:s28CustomDebugStringConvertibleP", - "mangledName": "$ss28CustomDebugStringConvertibleP" - } - ] - }, - { - "kind": "TypeDecl", - "name": "UserFeedback", - "printedName": "UserFeedback", - "children": [ - { - "kind": "Var", - "name": "eventId", - "printedName": "eventId", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(py)eventId", - "mangledName": "$s6Sentry12UserFeedbackC7eventIdAA0aE0Cvp", - "moduleName": "Sentry", - "isOpen": true, - "declAttributes": [ - "ObjC" - ], - "accessors": [ { "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "name": "Set", + "printedName": "Set()", "children": [ { "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)eventId", - "mangledName": "$s6Sentry12UserFeedbackC7eventIdAA0aE0Cvg", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)setEnableViewRendererV2:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvs", "moduleName": "Sentry", - "isOpen": true, + "implicit": true, "declAttributes": [ "ObjC" ], - "accessorKind": "get" + "accessorKind": "set" } ] }, { "kind": "Var", - "name": "name", - "printedName": "name", + "name": "enableFastViewRendering", + "printedName": "enableFastViewRendering", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(py)name", - "mangledName": "$s6Sentry12UserFeedbackC4nameSSvp", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)enableFastViewRendering", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC010enableFastB9RenderingSbvp", "moduleName": "Sentry", - "isOpen": true, "declAttributes": [ "ObjC", "HasStorage" @@ -44190,17 +43905,16 @@ "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)name", - "mangledName": "$s6Sentry12UserFeedbackC4nameSSvg", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)enableFastViewRendering", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC010enableFastB9RenderingSbvg", "moduleName": "Sentry", "implicit": true, - "isOpen": true, "declAttributes": [ "ObjC" ], @@ -44218,17 +43932,16 @@ }, { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)setName:", - "mangledName": "$s6Sentry12UserFeedbackC4nameSSvs", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)setEnableFastViewRendering:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC010enableFastB9RenderingSbvs", "moduleName": "Sentry", "implicit": true, - "isOpen": true, "declAttributes": [ "ObjC" ], @@ -44238,21 +43951,21 @@ }, { "kind": "Var", - "name": "email", - "printedName": "email", + "name": "maskAllImages", + "printedName": "maskAllImages", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(py)email", - "mangledName": "$s6Sentry12UserFeedbackC5emailSSvp", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)maskAllImages", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13maskAllImagesSbvp", "moduleName": "Sentry", - "isOpen": true, + "objc_name": "maskAllImages", "declAttributes": [ "ObjC", "HasStorage" @@ -44266,17 +43979,17 @@ "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)email", - "mangledName": "$s6Sentry12UserFeedbackC5emailSSvg", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)maskAllImages", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13maskAllImagesSbvg", "moduleName": "Sentry", "implicit": true, - "isOpen": true, + "objc_name": "maskAllImages", "declAttributes": [ "ObjC" ], @@ -44294,17 +44007,16 @@ }, { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)setEmail:", - "mangledName": "$s6Sentry12UserFeedbackC5emailSSvs", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)setMaskAllImages:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13maskAllImagesSbvs", "moduleName": "Sentry", "implicit": true, - "isOpen": true, "declAttributes": [ "ObjC" ], @@ -44314,21 +44026,21 @@ }, { "kind": "Var", - "name": "comments", - "printedName": "comments", + "name": "maskAllText", + "printedName": "maskAllText", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(py)comments", - "mangledName": "$s6Sentry12UserFeedbackC8commentsSSvp", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)maskAllText", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11maskAllTextSbvp", "moduleName": "Sentry", - "isOpen": true, + "objc_name": "maskAllText", "declAttributes": [ "ObjC", "HasStorage" @@ -44342,17 +44054,17 @@ "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)comments", - "mangledName": "$s6Sentry12UserFeedbackC8commentsSSvg", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)maskAllText", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11maskAllTextSbvg", "moduleName": "Sentry", "implicit": true, - "isOpen": true, + "objc_name": "maskAllText", "declAttributes": [ "ObjC" ], @@ -44370,17 +44082,16 @@ }, { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)setComments:", - "mangledName": "$s6Sentry12UserFeedbackC8commentsSSvs", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)setMaskAllText:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11maskAllTextSbvs", "moduleName": "Sentry", "implicit": true, - "isOpen": true, "declAttributes": [ "ObjC" ], @@ -44389,512 +44100,252 @@ ] }, { - "kind": "Constructor", - "name": "init", - "printedName": "init(eventId:)", - "children": [ - { - "kind": "TypeNominal", - "name": "UserFeedback", - "printedName": "Sentry.UserFeedback", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback" - }, - { - "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - } - ], - "declKind": "Constructor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)initWithEventId:", - "mangledName": "$s6Sentry12UserFeedbackC7eventIdAcA0aE0C_tcfc", - "moduleName": "Sentry", - "objc_name": "initWithEventId:", - "declAttributes": [ - "ObjC" - ], - "init_kind": "Designated" - }, - { - "kind": "Function", - "name": "serialize", - "printedName": "serialize()", + "kind": "Var", + "name": "maskedViewClasses", + "printedName": "maskedViewClasses", "children": [ { "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Any]", + "name": "Array", + "printedName": "[Swift.AnyClass]", "children": [ { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "Any" + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] } ], - "usr": "s:SD" + "usr": "s:Sa" } ], - "declKind": "Func", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)serialize", - "mangledName": "$s6Sentry12UserFeedbackC9serializeSDySSypGyF", + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)maskedViewClasses", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06maskedB7ClassesSayyXlXpGvp", "moduleName": "Sentry", - "isOpen": true, - "objc_name": "serialize", + "objc_name": "maskedViewClasses", "declAttributes": [ - "ObjC" + "ObjC", + "HasStorage" ], - "funcSelfKind": "NonMutating" - } - ], - "declKind": "Class", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback", - "mangledName": "$s6Sentry12UserFeedbackC", - "moduleName": "Sentry", - "deprecated": true, - "isOpen": true, - "objc_name": "SentryUserFeedback", - "declAttributes": [ - "Available", - "ObjC", - "Available" - ], - "superclassUsr": "c:objc(cs)NSObject", - "superclassNames": [ - "ObjectiveC.NSObject" - ], - "conformances": [ - { - "kind": "Conformance", - "name": "SentrySerializable", - "printedName": "SentrySerializable", - "usr": "c:objc(pl)SentrySerializable" - }, - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "NSObjectProtocol", - "printedName": "NSObjectProtocol", - "usr": "c:objc(pl)NSObject" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "CVarArg", - "printedName": "CVarArg", - "usr": "s:s7CVarArgP", - "mangledName": "$ss7CVarArgP" - }, - { - "kind": "Conformance", - "name": "CustomStringConvertible", - "printedName": "CustomStringConvertible", - "usr": "s:s23CustomStringConvertibleP", - "mangledName": "$ss23CustomStringConvertibleP" - }, - { - "kind": "Conformance", - "name": "CustomDebugStringConvertible", - "printedName": "CustomDebugStringConvertible", - "usr": "s:s28CustomDebugStringConvertibleP", - "mangledName": "$ss28CustomDebugStringConvertibleP" - } - ] - }, - { - "kind": "TypeDecl", - "name": "SentryReplayOptions", - "printedName": "SentryReplayOptions", - "children": [ - { - "kind": "TypeDecl", - "name": "DefaultValues", - "printedName": "DefaultValues", - "children": [ + "hasStorage": true, + "accessors": [ { - "kind": "Var", - "name": "sessionSampleRate", - "printedName": "sessionSampleRate", + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", "children": [ { "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "usr": "s:Sf" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17sessionSampleRateSfvpZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17sessionSampleRateSfvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "name": "Array", + "printedName": "[Swift.AnyClass]", "children": [ { - "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "usr": "s:Sf" + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] } ], - "declKind": "Accessor", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17sessionSampleRateSfvgZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17sessionSampleRateSfvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" + "usr": "s:Sa" } - ] + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)maskedViewClasses", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06maskedB7ClassesSayyXlXpGvg", + "moduleName": "Sentry", + "implicit": true, + "objc_name": "maskedViewClasses", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" }, { - "kind": "Var", - "name": "onErrorSampleRate", - "printedName": "onErrorSampleRate", + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", "children": [ { "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "usr": "s:Sf" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17onErrorSampleRateSfvpZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17onErrorSampleRateSfvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ + "name": "Void", + "printedName": "()" + }, { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", "children": [ { - "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "usr": "s:Sf" + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] } ], - "declKind": "Accessor", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17onErrorSampleRateSfvgZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17onErrorSampleRateSfvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" - } - ] - }, - { - "kind": "Var", - "name": "maskAllText", - "printedName": "maskAllText", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "usr": "s:Sa" } ], - "declKind": "Var", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC11maskAllTextSbvpZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC11maskAllTextSbvpZ", + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)setMaskedViewClasses:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06maskedB7ClassesSayyXlXpGvs", "moduleName": "Sentry", - "static": true, + "implicit": true, "declAttributes": [ - "Final", - "HasStorage" + "ObjC" ], - "isLet": true, - "hasStorage": true, - "accessors": [ + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "unmaskedViewClasses", + "printedName": "unmaskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC11maskAllTextSbvgZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC11maskAllTextSbvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" + ] } - ] - }, + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)unmaskedViewClasses", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC08unmaskedB7ClassesSayyXlXpGvp", + "moduleName": "Sentry", + "objc_name": "unmaskedViewClasses", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ { - "kind": "Var", - "name": "maskAllImages", - "printedName": "maskAllImages", + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC13maskAllImagesSbvpZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC13maskAllImagesSbvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC13maskAllImagesSbvgZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC13maskAllImagesSbvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" - } - ] - }, - { - "kind": "Var", - "name": "enableViewRendererV2", - "printedName": "enableViewRendererV2", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC20enableViewRendererV2SbvpZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC20enableViewRendererV2SbvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC20enableViewRendererV2SbvgZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC20enableViewRendererV2SbvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" - } - ] - }, - { - "kind": "Var", - "name": "enableFastViewRendering", - "printedName": "enableFastViewRendering", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC23enableFastViewRenderingSbvpZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC23enableFastViewRenderingSbvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC23enableFastViewRenderingSbvgZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC23enableFastViewRenderingSbvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" - } - ] - }, - { - "kind": "Var", - "name": "quality", - "printedName": "quality", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryReplayQuality", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" - } - ], - "declKind": "Var", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC7qualityAC0aB7QualityOvpZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC7qualityAC0aB7QualityOvpZ", - "moduleName": "Sentry", - "static": true, - "declAttributes": [ - "Final", - "HasStorage" - ], - "isLet": true, - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryReplayQuality", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" - } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC7qualityAC0aB7QualityOvgZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC7qualityAC0aB7QualityOvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" - } - ] - }, - { - "kind": "Var", - "name": "maskedViewClasses", - "printedName": "maskedViewClasses", - "children": [ - { - "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", + "name": "Array", + "printedName": "[Swift.AnyClass]", "children": [ { "kind": "TypeNameAlias", @@ -44933,83 +44384,27 @@ "usr": "s:Sa" } ], - "declKind": "Var", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17maskedViewClassesSayyXlXpGvpZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17maskedViewClassesSayyXlXpGvpZ", + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)unmaskedViewClasses", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC08unmaskedB7ClassesSayyXlXpGvg", "moduleName": "Sentry", - "static": true, + "implicit": true, + "objc_name": "unmaskedViewClasses", "declAttributes": [ - "Final", - "HasStorage" + "ObjC" ], - "isLet": true, - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] - } - ], - "usr": "s:Sa" - } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17maskedViewClassesSayyXlXpGvgZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17maskedViewClassesSayyXlXpGvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" - } - ] + "accessorKind": "get" }, { - "kind": "Var", - "name": "unmaskedViewClasses", - "printedName": "unmaskedViewClasses", + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, { "kind": "TypeNominal", "name": "Array", @@ -45052,230 +44447,321 @@ "usr": "s:Sa" } ], - "declKind": "Var", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC19unmaskedViewClassesSayyXlXpGvpZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC19unmaskedViewClassesSayyXlXpGvpZ", + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)setUnmaskedViewClasses:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC08unmaskedB7ClassesSayyXlXpGvs", "moduleName": "Sentry", - "static": true, + "implicit": true, "declAttributes": [ - "Final", - "HasStorage" + "ObjC" ], - "isLet": true, - "hasStorage": true, - "accessors": [ + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryViewScreenshotOptions", + "printedName": "Sentry.SentryViewScreenshotOptions", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)init", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Convenience" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(enableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryViewScreenshotOptions", + "printedName": "Sentry.SentryViewScreenshotOptions", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", "children": [ { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", "children": [ { "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", + "name": "AnyObject", + "printedName": "Swift.AnyObject", "children": [ { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", "children": [ { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" } ] } ] } - ], - "usr": "s:Sa" - } - ], - "declKind": "Accessor", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC19unmaskedViewClassesSayyXlXpGvgZ", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC19unmaskedViewClassesSayyXlXpGvgZ", - "moduleName": "Sentry", - "static": true, - "implicit": true, - "declAttributes": [ - "Final" - ], - "accessorKind": "get" - } - ] - } - ], - "declKind": "Class", - "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC", - "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC", - "moduleName": "Sentry", - "hasMissingDesignatedInitializers": true, - "conformances": [ - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - } - ] - }, - { - "kind": "TypeDecl", - "name": "SentryReplayQuality", - "printedName": "SentryReplayQuality", - "children": [ - { - "kind": "Var", - "name": "low", - "printedName": "low", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryReplayOptions.SentryReplayQuality.Type) -> Sentry.SentryReplayOptions.SentryReplayQuality", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryReplayQuality", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryReplayQuality", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" - } ] } ] } ], - "declKind": "EnumElement", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO3lowyA2EmF", - "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO3lowyA2EmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] + "hasDefaultArg": true, + "usr": "s:Sa" }, { - "kind": "Var", - "name": "medium", - "printedName": "medium", + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryReplayOptions.SentryReplayQuality.Type) -> Sentry.SentryReplayOptions.SentryReplayQuality", + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", "children": [ { "kind": "TypeNominal", - "name": "SentryReplayQuality", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality.Type", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", "children": [ { - "kind": "TypeNominal", - "name": "SentryReplayQuality", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] } ] } ] } ], - "declKind": "EnumElement", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO6mediumyA2EmF", - "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO6mediumyA2EmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] - }, - { - "kind": "Var", - "name": "high", - "printedName": "high", + "hasDefaultArg": true, + "usr": "s:Sa" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)initWithEnableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV20e4FastB9Rendering11maskAllText0jK6Images06maskedB7Classes08unmaskedbO0ACSb_S3bSayyXlXpGAJtcfc", + "moduleName": "Sentry", + "objc_name": "initWithEnableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "description", + "printedName": "description", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)description", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11descriptionSSvp", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "description", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryReplayOptions.SentryReplayQuality.Type) -> Sentry.SentryReplayOptions.SentryReplayQuality", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryReplayQuality", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryReplayQuality", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" - } - ] - } - ] + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], - "declKind": "EnumElement", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO4highyA2EmF", - "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO4highyA2EmF", + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)description", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11descriptionSSvg", "moduleName": "Sentry", + "overriding": true, + "objc_name": "description", "declAttributes": [ - "ObjC" - ] - }, + "Dynamic", + "ObjC", + "Override" + ], + "accessorKind": "get" + } + ] + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC", + "moduleName": "Sentry", + "declAttributes": [ + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "SentryRedactOptions", + "printedName": "SentryRedactOptions", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions", + "mangledName": "$s6Sentry0A13RedactOptionsP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryFeedback", + "printedName": "SentryFeedback", + "children": [ + { + "kind": "TypeDecl", + "name": "SentryFeedbackSource", + "printedName": "SentryFeedbackSource", + "children": [ { "kind": "Var", - "name": "description", - "printedName": "description", + "name": "serialize", + "printedName": "serialize", "children": [ { "kind": "TypeNominal", @@ -45285,8 +44771,8 @@ } ], "declKind": "Var", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO11descriptionSSvp", - "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO11descriptionSSvp", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO9serializeSSvp", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO9serializeSSvp", "moduleName": "Sentry", "accessors": [ { @@ -45302,13 +44788,93 @@ } ], "declKind": "Accessor", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO11descriptionSSvg", - "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO11descriptionSSvg", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO9serializeSSvg", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO9serializeSSvg", "moduleName": "Sentry", "accessorKind": "get" } ] }, + { + "kind": "Var", + "name": "widget", + "printedName": "widget", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryFeedback.SentryFeedbackSource.Type) -> Sentry.SentryFeedback.SentryFeedbackSource", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO6widgetyA2EmF", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO6widgetyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "custom", + "printedName": "custom", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryFeedback.SentryFeedbackSource.Type) -> Sentry.SentryFeedback.SentryFeedbackSource", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO6customyA2EmF", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO6customyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, { "kind": "Constructor", "name": "init", @@ -45317,13 +44883,13 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality?", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource?", "children": [ { "kind": "TypeNominal", - "name": "SentryReplayQuality", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" } ], "usr": "s:Sq" @@ -45336,8 +44902,8 @@ } ], "declKind": "Constructor", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueAESgSi_tcfc", - "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueAESgSi_tcfc", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO8rawValueAESgSi_tcfc", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO8rawValueAESgSi_tcfc", "moduleName": "Sentry", "init_kind": "Designated" }, @@ -45354,8 +44920,8 @@ } ], "declKind": "TypeAlias", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO8RawValuea", - "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO8RawValuea", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO8RawValuea", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO8RawValuea", "moduleName": "Sentry" }, { @@ -45371,8 +44937,8 @@ } ], "declKind": "Var", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueSivp", - "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueSivp", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO8rawValueSivp", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO8rawValueSivp", "moduleName": "Sentry", "accessors": [ { @@ -45388,8 +44954,8 @@ } ], "declKind": "Accessor", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueSivg", - "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueSivg", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO8rawValueSivg", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO8rawValueSivg", "moduleName": "Sentry", "accessorKind": "get" } @@ -45397,21 +44963,14 @@ } ], "declKind": "Enum", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO", - "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO", "moduleName": "Sentry", "declAttributes": [ "ObjC" ], "enumRawTypeName": "Int", "conformances": [ - { - "kind": "Conformance", - "name": "CustomStringConvertible", - "printedName": "CustomStringConvertible", - "usr": "s:s23CustomStringConvertibleP", - "mangledName": "$ss23CustomStringConvertibleP" - }, { "kind": "Conformance", "name": "Copyable", @@ -45453,7 +45012,7 @@ { "kind": "TypeNameAlias", "name": "RawValue", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality.RawValue", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource.RawValue", "children": [ { "kind": "TypeNominal", @@ -45472,173 +45031,389 @@ ] }, { - "kind": "Var", - "name": "sessionSampleRate", - "printedName": "sessionSampleRate", + "kind": "Constructor", + "name": "init", + "printedName": "init(message:name:email:source:associatedEventId:attachments:)", "children": [ { "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "usr": "s:Sf" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)sessionSampleRate", - "mangledName": "$s6Sentry0A13ReplayOptionsC17sessionSampleRateSfvp", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ + "name": "SentryFeedback", + "printedName": "Sentry.SentryFeedback", + "usr": "c:@M@Sentry@objc(cs)SentryFeedback" + }, { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", "children": [ { "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "usr": "s:Sf" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)sessionSampleRate", - "mangledName": "$s6Sentry0A13ReplayOptionsC17sessionSampleRateSfvg", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "get" + "usr": "s:Sq" }, { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - }, - { - "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "usr": "s:Sf" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setSessionSampleRate:", - "mangledName": "$s6Sentry0A13ReplayOptionsC17sessionSampleRateSfvs", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Var", - "name": "onErrorSampleRate", - "printedName": "onErrorSampleRate", - "children": [ + "usr": "s:Sq" + }, { "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "usr": "s:Sf" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)onErrorSampleRate", - "mangledName": "$s6Sentry0A13ReplayOptionsC17onErrorSampleRateSfvp", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", + "hasDefaultArg": true, + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" + }, { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryId?", "children": [ { "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "usr": "s:Sf" + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)onErrorSampleRate", - "mangledName": "$s6Sentry0A13ReplayOptionsC17onErrorSampleRateSfvg", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "get" + "hasDefaultArg": true, + "usr": "s:Sq" }, { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Foundation.Data]?", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - }, - { - "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "usr": "s:Sf" + "name": "Array", + "printedName": "[Foundation.Data]", + "children": [ + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + } + ], + "usr": "s:Sa" } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setOnErrorSampleRate:", - "mangledName": "$s6Sentry0A13ReplayOptionsC17onErrorSampleRateSfvs", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" + "hasDefaultArg": true, + "usr": "s:Sq" } - ] + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryFeedback(im)initWithMessage:name:email:source:associatedEventId:attachments:", + "mangledName": "$s6Sentry0A8FeedbackC7message4name5email6source17associatedEventId11attachmentsACSS_SSSgAjC0aB6SourceOAA0aI0CSgSay10Foundation4DataVGSgtcfc", + "moduleName": "Sentry", + "objc_name": "initWithMessage:name:email:source:associatedEventId:attachments:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" }, { - "kind": "Var", - "name": "maskAllText", - "printedName": "maskAllText", + "kind": "Function", + "name": "serialize", + "printedName": "serialize()", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" } ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)maskAllText", - "mangledName": "$s6Sentry0A13ReplayOptionsC11maskAllTextSbvp", + "declKind": "Func", + "usr": "c:@CM@Sentry@objc(cs)SentryFeedback(im)serialize", + "mangledName": "$s6Sentry0A8FeedbackC9serializeSDySSypGyF", "moduleName": "Sentry", - "objc_name": "maskAllText", + "objc_name": "serialize", "declAttributes": [ "ObjC", - "HasStorage" + "Dynamic" + ], + "isFromExtension": true, + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryFeedback", + "mangledName": "$s6Sentry0A8FeedbackC", + "moduleName": "Sentry", + "declAttributes": [ + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "SentrySerializable", + "printedName": "SentrySerializable", + "usr": "c:objc(pl)SentrySerializable" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryEventDecodable", + "printedName": "SentryEventDecodable", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(from:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryEventDecodable", + "printedName": "Sentry.SentryEventDecodable", + "usr": "c:@M@Sentry@objc(cs)SentryEventDecodable" + }, + { + "kind": "TypeNominal", + "name": "Decoder", + "printedName": "any Swift.Decoder", + "usr": "s:s7DecoderP" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A14EventDecodableC4fromACs7Decoder_p_tKcfc", + "mangledName": "$s6Sentry0A14EventDecodableC4fromACs7Decoder_p_tKcfc", + "moduleName": "Sentry", + "declAttributes": [ + "Required" + ], + "throwing": true, + "init_kind": "Convenience" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryEventDecodable", + "printedName": "Sentry.SentryEventDecodable", + "usr": "c:@M@Sentry@objc(cs)SentryEventDecodable" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryEventDecodable(im)init", + "mangledName": "$s6Sentry0A14EventDecodableCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Required" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryEventDecodable", + "mangledName": "$s6Sentry0A14EventDecodableC", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryEventDecodable", + "declAttributes": [ + "ObjC" + ], + "superclassUsr": "c:objc(cs)SentryEvent", + "superclassNames": [ + "Sentry.Event", + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Decodable", + "printedName": "Decodable", + "usr": "s:Se", + "mangledName": "$sSe" + }, + { + "kind": "Conformance", + "name": "SentrySerializable", + "printedName": "SentrySerializable", + "usr": "c:objc(pl)SentrySerializable" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "UserFeedback", + "printedName": "UserFeedback", + "children": [ + { + "kind": "Var", + "name": "eventId", + "printedName": "eventId", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(py)eventId", + "mangledName": "$s6Sentry12UserFeedbackC7eventIdAA0aE0Cvp", + "moduleName": "Sentry", + "isOpen": true, + "declAttributes": [ + "ObjC" ], - "hasStorage": true, "accessors": [ { "kind": "Accessor", @@ -45647,68 +45422,40 @@ "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)maskAllText", - "mangledName": "$s6Sentry0A13ReplayOptionsC11maskAllTextSbvg", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)eventId", + "mangledName": "$s6Sentry12UserFeedbackC7eventIdAA0aE0Cvg", "moduleName": "Sentry", - "implicit": true, - "objc_name": "maskAllText", + "isOpen": true, "declAttributes": [ "ObjC" ], "accessorKind": "get" - }, - { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - }, - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setMaskAllText:", - "mangledName": "$s6Sentry0A13ReplayOptionsC11maskAllTextSbvs", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" } ] }, { "kind": "Var", - "name": "maskAllImages", - "printedName": "maskAllImages", + "name": "name", + "printedName": "name", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)maskAllImages", - "mangledName": "$s6Sentry0A13ReplayOptionsC13maskAllImagesSbvp", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(py)name", + "mangledName": "$s6Sentry12UserFeedbackC4nameSSvp", "moduleName": "Sentry", - "objc_name": "maskAllImages", + "isOpen": true, "declAttributes": [ "ObjC", "HasStorage" @@ -45722,17 +45469,17 @@ "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)maskAllImages", - "mangledName": "$s6Sentry0A13ReplayOptionsC13maskAllImagesSbvg", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)name", + "mangledName": "$s6Sentry12UserFeedbackC4nameSSvg", "moduleName": "Sentry", "implicit": true, - "objc_name": "maskAllImages", + "isOpen": true, "declAttributes": [ "ObjC" ], @@ -45750,16 +45497,17 @@ }, { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setMaskAllImages:", - "mangledName": "$s6Sentry0A13ReplayOptionsC13maskAllImagesSbvs", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)setName:", + "mangledName": "$s6Sentry12UserFeedbackC4nameSSvs", "moduleName": "Sentry", "implicit": true, + "isOpen": true, "declAttributes": [ "ObjC" ], @@ -45769,20 +45517,21 @@ }, { "kind": "Var", - "name": "quality", - "printedName": "quality", + "name": "email", + "printedName": "email", "children": [ { "kind": "TypeNominal", - "name": "SentryReplayQuality", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)quality", - "mangledName": "$s6Sentry0A13ReplayOptionsC7qualityAC0aB7QualityOvp", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(py)email", + "mangledName": "$s6Sentry12UserFeedbackC5emailSSvp", "moduleName": "Sentry", + "isOpen": true, "declAttributes": [ "ObjC", "HasStorage" @@ -45796,16 +45545,17 @@ "children": [ { "kind": "TypeNominal", - "name": "SentryReplayQuality", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)quality", - "mangledName": "$s6Sentry0A13ReplayOptionsC7qualityAC0aB7QualityOvg", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)email", + "mangledName": "$s6Sentry12UserFeedbackC5emailSSvg", "moduleName": "Sentry", "implicit": true, + "isOpen": true, "declAttributes": [ "ObjC" ], @@ -45823,16 +45573,17 @@ }, { "kind": "TypeNominal", - "name": "SentryReplayQuality", - "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", - "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setQuality:", - "mangledName": "$s6Sentry0A13ReplayOptionsC7qualityAC0aB7QualityOvs", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)setEmail:", + "mangledName": "$s6Sentry12UserFeedbackC5emailSSvs", "moduleName": "Sentry", "implicit": true, + "isOpen": true, "declAttributes": [ "ObjC" ], @@ -45842,56 +45593,21 @@ }, { "kind": "Var", - "name": "maskedViewClasses", - "printedName": "maskedViewClasses", + "name": "comments", + "printedName": "comments", "children": [ { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] - } - ], - "usr": "s:Sa" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)maskedViewClasses", - "mangledName": "$s6Sentry0A13ReplayOptionsC17maskedViewClassesSayyXlXpGvp", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(py)comments", + "mangledName": "$s6Sentry12UserFeedbackC8commentsSSvp", "moduleName": "Sentry", - "objc_name": "maskedViewClasses", + "isOpen": true, "declAttributes": [ "ObjC", "HasStorage" @@ -45905,52 +45621,17 @@ "children": [ { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] - } - ], - "usr": "s:Sa" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)maskedViewClasses", - "mangledName": "$s6Sentry0A13ReplayOptionsC17maskedViewClassesSayyXlXpGvg", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)comments", + "mangledName": "$s6Sentry12UserFeedbackC8commentsSSvg", "moduleName": "Sentry", "implicit": true, - "objc_name": "maskedViewClasses", + "isOpen": true, "declAttributes": [ "ObjC" ], @@ -45968,51 +45649,17 @@ }, { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] - } - ], - "usr": "s:Sa" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setMaskedViewClasses:", - "mangledName": "$s6Sentry0A13ReplayOptionsC17maskedViewClassesSayyXlXpGvs", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)setComments:", + "mangledName": "$s6Sentry12UserFeedbackC8commentsSSvs", "moduleName": "Sentry", "implicit": true, + "isOpen": true, "declAttributes": [ "ObjC" ], @@ -46021,514 +45668,92 @@ ] }, { - "kind": "Var", - "name": "unmaskedViewClasses", - "printedName": "unmaskedViewClasses", + "kind": "Constructor", + "name": "init", + "printedName": "init(eventId:)", "children": [ { "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] - } - ], - "usr": "s:Sa" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)unmaskedViewClasses", - "mangledName": "$s6Sentry0A13ReplayOptionsC19unmaskedViewClassesSayyXlXpGvp", - "moduleName": "Sentry", - "objc_name": "unmaskedViewClasses", - "declAttributes": [ - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] - } - ], - "usr": "s:Sa" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)unmaskedViewClasses", - "mangledName": "$s6Sentry0A13ReplayOptionsC19unmaskedViewClassesSayyXlXpGvg", - "moduleName": "Sentry", - "implicit": true, - "objc_name": "unmaskedViewClasses", - "declAttributes": [ - "ObjC" - ], - "accessorKind": "get" + "name": "UserFeedback", + "printedName": "Sentry.UserFeedback", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback" }, - { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - }, - { - "kind": "TypeNominal", - "name": "Array", - "printedName": "[Swift.AnyClass]", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyClass", - "printedName": "Swift.AnyClass", - "children": [ - { - "kind": "TypeNominal", - "name": "ExistentialMetatype", - "printedName": "any Swift.AnyObject.Type", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Swift.AnyObject", - "children": [ - { - "kind": "TypeNameAlias", - "name": "AnyObject", - "printedName": "Builtin.AnyObject", - "children": [ - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "AnyObject" - } - ] - } - ] - } - ] - } - ] - } - ], - "usr": "s:Sa" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setUnmaskedViewClasses:", - "mangledName": "$s6Sentry0A13ReplayOptionsC19unmaskedViewClassesSayyXlXpGvs", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Var", - "name": "enableExperimentalViewRenderer", - "printedName": "enableExperimentalViewRenderer", - "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" } ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)enableExperimentalViewRenderer", - "mangledName": "$s6Sentry0A13ReplayOptionsC30enableExperimentalViewRendererSbvp", + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)initWithEventId:", + "mangledName": "$s6Sentry12UserFeedbackC7eventIdAcA0aE0C_tcfc", "moduleName": "Sentry", - "deprecated": true, + "objc_name": "initWithEventId:", "declAttributes": [ - "Available", "ObjC" ], - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)enableExperimentalViewRenderer", - "mangledName": "$s6Sentry0A13ReplayOptionsC30enableExperimentalViewRendererSbvg", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ], - "accessorKind": "get" - }, - { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - }, - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setEnableExperimentalViewRenderer:", - "mangledName": "$s6Sentry0A13ReplayOptionsC30enableExperimentalViewRendererSbvs", - "moduleName": "Sentry", - "objc_name": "setEnableExperimentalViewRenderer:", - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Var", - "name": "enableViewRendererV2", - "printedName": "enableViewRendererV2", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)enableViewRendererV2", - "mangledName": "$s6Sentry0A13ReplayOptionsC20enableViewRendererV2Sbvp", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)enableViewRendererV2", - "mangledName": "$s6Sentry0A13ReplayOptionsC20enableViewRendererV2Sbvg", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "get" - }, - { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - }, - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setEnableViewRendererV2:", - "mangledName": "$s6Sentry0A13ReplayOptionsC20enableViewRendererV2Sbvs", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" - } - ] + "init_kind": "Designated" }, { - "kind": "Var", - "name": "enableFastViewRendering", - "printedName": "enableFastViewRendering", + "kind": "Function", + "name": "serialize", + "printedName": "serialize()", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)enableFastViewRendering", - "mangledName": "$s6Sentry0A13ReplayOptionsC23enableFastViewRenderingSbvp", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)enableFastViewRendering", - "mangledName": "$s6Sentry0A13ReplayOptionsC23enableFastViewRenderingSbvg", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "get" - }, - { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" }, { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "ProtocolComposition", + "printedName": "Any" } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setEnableFastViewRendering:", - "mangledName": "$s6Sentry0A13ReplayOptionsC23enableFastViewRenderingSbvs", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Constructor", - "name": "init", - "printedName": "init()", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryReplayOptions", - "printedName": "Sentry.SentryReplayOptions", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions" - } - ], - "declKind": "Constructor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)init", - "mangledName": "$s6Sentry0A13ReplayOptionsCACycfc", - "moduleName": "Sentry", - "overriding": true, - "objc_name": "init", - "declAttributes": [ - "ObjC", - "Dynamic", - "Override" - ], - "init_kind": "Convenience" - }, - { - "kind": "Constructor", - "name": "init", - "printedName": "init(sessionSampleRate:onErrorSampleRate:maskAllText:maskAllImages:enableViewRendererV2:enableFastViewRendering:)", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryReplayOptions", - "printedName": "Sentry.SentryReplayOptions", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions" - }, - { - "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "hasDefaultArg": true, - "usr": "s:Sf" - }, - { - "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "hasDefaultArg": true, - "usr": "s:Sf" - }, - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "hasDefaultArg": true, - "usr": "s:Sb" - }, - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "hasDefaultArg": true, - "usr": "s:Sb" - }, - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "hasDefaultArg": true, - "usr": "s:Sb" - }, - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "hasDefaultArg": true, - "usr": "s:Sb" + "usr": "s:SD" } ], - "declKind": "Constructor", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)initWithSessionSampleRate:onErrorSampleRate:maskAllText:maskAllImages:enableViewRendererV2:enableFastViewRendering:", - "mangledName": "$s6Sentry0A13ReplayOptionsC17sessionSampleRate07onErroreF011maskAllText0iJ6Images20enableViewRendererV20m4FastN9RenderingACSf_SfS4btcfc", + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback(im)serialize", + "mangledName": "$s6Sentry12UserFeedbackC9serializeSDySSypGyF", "moduleName": "Sentry", - "objc_name": "initWithSessionSampleRate:onErrorSampleRate:maskAllText:maskAllImages:enableViewRendererV2:enableFastViewRendering:", + "isOpen": true, + "objc_name": "serialize", "declAttributes": [ "ObjC" ], - "init_kind": "Convenience" + "funcSelfKind": "NonMutating" } ], "declKind": "Class", - "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions", - "mangledName": "$s6Sentry0A13ReplayOptionsC", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback", + "mangledName": "$s6Sentry12UserFeedbackC", "moduleName": "Sentry", + "deprecated": true, + "isOpen": true, + "objc_name": "SentryUserFeedback", "declAttributes": [ - "ObjCMembers", - "ObjC" + "Available", + "ObjC", + "Available" ], "superclassUsr": "c:objc(cs)NSObject", - "hasMissingDesignatedInitializers": true, - "inheritsConvenienceInitializers": true, "superclassNames": [ "ObjectiveC.NSObject" ], "conformances": [ { "kind": "Conformance", - "name": "SentryRedactOptions", - "printedName": "SentryRedactOptions", - "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions", - "mangledName": "$s6Sentry0A13RedactOptionsP" + "name": "SentrySerializable", + "printedName": "SentrySerializable", + "usr": "c:objc(pl)SentrySerializable" }, { "kind": "Conformance", @@ -46589,159 +45814,96 @@ }, { "kind": "TypeDecl", - "name": "SentryEventDecoder", - "printedName": "SentryEventDecoder", + "name": "SentryLogMessage", + "printedName": "SentryLogMessage", "children": [ { "kind": "Constructor", "name": "init", - "printedName": "init()", + "printedName": "init(stringLiteral:)", "children": [ { "kind": "TypeNominal", - "name": "SentryEventDecoder", - "printedName": "Sentry.SentryEventDecoder", - "usr": "c:@M@Sentry@objc(cs)SentryEventDecoder" - } - ], + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], "declKind": "Constructor", - "usr": "c:@M@Sentry@objc(cs)SentryEventDecoder(im)init", - "mangledName": "$s6Sentry0A12EventDecoderCACycfc", + "usr": "s:6Sentry0A10LogMessageV13stringLiteralACSS_tcfc", + "mangledName": "$s6Sentry0A10LogMessageV13stringLiteralACSS_tcfc", "moduleName": "Sentry", - "overriding": true, - "objc_name": "init", - "declAttributes": [ - "ObjC", - "Dynamic", - "Override" - ], "init_kind": "Designated" - } - ], - "declKind": "Class", - "usr": "c:@M@Sentry@objc(cs)SentryEventDecoder", - "mangledName": "$s6Sentry0A12EventDecoderC", - "moduleName": "Sentry", - "declAttributes": [ - "ObjCMembers", - "ObjC" - ], - "superclassUsr": "c:objc(cs)NSObject", - "inheritsConvenienceInitializers": true, - "superclassNames": [ - "ObjectiveC.NSObject" - ], - "conformances": [ - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "NSObjectProtocol", - "printedName": "NSObjectProtocol", - "usr": "c:objc(pl)NSObject" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "CVarArg", - "printedName": "CVarArg", - "usr": "s:s7CVarArgP", - "mangledName": "$ss7CVarArgP" - }, - { - "kind": "Conformance", - "name": "CustomStringConvertible", - "printedName": "CustomStringConvertible", - "usr": "s:s23CustomStringConvertibleP", - "mangledName": "$ss23CustomStringConvertibleP" }, { - "kind": "Conformance", - "name": "CustomDebugStringConvertible", - "printedName": "CustomDebugStringConvertible", - "usr": "s:s28CustomDebugStringConvertibleP", - "mangledName": "$ss28CustomDebugStringConvertibleP" - } - ] - }, - { - "kind": "TypeDecl", - "name": "SentryUserFeedbackConfiguration", - "printedName": "SentryUserFeedbackConfiguration", - "children": [ - { - "kind": "Var", - "name": "animations", - "printedName": "animations", + "kind": "Constructor", + "name": "init", + "printedName": "init(stringInterpolation:)", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "StringInterpolation", + "printedName": "Sentry.SentryLogMessage.StringInterpolation", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV" } ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)animations", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10animationsSbvp", + "declKind": "Constructor", + "usr": "s:6Sentry0A10LogMessageV19stringInterpolationA2C06StringE0V_tcfc", + "mangledName": "$s6Sentry0A10LogMessageV19stringInterpolationA2C06StringE0V_tcfc", "moduleName": "Sentry", - "declAttributes": [ - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ + "init_kind": "Designated" + }, + { + "kind": "TypeDecl", + "name": "StringInterpolation", + "printedName": "StringInterpolation", + "children": [ { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "Constructor", + "name": "init", + "printedName": "init(literalCapacity:interpolationCount:)", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "StringInterpolation", + "printedName": "Sentry.SentryLogMessage.StringInterpolation", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)animations", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10animationsSbvg", + "declKind": "Constructor", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV15literalCapacity18interpolationCountAESi_Sitcfc", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV15literalCapacity18interpolationCountAESi_Sitcfc", "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "get" + "init_kind": "Designated" }, { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", + "kind": "Function", + "name": "appendLiteral", + "printedName": "appendLiteral(_:)", "children": [ { "kind": "TypeNominal", @@ -46750,126 +45912,91 @@ }, { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setAnimations:", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10animationsSbvs", + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV13appendLiteralyySSF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV13appendLiteralyySSF", "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Var", - "name": "configureWidget", - "printedName": "configureWidget", - "children": [ + "funcSelfKind": "Mutating" + }, { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "((Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void)?", + "kind": "Function", + "name": "appendInterpolation", + "printedName": "appendInterpolation(_:)", "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, { "kind": "TypeFunc", "name": "Function", - "printedName": "(Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void", + "printedName": "() -> Swift.String", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" }, { "kind": "TypeNominal", - "name": "SentryUserFeedbackWidgetConfiguration", - "printedName": "Sentry.SentryUserFeedbackWidgetConfiguration", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration" + "name": "Void", + "printedName": "()" } ] } ], - "usr": "s:Sq" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)configureWidget", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15configureWidgetyAA0abcfD0CcSgvp", - "moduleName": "Sentry", - "declAttributes": [ - "HasInitialValue", - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySSyXAF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySSyXAF", + "moduleName": "Sentry", + "funcSelfKind": "Mutating" + }, { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "Function", + "name": "appendInterpolation", + "printedName": "appendInterpolation(_:)", "children": [ { "kind": "TypeNominal", - "name": "Optional", - "printedName": "((Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void)?", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Bool", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "SentryUserFeedbackWidgetConfiguration", - "printedName": "Sentry.SentryUserFeedbackWidgetConfiguration", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration" - } - ] + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" } - ], - "usr": "s:Sq" + ] } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)configureWidget", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15configureWidgetyAA0abcfD0CcSgvg", + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySbyXAF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySbyXAF", "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "get" + "funcSelfKind": "Mutating" }, { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", + "kind": "Function", + "name": "appendInterpolation", + "printedName": "appendInterpolation(_:)", "children": [ { "kind": "TypeNominal", @@ -46877,99 +46004,34 @@ "printedName": "()" }, { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "((Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void)?", + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Int", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "SentryUserFeedbackWidgetConfiguration", - "printedName": "Sentry.SentryUserFeedbackWidgetConfiguration", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration" - } - ] + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" } - ], - "usr": "s:Sq" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setConfigureWidget:", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15configureWidgetyAA0abcfD0CcSgvs", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Var", - "name": "useShakeGesture", - "printedName": "useShakeGesture", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)useShakeGesture", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15useShakeGestureSbvp", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + ] } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)useShakeGesture", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15useShakeGestureSbvg", + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySiyXAF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySiyXAF", "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "get" + "funcSelfKind": "Mutating" }, { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", + "kind": "Function", + "name": "appendInterpolation", + "printedName": "appendInterpolation(_:)", "children": [ { "kind": "TypeNominal", @@ -46977,72 +46039,69 @@ "printedName": "()" }, { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Double", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setUseShakeGesture:", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15useShakeGestureSbvs", + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySdyXAF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySdyXAF", "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Var", - "name": "showFormForScreenshots", - "printedName": "showFormForScreenshots", - "children": [ - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)showFormForScreenshots", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC22showFormForScreenshotsSbvp", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ + "funcSelfKind": "Mutating" + }, { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "Function", + "name": "appendInterpolation", + "printedName": "appendInterpolation(_:)", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Float", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)showFormForScreenshots", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC22showFormForScreenshotsSbvg", + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySfyXAF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySfyXAF", "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "get" + "funcSelfKind": "Mutating" }, { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", + "kind": "Function", + "name": "appendInterpolation", + "printedName": "appendInterpolation(_:)", "children": [ { "kind": "TypeNominal", @@ -47050,50 +46109,303 @@ "printedName": "()" }, { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> T", + "children": [ + { + "kind": "TypeNominal", + "name": "GenericTypeParam", + "printedName": "T" + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setShowFormForScreenshots:", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC22showFormForScreenshotsSbvs", + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV06appendE0yyxyXAs06CustomD11ConvertibleRzlF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV06appendE0yyxyXAs06CustomD11ConvertibleRzlF", "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Var", - "name": "customButton", - "printedName": "customButton", - "children": [ + "genericSig": "", + "funcSelfKind": "Mutating" + }, { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "UIKit.UIButton?", + "kind": "TypeAlias", + "name": "StringLiteralType", + "printedName": "StringLiteralType", "children": [ { "kind": "TypeNominal", - "name": "UIButton", - "printedName": "UIKit.UIButton", - "usr": "c:objc(cs)UIButton" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], - "usr": "s:Sq" + "declKind": "TypeAlias", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV0D11LiteralTypea", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV0D11LiteralTypea", + "moduleName": "Sentry" } ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)customButton", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC12customButtonSo8UIButtonCSgvp", + "declKind": "Struct", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV", + "moduleName": "Sentry", + "conformances": [ + { + "kind": "Conformance", + "name": "StringInterpolationProtocol", + "printedName": "StringInterpolationProtocol", + "children": [ + { + "kind": "TypeWitness", + "name": "StringLiteralType", + "printedName": "StringLiteralType", + "children": [ + { + "kind": "TypeNameAlias", + "name": "StringLiteralType", + "printedName": "Sentry.SentryLogMessage.StringInterpolation.StringLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ] + } + ] + } + ], + "usr": "s:s27StringInterpolationProtocolP", + "mangledName": "$ss27StringInterpolationProtocolP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + } + ] + }, + { + "kind": "TypeAlias", + "name": "ExtendedGraphemeClusterLiteralType", + "printedName": "ExtendedGraphemeClusterLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A10LogMessageV34ExtendedGraphemeClusterLiteralTypea", + "mangledName": "$s6Sentry0A10LogMessageV34ExtendedGraphemeClusterLiteralTypea", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "StringLiteralType", + "printedName": "StringLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A10LogMessageV17StringLiteralTypea", + "mangledName": "$s6Sentry0A10LogMessageV17StringLiteralTypea", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "UnicodeScalarLiteralType", + "printedName": "UnicodeScalarLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A10LogMessageV24UnicodeScalarLiteralTypea", + "mangledName": "$s6Sentry0A10LogMessageV24UnicodeScalarLiteralTypea", + "moduleName": "Sentry" + } + ], + "declKind": "Struct", + "usr": "s:6Sentry0A10LogMessageV", + "mangledName": "$s6Sentry0A10LogMessageV", + "moduleName": "Sentry", + "conformances": [ + { + "kind": "Conformance", + "name": "ExpressibleByStringInterpolation", + "printedName": "ExpressibleByStringInterpolation", + "children": [ + { + "kind": "TypeWitness", + "name": "StringInterpolation", + "printedName": "StringInterpolation", + "children": [ + { + "kind": "TypeNominal", + "name": "StringInterpolation", + "printedName": "Sentry.SentryLogMessage.StringInterpolation", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV" + } + ] + } + ], + "usr": "s:s32ExpressibleByStringInterpolationP", + "mangledName": "$ss32ExpressibleByStringInterpolationP" + }, + { + "kind": "Conformance", + "name": "ExpressibleByStringLiteral", + "printedName": "ExpressibleByStringLiteral", + "children": [ + { + "kind": "TypeWitness", + "name": "StringLiteralType", + "printedName": "StringLiteralType", + "children": [ + { + "kind": "TypeNameAlias", + "name": "StringLiteralType", + "printedName": "Sentry.SentryLogMessage.StringLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ] + } + ] + } + ], + "usr": "s:s26ExpressibleByStringLiteralP", + "mangledName": "$ss26ExpressibleByStringLiteralP" + }, + { + "kind": "Conformance", + "name": "ExpressibleByExtendedGraphemeClusterLiteral", + "printedName": "ExpressibleByExtendedGraphemeClusterLiteral", + "children": [ + { + "kind": "TypeWitness", + "name": "ExtendedGraphemeClusterLiteralType", + "printedName": "ExtendedGraphemeClusterLiteralType", + "children": [ + { + "kind": "TypeNameAlias", + "name": "ExtendedGraphemeClusterLiteralType", + "printedName": "Sentry.SentryLogMessage.ExtendedGraphemeClusterLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ] + } + ] + } + ], + "usr": "s:s43ExpressibleByExtendedGraphemeClusterLiteralP", + "mangledName": "$ss43ExpressibleByExtendedGraphemeClusterLiteralP" + }, + { + "kind": "Conformance", + "name": "ExpressibleByUnicodeScalarLiteral", + "printedName": "ExpressibleByUnicodeScalarLiteral", + "children": [ + { + "kind": "TypeWitness", + "name": "UnicodeScalarLiteralType", + "printedName": "UnicodeScalarLiteralType", + "children": [ + { + "kind": "TypeNameAlias", + "name": "UnicodeScalarLiteralType", + "printedName": "Sentry.SentryLogMessage.UnicodeScalarLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ] + } + ] + } + ], + "usr": "s:s33ExpressibleByUnicodeScalarLiteralP", + "mangledName": "$ss33ExpressibleByUnicodeScalarLiteralP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryLog", + "printedName": "SentryLog", + "children": [ + { + "kind": "Var", + "name": "timestamp", + "printedName": "timestamp", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryLog(py)timestamp", + "mangledName": "$s6Sentry0A3LogC9timestamp10Foundation4DateVvp", "moduleName": "Sentry", "declAttributes": [ - "HasInitialValue", + "Final", "ObjC", "HasStorage" ], @@ -47106,25 +46418,18 @@ "children": [ { "kind": "TypeNominal", - "name": "Optional", - "printedName": "UIKit.UIButton?", - "children": [ - { - "kind": "TypeNominal", - "name": "UIButton", - "printedName": "UIKit.UIButton", - "usr": "c:objc(cs)UIButton" - } - ], - "usr": "s:Sq" + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)customButton", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC12customButtonSo8UIButtonCSgvg", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)timestamp", + "mangledName": "$s6Sentry0A3LogC9timestamp10Foundation4DateVvg", "moduleName": "Sentry", "implicit": true, "declAttributes": [ + "Final", "ObjC" ], "accessorKind": "get" @@ -47141,25 +46446,18 @@ }, { "kind": "TypeNominal", - "name": "Optional", - "printedName": "UIKit.UIButton?", - "children": [ - { - "kind": "TypeNominal", - "name": "UIButton", - "printedName": "UIKit.UIButton", - "usr": "c:objc(cs)UIButton" - } - ], - "usr": "s:Sq" + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setCustomButton:", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC12customButtonSo8UIButtonCSgvs", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)setTimestamp:", + "mangledName": "$s6Sentry0A3LogC9timestamp10Foundation4DateVvs", "moduleName": "Sentry", "implicit": true, "declAttributes": [ + "Final", "ObjC" ], "accessorKind": "set" @@ -47168,49 +46466,22 @@ }, { "kind": "Var", - "name": "configureForm", - "printedName": "configureForm", + "name": "traceId", + "printedName": "traceId", "children": [ { "kind": "TypeNominal", - "name": "Optional", - "printedName": "((Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void)?", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "SentryUserFeedbackFormConfiguration", - "printedName": "Sentry.SentryUserFeedbackFormConfiguration", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration" - } - ] - } - ], - "usr": "s:Sq" + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)configureForm", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13configureFormyAA0abcfD0CcSgvp", + "usr": "c:@M@Sentry@objc(cs)SentryLog(py)traceId", + "mangledName": "$s6Sentry0A3LogC7traceIdAA0aD0Cvp", "moduleName": "Sentry", "declAttributes": [ - "HasInitialValue", + "Final", "ObjC", "HasStorage" ], @@ -47223,44 +46494,18 @@ "children": [ { "kind": "TypeNominal", - "name": "Optional", - "printedName": "((Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void)?", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "SentryUserFeedbackFormConfiguration", - "printedName": "Sentry.SentryUserFeedbackFormConfiguration", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration" - } - ] - } - ], - "usr": "s:Sq" + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)configureForm", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13configureFormyAA0abcfD0CcSgvg", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)traceId", + "mangledName": "$s6Sentry0A3LogC7traceIdAA0aD0Cvg", "moduleName": "Sentry", "implicit": true, "declAttributes": [ + "Final", "ObjC" ], "accessorKind": "get" @@ -47277,44 +46522,18 @@ }, { "kind": "TypeNominal", - "name": "Optional", - "printedName": "((Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void)?", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "SentryUserFeedbackFormConfiguration", - "printedName": "Sentry.SentryUserFeedbackFormConfiguration", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration" - } - ] - } - ], - "usr": "s:Sq" + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setConfigureForm:", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13configureFormyAA0abcfD0CcSgvs", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)setTraceId:", + "mangledName": "$s6Sentry0A3LogC7traceIdAA0aD0Cvs", "moduleName": "Sentry", "implicit": true, "declAttributes": [ + "Final", "ObjC" ], "accessorKind": "set" @@ -47323,43 +46542,22 @@ }, { "kind": "Var", - "name": "tags", - "printedName": "tags", + "name": "level", + "printedName": "level", "children": [ { "kind": "TypeNominal", - "name": "Optional", - "printedName": "[Swift.String : Any]?", - "children": [ - { - "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Any]", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "Any" - } - ], - "usr": "s:SD" - } - ], - "usr": "s:Sq" + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)tags", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC4tagsSDySSypGSgvp", + "usr": "c:@M@Sentry@objc(cs)SentryLog(py)level", + "mangledName": "$s6Sentry0A3LogC5levelAC5LevelOvp", "moduleName": "Sentry", "declAttributes": [ - "HasInitialValue", + "Final", "ObjC", "HasStorage" ], @@ -47372,38 +46570,18 @@ "children": [ { "kind": "TypeNominal", - "name": "Optional", - "printedName": "[Swift.String : Any]?", - "children": [ - { - "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Any]", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "Any" - } - ], - "usr": "s:SD" - } - ], - "usr": "s:Sq" + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)tags", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC4tagsSDySSypGSgvg", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)level", + "mangledName": "$s6Sentry0A3LogC5levelAC5LevelOvg", "moduleName": "Sentry", "implicit": true, "declAttributes": [ + "Final", "ObjC" ], "accessorKind": "get" @@ -47420,38 +46598,18 @@ }, { "kind": "TypeNominal", - "name": "Optional", - "printedName": "[Swift.String : Any]?", - "children": [ - { - "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Any]", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "Any" - } - ], - "usr": "s:SD" - } - ], - "usr": "s:Sq" + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setTags:", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC4tagsSDySSypGSgvs", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)setLevel:", + "mangledName": "$s6Sentry0A3LogC5levelAC5LevelOvs", "moduleName": "Sentry", "implicit": true, "declAttributes": [ + "Final", "ObjC" ], "accessorKind": "set" @@ -47460,48 +46618,22 @@ }, { "kind": "Var", - "name": "onFormOpen", - "printedName": "onFormOpen", + "name": "body", + "printedName": "body", "children": [ { "kind": "TypeNominal", - "name": "Optional", - "printedName": "(() -> Swift.Void)?", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "() -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - } - ], - "usr": "s:Sq" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)onFormOpen", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10onFormOpenyycSgvp", + "usr": "c:@M@Sentry@objc(cs)SentryLog(py)body", + "mangledName": "$s6Sentry0A3LogC4bodySSvp", "moduleName": "Sentry", "declAttributes": [ - "HasInitialValue", + "Final", "ObjC", "HasStorage" ], @@ -47514,43 +46646,18 @@ "children": [ { "kind": "TypeNominal", - "name": "Optional", - "printedName": "(() -> Swift.Void)?", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "() -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - } - ], - "usr": "s:Sq" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)onFormOpen", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10onFormOpenyycSgvg", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)body", + "mangledName": "$s6Sentry0A3LogC4bodySSvg", "moduleName": "Sentry", "implicit": true, "declAttributes": [ + "Final", "ObjC" ], "accessorKind": "get" @@ -47567,43 +46674,18 @@ }, { "kind": "TypeNominal", - "name": "Optional", - "printedName": "(() -> Swift.Void)?", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "() -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - } - ], - "usr": "s:Sq" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setOnFormOpen:", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10onFormOpenyycSgvs", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)setBody:", + "mangledName": "$s6Sentry0A3LogC4bodySSvs", "moduleName": "Sentry", "implicit": true, "declAttributes": [ + "Final", "ObjC" ], "accessorKind": "set" @@ -47612,48 +46694,36 @@ }, { "kind": "Var", - "name": "onFormClose", - "printedName": "onFormClose", + "name": "attributes", + "printedName": "attributes", "children": [ { "kind": "TypeNominal", - "name": "Optional", - "printedName": "(() -> Swift.Void)?", + "name": "Dictionary", + "printedName": "[Swift.String : Sentry.SentryLog.Attribute]", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "() -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" } ], - "usr": "s:Sq" + "usr": "s:SD" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)onFormClose", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC11onFormCloseyycSgvp", + "usr": "c:@M@Sentry@objc(cs)SentryLog(py)attributes", + "mangledName": "$s6Sentry0A3LogC10attributesSDySSAC9AttributeCGvp", "moduleName": "Sentry", "declAttributes": [ - "HasInitialValue", + "Final", "ObjC", "HasStorage" ], @@ -47666,43 +46736,32 @@ "children": [ { "kind": "TypeNominal", - "name": "Optional", - "printedName": "(() -> Swift.Void)?", + "name": "Dictionary", + "printedName": "[Swift.String : Sentry.SentryLog.Attribute]", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "() -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" } ], - "usr": "s:Sq" + "usr": "s:SD" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)onFormClose", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC11onFormCloseyycSgvg", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)attributes", + "mangledName": "$s6Sentry0A3LogC10attributesSDySSAC9AttributeCGvg", "moduleName": "Sentry", "implicit": true, "declAttributes": [ + "Final", "ObjC" ], "accessorKind": "get" @@ -47719,43 +46778,32 @@ }, { "kind": "TypeNominal", - "name": "Optional", - "printedName": "(() -> Swift.Void)?", + "name": "Dictionary", + "printedName": "[Swift.String : Sentry.SentryLog.Attribute]", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "() -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" } ], - "usr": "s:Sq" + "usr": "s:SD" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setOnFormClose:", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC11onFormCloseyycSgvs", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)setAttributes:", + "mangledName": "$s6Sentry0A3LogC10attributesSDySSAC9AttributeCGvs", "moduleName": "Sentry", "implicit": true, "declAttributes": [ + "Final", "ObjC" ], "accessorKind": "set" @@ -47764,62 +46812,31 @@ }, { "kind": "Var", - "name": "onSubmitSuccess", - "printedName": "onSubmitSuccess", + "name": "severityNumber", + "printedName": "severityNumber", "children": [ { "kind": "TypeNominal", "name": "Optional", - "printedName": "(([Swift.String : Any]) -> Swift.Void)?", + "printedName": "Foundation.NSNumber?", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "([Swift.String : Any]) -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Any]", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "Any" - } - ], - "usr": "s:SD" - } - ] + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } ], "usr": "s:Sq" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)onSubmitSuccess", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15onSubmitSuccessySDySSypGcSgvp", + "usr": "c:@M@Sentry@objc(cs)SentryLog(py)severityNumber", + "mangledName": "$s6Sentry0A3LogC14severityNumberSo8NSNumberCSgvp", "moduleName": "Sentry", "declAttributes": [ "HasInitialValue", + "Final", "ObjC", "HasStorage" ], @@ -47833,56 +46850,25 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "(([Swift.String : Any]) -> Swift.Void)?", + "printedName": "Foundation.NSNumber?", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "([Swift.String : Any]) -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Any]", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "Any" - } - ], - "usr": "s:SD" - } - ] + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } ], "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)onSubmitSuccess", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15onSubmitSuccessySDySSypGcSgvg", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)severityNumber", + "mangledName": "$s6Sentry0A3LogC14severityNumberSo8NSNumberCSgvg", "moduleName": "Sentry", "implicit": true, "declAttributes": [ + "Final", "ObjC" ], "accessorKind": "get" @@ -47900,56 +46886,25 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "(([Swift.String : Any]) -> Swift.Void)?", + "printedName": "Foundation.NSNumber?", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "([Swift.String : Any]) -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "Dictionary", - "printedName": "[Swift.String : Any]", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - }, - { - "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "Any" - } - ], - "usr": "s:SD" - } - ] + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" } ], "usr": "s:Sq" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setOnSubmitSuccess:", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15onSubmitSuccessySDySSypGcSgvs", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)setSeverityNumber:", + "mangledName": "$s6Sentry0A3LogC14severityNumberSo8NSNumberCSgvs", "moduleName": "Sentry", "implicit": true, "declAttributes": [ + "Final", "ObjC" ], "accessorKind": "set" @@ -47957,659 +46912,329 @@ ] }, { - "kind": "Var", - "name": "onSubmitError", - "printedName": "onSubmitError", + "kind": "TypeDecl", + "name": "Level", + "printedName": "Level", "children": [ { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "((any Swift.Error) -> Swift.Void)?", + "kind": "Var", + "name": "trace", + "printedName": "trace", "children": [ { "kind": "TypeFunc", "name": "Function", - "printedName": "(any Swift.Error) -> Swift.Void", + "printedName": "(Sentry.SentryLog.Level.Type) -> Sentry.SentryLog.Level", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLog.Level.Type", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" } ] - }, - { - "kind": "TypeNominal", - "name": "Error", - "printedName": "any Swift.Error", - "usr": "s:s5ErrorP" } ] } ], - "usr": "s:Sq" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)onSubmitError", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13onSubmitErrorys0G0_pcSgvp", - "moduleName": "Sentry", - "declAttributes": [ - "HasInitialValue", - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ + "declKind": "EnumElement", + "usr": "s:6Sentry0A3LogC5LevelO5traceyA2EmF", + "mangledName": "$s6Sentry0A3LogC5LevelO5traceyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "Var", + "name": "debug", + "printedName": "debug", "children": [ { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "((any Swift.Error) -> Swift.Void)?", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog.Level.Type) -> Sentry.SentryLog.Level", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(any Swift.Error) -> Swift.Void", + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLog.Level.Type", "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, { "kind": "TypeNominal", - "name": "Error", - "printedName": "any Swift.Error", - "usr": "s:s5ErrorP" + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" } ] } - ], - "usr": "s:Sq" + ] } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)onSubmitError", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13onSubmitErrorys0G0_pcSgvg", + "declKind": "EnumElement", + "usr": "s:6Sentry0A3LogC5LevelO5debugyA2EmF", + "mangledName": "$s6Sentry0A3LogC5LevelO5debugyA2EmF", "moduleName": "Sentry", - "implicit": true, "declAttributes": [ "ObjC" - ], - "accessorKind": "get" + ] }, { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", + "kind": "Var", + "name": "info", + "printedName": "info", "children": [ { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - }, - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "((any Swift.Error) -> Swift.Void)?", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog.Level.Type) -> Sentry.SentryLog.Level", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(any Swift.Error) -> Swift.Void", + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLog.Level.Type", "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, { "kind": "TypeNominal", - "name": "Error", - "printedName": "any Swift.Error", - "usr": "s:s5ErrorP" + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" } ] } - ], - "usr": "s:Sq" + ] } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setOnSubmitError:", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13onSubmitErrorys0G0_pcSgvs", + "declKind": "EnumElement", + "usr": "s:6Sentry0A3LogC5LevelO4infoyA2EmF", + "mangledName": "$s6Sentry0A3LogC5LevelO4infoyA2EmF", "moduleName": "Sentry", - "implicit": true, "declAttributes": [ "ObjC" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Var", - "name": "configureTheme", - "printedName": "configureTheme", - "children": [ + ] + }, { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "kind": "Var", + "name": "warn", + "printedName": "warn", "children": [ { "kind": "TypeFunc", "name": "Function", - "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "printedName": "(Sentry.SentryLog.Level.Type) -> Sentry.SentryLog.Level", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLog.Level.Type", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" } ] - }, - { - "kind": "TypeNominal", - "name": "SentryUserFeedbackThemeConfiguration", - "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" } ] } ], - "usr": "s:Sq" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)configureTheme", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC14configureThemeyAA0abcfD0CcSgvp", - "moduleName": "Sentry", - "declAttributes": [ - "HasInitialValue", - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ + "declKind": "EnumElement", + "usr": "s:6Sentry0A3LogC5LevelO4warnyA2EmF", + "mangledName": "$s6Sentry0A3LogC5LevelO4warnyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", + "kind": "Var", + "name": "error", + "printedName": "error", "children": [ { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog.Level.Type) -> Sentry.SentryLog.Level", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLog.Level.Type", "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, { "kind": "TypeNominal", - "name": "SentryUserFeedbackThemeConfiguration", - "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" } ] } - ], - "usr": "s:Sq" + ] } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)configureTheme", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC14configureThemeyAA0abcfD0CcSgvg", + "declKind": "EnumElement", + "usr": "s:6Sentry0A3LogC5LevelO5erroryA2EmF", + "mangledName": "$s6Sentry0A3LogC5LevelO5erroryA2EmF", "moduleName": "Sentry", - "implicit": true, "declAttributes": [ "ObjC" - ], - "accessorKind": "get" + ] }, { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - }, - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "SentryUserFeedbackThemeConfiguration", - "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" - } - ] - } - ], - "usr": "s:Sq" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setConfigureTheme:", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC14configureThemeyAA0abcfD0CcSgvs", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Var", - "name": "configureDarkTheme", - "printedName": "configureDarkTheme", - "children": [ - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "kind": "Var", + "name": "fatal", + "printedName": "fatal", "children": [ { "kind": "TypeFunc", "name": "Function", - "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "printedName": "(Sentry.SentryLog.Level.Type) -> Sentry.SentryLog.Level", "children": [ { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" }, { "kind": "TypeNominal", - "name": "SentryUserFeedbackThemeConfiguration", - "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" - } - ] - } - ], - "usr": "s:Sq" - } - ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)configureDarkTheme", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC18configureDarkThemeyAA0abcgD0CcSgvp", - "moduleName": "Sentry", - "declAttributes": [ - "HasInitialValue", - "ObjC", - "HasStorage" - ], - "hasStorage": true, - "accessors": [ - { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Optional", - "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "name": "Metatype", + "printedName": "Sentry.SentryLog.Level.Type", "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, { "kind": "TypeNominal", - "name": "SentryUserFeedbackThemeConfiguration", - "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" } ] } - ], - "usr": "s:Sq" + ] } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)configureDarkTheme", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC18configureDarkThemeyAA0abcgD0CcSgvg", + "declKind": "EnumElement", + "usr": "s:6Sentry0A3LogC5LevelO5fatalyA2EmF", + "mangledName": "$s6Sentry0A3LogC5LevelO5fatalyA2EmF", "moduleName": "Sentry", - "implicit": true, "declAttributes": [ "ObjC" - ], - "accessorKind": "get" + ] }, { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", + "kind": "Constructor", + "name": "init", + "printedName": "init(value:)", "children": [ { "kind": "TypeNominal", - "name": "Void", - "printedName": "()" + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" }, { "kind": "TypeNominal", - "name": "Optional", - "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", - "children": [ - { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", - "children": [ - { - "kind": "TypeNameAlias", - "name": "Void", - "printedName": "Swift.Void", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - } - ] - }, - { - "kind": "TypeNominal", - "name": "SentryUserFeedbackThemeConfiguration", - "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" - } - ] - } - ], - "usr": "s:Sq" + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setConfigureDarkTheme:", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC18configureDarkThemeyAA0abcgD0CcSgvs", + "declKind": "Constructor", + "usr": "s:6Sentry0A3LogC5LevelO5valueAESS_tKcfc", + "mangledName": "$s6Sentry0A3LogC5LevelO5valueAESS_tKcfc", "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" - } - ] - }, - { - "kind": "Constructor", - "name": "init", - "printedName": "init()", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryUserFeedbackConfiguration", - "printedName": "Sentry.SentryUserFeedbackConfiguration", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration" - } - ], - "declKind": "Constructor", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)init", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationCACycfc", - "moduleName": "Sentry", - "overriding": true, - "objc_name": "init", - "declAttributes": [ - "ObjC", - "Dynamic", - "Override" - ], - "init_kind": "Designated" - } - ], - "declKind": "Class", - "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration", - "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC", - "moduleName": "Sentry", - "intro_iOS": "13.0", - "declAttributes": [ - "Available", - "ObjCMembers", - "Available", - "ObjC" - ], - "superclassUsr": "c:objc(cs)NSObject", - "inheritsConvenienceInitializers": true, - "superclassNames": [ - "ObjectiveC.NSObject" - ], - "conformances": [ - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "NSObjectProtocol", - "printedName": "NSObjectProtocol", - "usr": "c:objc(pl)NSObject" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "CVarArg", - "printedName": "CVarArg", - "usr": "s:s7CVarArgP", - "mangledName": "$ss7CVarArgP" - }, - { - "kind": "Conformance", - "name": "CustomStringConvertible", - "printedName": "CustomStringConvertible", - "usr": "s:s23CustomStringConvertibleP", - "mangledName": "$ss23CustomStringConvertibleP" - }, - { - "kind": "Conformance", - "name": "CustomDebugStringConvertible", - "printedName": "CustomDebugStringConvertible", - "usr": "s:s28CustomDebugStringConvertibleP", - "mangledName": "$ss28CustomDebugStringConvertibleP" - } - ] - }, - { - "kind": "TypeDecl", - "name": "SentryProfileOptions", - "printedName": "SentryProfileOptions", - "children": [ - { - "kind": "TypeDecl", - "name": "SentryProfileLifecycle", - "printedName": "SentryProfileLifecycle", - "children": [ + "throwing": true, + "init_kind": "Designated" + }, { "kind": "Var", - "name": "manual", - "printedName": "manual", + "name": "value", + "printedName": "value", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryProfileOptions.SentryProfileLifecycle.Type) -> Sentry.SentryProfileOptions.SentryProfileLifecycle", + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A3LogC5LevelO5valueSSvp", + "mangledName": "$s6Sentry0A3LogC5LevelO5valueSSvp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", "children": [ { "kind": "TypeNominal", - "name": "SentryProfileLifecycle", - "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryProfileLifecycle", - "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" - } - ] + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } - ] + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A3LogC5LevelO5valueSSvg", + "mangledName": "$s6Sentry0A3LogC5LevelO5valueSSvg", + "moduleName": "Sentry", + "accessorKind": "get" } - ], - "declKind": "EnumElement", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO6manualyA2EmF", - "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO6manualyA2EmF", - "moduleName": "Sentry", - "declAttributes": [ - "ObjC" ] }, { - "kind": "Var", - "name": "trace", - "printedName": "trace", + "kind": "Function", + "name": "toSeverityNumber", + "printedName": "toSeverityNumber()", "children": [ { - "kind": "TypeFunc", - "name": "Function", - "printedName": "(Sentry.SentryProfileOptions.SentryProfileLifecycle.Type) -> Sentry.SentryProfileOptions.SentryProfileLifecycle", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryProfileLifecycle", - "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" - }, - { - "kind": "TypeNominal", - "name": "Metatype", - "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle.Type", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryProfileLifecycle", - "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" - } - ] - } - ] + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" } ], - "declKind": "EnumElement", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO5traceyA2EmF", - "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO5traceyA2EmF", + "declKind": "Func", + "usr": "s:6Sentry0A3LogC5LevelO16toSeverityNumberSiyF", + "mangledName": "$s6Sentry0A3LogC5LevelO16toSeverityNumberSiyF", "moduleName": "Sentry", - "declAttributes": [ - "ObjC" - ] + "funcSelfKind": "NonMutating" }, { "kind": "Constructor", @@ -48619,13 +47244,13 @@ { "kind": "TypeNominal", "name": "Optional", - "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle?", + "printedName": "Sentry.SentryLog.Level?", "children": [ { "kind": "TypeNominal", - "name": "SentryProfileLifecycle", - "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" } ], "usr": "s:Sq" @@ -48638,8 +47263,8 @@ } ], "declKind": "Constructor", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueAESgSi_tcfc", - "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueAESgSi_tcfc", + "usr": "s:6Sentry0A3LogC5LevelO8rawValueAESgSi_tcfc", + "mangledName": "$s6Sentry0A3LogC5LevelO8rawValueAESgSi_tcfc", "moduleName": "Sentry", "init_kind": "Designated" }, @@ -48656,8 +47281,8 @@ } ], "declKind": "TypeAlias", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO8RawValuea", - "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO8RawValuea", + "usr": "s:6Sentry0A3LogC5LevelO8RawValuea", + "mangledName": "$s6Sentry0A3LogC5LevelO8RawValuea", "moduleName": "Sentry" }, { @@ -48673,8 +47298,8 @@ } ], "declKind": "Var", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueSivp", - "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueSivp", + "usr": "s:6Sentry0A3LogC5LevelO8rawValueSivp", + "mangledName": "$s6Sentry0A3LogC5LevelO8rawValueSivp", "moduleName": "Sentry", "accessors": [ { @@ -48690,8 +47315,8 @@ } ], "declKind": "Accessor", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueSivg", - "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueSivg", + "usr": "s:6Sentry0A3LogC5LevelO8rawValueSivg", + "mangledName": "$s6Sentry0A3LogC5LevelO8rawValueSivg", "moduleName": "Sentry", "accessorKind": "get" } @@ -48699,239 +47324,7339 @@ } ], "declKind": "Enum", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO", - "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO", + "usr": "s:6Sentry0A3LogC5LevelO", + "mangledName": "$s6Sentry0A3LogC5LevelO", + "moduleName": "Sentry", + "objc_name": "SentryStructuredLogLevel", + "declAttributes": [ + "ObjC" + ], + "isFromExtension": true, + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryLog.Level.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, + { + "kind": "TypeDecl", + "name": "Attribute", + "printedName": "Attribute", + "children": [ + { + "kind": "Var", + "name": "type", + "printedName": "type", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A3LogC9AttributeC4typeSSvp", + "mangledName": "$s6Sentry0A3LogC9AttributeC4typeSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A3LogC9AttributeC4typeSSvg", + "mangledName": "$s6Sentry0A3LogC9AttributeC4typeSSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "value", + "printedName": "value", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A3LogC9AttributeC5valueypvp", + "mangledName": "$s6Sentry0A3LogC9AttributeC5valueypvp", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A3LogC9AttributeC5valueypvg", + "mangledName": "$s6Sentry0A3LogC9AttributeC5valueypvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(string:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A3LogC9AttributeC6stringAESS_tcfc", + "mangledName": "$s6Sentry0A3LogC9AttributeC6stringAESS_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithString:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(boolean:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A3LogC9AttributeC7booleanAESb_tcfc", + "mangledName": "$s6Sentry0A3LogC9AttributeC7booleanAESb_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithBoolean:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(integer:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A3LogC9AttributeC7integerAESi_tcfc", + "mangledName": "$s6Sentry0A3LogC9AttributeC7integerAESi_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithInteger:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(double:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" + }, + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A3LogC9AttributeC6doubleAESd_tcfc", + "mangledName": "$s6Sentry0A3LogC9AttributeC6doubleAESd_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithDouble:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(float:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" + }, + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A3LogC9AttributeC5floatAESf_tcfc", + "mangledName": "$s6Sentry0A3LogC9AttributeC5floatAESf_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithFloat:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "s:6Sentry0A3LogC9AttributeC", + "mangledName": "$s6Sentry0A3LogC9AttributeC", + "moduleName": "Sentry", + "objc_name": "SentryStructuredLogAttribute", + "declAttributes": [ + "Final", + "ObjCMembers", + "ObjC" + ], + "isFromExtension": true, + "superclassUsr": "c:objc(cs)NSObject", + "hasMissingDesignatedInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryLog", + "mangledName": "$s6Sentry0A3LogC", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "hasMissingDesignatedInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryLogger", + "printedName": "SentryLogger", + "children": [ + { + "kind": "Function", + "name": "trace", + "printedName": "trace(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "hasDefaultArg": true, + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A6LoggerC5trace_10attributesyAA0A10LogMessageV_SDySSypGtF", + "mangledName": "$s6Sentry0A6LoggerC5trace_10attributesyAA0A10LogMessageV_SDySSypGtF", + "moduleName": "Sentry", + "declAttributes": [ + "Final" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "trace", + "printedName": "trace(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)trace:", + "mangledName": "$s6Sentry0A6LoggerC5traceyySSF", + "moduleName": "Sentry", + "objc_name": "trace:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "trace", + "printedName": "trace(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)trace:attributes:", + "mangledName": "$s6Sentry0A6LoggerC5trace_10attributesySS_SDySSypGtF", + "moduleName": "Sentry", + "objc_name": "trace:attributes:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "debug", + "printedName": "debug(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "hasDefaultArg": true, + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A6LoggerC5debug_10attributesyAA0A10LogMessageV_SDySSypGtF", + "mangledName": "$s6Sentry0A6LoggerC5debug_10attributesyAA0A10LogMessageV_SDySSypGtF", + "moduleName": "Sentry", + "declAttributes": [ + "Final" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "debug", + "printedName": "debug(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)debug:", + "mangledName": "$s6Sentry0A6LoggerC5debugyySSF", + "moduleName": "Sentry", + "objc_name": "debug:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "debug", + "printedName": "debug(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)debug:attributes:", + "mangledName": "$s6Sentry0A6LoggerC5debug_10attributesySS_SDySSypGtF", + "moduleName": "Sentry", + "objc_name": "debug:attributes:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "info", + "printedName": "info(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "hasDefaultArg": true, + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A6LoggerC4info_10attributesyAA0A10LogMessageV_SDySSypGtF", + "mangledName": "$s6Sentry0A6LoggerC4info_10attributesyAA0A10LogMessageV_SDySSypGtF", + "moduleName": "Sentry", + "declAttributes": [ + "Final" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "info", + "printedName": "info(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)info:", + "mangledName": "$s6Sentry0A6LoggerC4infoyySSF", + "moduleName": "Sentry", + "objc_name": "info:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "info", + "printedName": "info(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)info:attributes:", + "mangledName": "$s6Sentry0A6LoggerC4info_10attributesySS_SDySSypGtF", + "moduleName": "Sentry", + "objc_name": "info:attributes:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "warn", + "printedName": "warn(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "hasDefaultArg": true, + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A6LoggerC4warn_10attributesyAA0A10LogMessageV_SDySSypGtF", + "mangledName": "$s6Sentry0A6LoggerC4warn_10attributesyAA0A10LogMessageV_SDySSypGtF", + "moduleName": "Sentry", + "declAttributes": [ + "Final" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "warn", + "printedName": "warn(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)warn:", + "mangledName": "$s6Sentry0A6LoggerC4warnyySSF", + "moduleName": "Sentry", + "objc_name": "warn:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "warn", + "printedName": "warn(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)warn:attributes:", + "mangledName": "$s6Sentry0A6LoggerC4warn_10attributesySS_SDySSypGtF", + "moduleName": "Sentry", + "objc_name": "warn:attributes:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "error", + "printedName": "error(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "hasDefaultArg": true, + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A6LoggerC5error_10attributesyAA0A10LogMessageV_SDySSypGtF", + "mangledName": "$s6Sentry0A6LoggerC5error_10attributesyAA0A10LogMessageV_SDySSypGtF", + "moduleName": "Sentry", + "declAttributes": [ + "Final" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "error", + "printedName": "error(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)error:", + "mangledName": "$s6Sentry0A6LoggerC5erroryySSF", + "moduleName": "Sentry", + "objc_name": "error:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "error", + "printedName": "error(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)error:attributes:", + "mangledName": "$s6Sentry0A6LoggerC5error_10attributesySS_SDySSypGtF", + "moduleName": "Sentry", + "objc_name": "error:attributes:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "fatal", + "printedName": "fatal(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "hasDefaultArg": true, + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A6LoggerC5fatal_10attributesyAA0A10LogMessageV_SDySSypGtF", + "mangledName": "$s6Sentry0A6LoggerC5fatal_10attributesyAA0A10LogMessageV_SDySSypGtF", + "moduleName": "Sentry", + "declAttributes": [ + "Final" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "fatal", + "printedName": "fatal(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)fatal:", + "mangledName": "$s6Sentry0A6LoggerC5fatalyySSF", + "moduleName": "Sentry", + "objc_name": "fatal:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "fatal", + "printedName": "fatal(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)fatal:attributes:", + "mangledName": "$s6Sentry0A6LoggerC5fatal_10attributesySS_SDySSypGtF", + "moduleName": "Sentry", + "objc_name": "fatal:attributes:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryLogger", + "mangledName": "$s6Sentry0A6LoggerC", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryReplayOptions", + "printedName": "SentryReplayOptions", + "children": [ + { + "kind": "TypeDecl", + "name": "DefaultValues", + "printedName": "DefaultValues", + "children": [ + { + "kind": "Var", + "name": "sessionSampleRate", + "printedName": "sessionSampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17sessionSampleRateSfvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17sessionSampleRateSfvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17sessionSampleRateSfvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17sessionSampleRateSfvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "onErrorSampleRate", + "printedName": "onErrorSampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17onErrorSampleRateSfvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17onErrorSampleRateSfvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17onErrorSampleRateSfvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17onErrorSampleRateSfvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskAllText", + "printedName": "maskAllText", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC11maskAllTextSbvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC11maskAllTextSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC11maskAllTextSbvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC11maskAllTextSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskAllImages", + "printedName": "maskAllImages", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC13maskAllImagesSbvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC13maskAllImagesSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC13maskAllImagesSbvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC13maskAllImagesSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "enableViewRendererV2", + "printedName": "enableViewRendererV2", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC20enableViewRendererV2SbvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC20enableViewRendererV2SbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC20enableViewRendererV2SbvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC20enableViewRendererV2SbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "enableFastViewRendering", + "printedName": "enableFastViewRendering", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC23enableFastViewRenderingSbvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC23enableFastViewRenderingSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC23enableFastViewRenderingSbvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC23enableFastViewRenderingSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "quality", + "printedName": "quality", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC7qualityAC0aB7QualityOvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC7qualityAC0aB7QualityOvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC7qualityAC0aB7QualityOvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC7qualityAC0aB7QualityOvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskedViewClasses", + "printedName": "maskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17maskedViewClassesSayyXlXpGvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17maskedViewClassesSayyXlXpGvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17maskedViewClassesSayyXlXpGvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17maskedViewClassesSayyXlXpGvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "unmaskedViewClasses", + "printedName": "unmaskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC19unmaskedViewClassesSayyXlXpGvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC19unmaskedViewClassesSayyXlXpGvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC19unmaskedViewClassesSayyXlXpGvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC19unmaskedViewClassesSayyXlXpGvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + } + ], + "declKind": "Class", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC", + "moduleName": "Sentry", + "hasMissingDesignatedInitializers": true, + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryReplayQuality", + "printedName": "SentryReplayQuality", + "children": [ + { + "kind": "Var", + "name": "low", + "printedName": "low", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryReplayOptions.SentryReplayQuality.Type) -> Sentry.SentryReplayOptions.SentryReplayQuality", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO3lowyA2EmF", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO3lowyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "medium", + "printedName": "medium", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryReplayOptions.SentryReplayQuality.Type) -> Sentry.SentryReplayOptions.SentryReplayQuality", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO6mediumyA2EmF", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO6mediumyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "high", + "printedName": "high", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryReplayOptions.SentryReplayQuality.Type) -> Sentry.SentryReplayOptions.SentryReplayQuality", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO4highyA2EmF", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO4highyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "description", + "printedName": "description", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO11descriptionSSvp", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO11descriptionSSvp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO11descriptionSSvg", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO11descriptionSSvg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueAESgSi_tcfc", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueAESgSi_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO8RawValuea", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO8RawValuea", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueSivp", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueSivp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueSivg", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueSivg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + } + ], + "declKind": "Enum", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, + { + "kind": "Var", + "name": "sessionSampleRate", + "printedName": "sessionSampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)sessionSampleRate", + "mangledName": "$s6Sentry0A13ReplayOptionsC17sessionSampleRateSfvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)sessionSampleRate", + "mangledName": "$s6Sentry0A13ReplayOptionsC17sessionSampleRateSfvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setSessionSampleRate:", + "mangledName": "$s6Sentry0A13ReplayOptionsC17sessionSampleRateSfvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "onErrorSampleRate", + "printedName": "onErrorSampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)onErrorSampleRate", + "mangledName": "$s6Sentry0A13ReplayOptionsC17onErrorSampleRateSfvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)onErrorSampleRate", + "mangledName": "$s6Sentry0A13ReplayOptionsC17onErrorSampleRateSfvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setOnErrorSampleRate:", + "mangledName": "$s6Sentry0A13ReplayOptionsC17onErrorSampleRateSfvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "maskAllText", + "printedName": "maskAllText", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)maskAllText", + "mangledName": "$s6Sentry0A13ReplayOptionsC11maskAllTextSbvp", + "moduleName": "Sentry", + "objc_name": "maskAllText", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)maskAllText", + "mangledName": "$s6Sentry0A13ReplayOptionsC11maskAllTextSbvg", + "moduleName": "Sentry", + "implicit": true, + "objc_name": "maskAllText", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setMaskAllText:", + "mangledName": "$s6Sentry0A13ReplayOptionsC11maskAllTextSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "maskAllImages", + "printedName": "maskAllImages", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)maskAllImages", + "mangledName": "$s6Sentry0A13ReplayOptionsC13maskAllImagesSbvp", + "moduleName": "Sentry", + "objc_name": "maskAllImages", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)maskAllImages", + "mangledName": "$s6Sentry0A13ReplayOptionsC13maskAllImagesSbvg", + "moduleName": "Sentry", + "implicit": true, + "objc_name": "maskAllImages", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setMaskAllImages:", + "mangledName": "$s6Sentry0A13ReplayOptionsC13maskAllImagesSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "quality", + "printedName": "quality", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)quality", + "mangledName": "$s6Sentry0A13ReplayOptionsC7qualityAC0aB7QualityOvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)quality", + "mangledName": "$s6Sentry0A13ReplayOptionsC7qualityAC0aB7QualityOvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setQuality:", + "mangledName": "$s6Sentry0A13ReplayOptionsC7qualityAC0aB7QualityOvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "maskedViewClasses", + "printedName": "maskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)maskedViewClasses", + "mangledName": "$s6Sentry0A13ReplayOptionsC17maskedViewClassesSayyXlXpGvp", + "moduleName": "Sentry", + "objc_name": "maskedViewClasses", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)maskedViewClasses", + "mangledName": "$s6Sentry0A13ReplayOptionsC17maskedViewClassesSayyXlXpGvg", + "moduleName": "Sentry", + "implicit": true, + "objc_name": "maskedViewClasses", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setMaskedViewClasses:", + "mangledName": "$s6Sentry0A13ReplayOptionsC17maskedViewClassesSayyXlXpGvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "unmaskedViewClasses", + "printedName": "unmaskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)unmaskedViewClasses", + "mangledName": "$s6Sentry0A13ReplayOptionsC19unmaskedViewClassesSayyXlXpGvp", + "moduleName": "Sentry", + "objc_name": "unmaskedViewClasses", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)unmaskedViewClasses", + "mangledName": "$s6Sentry0A13ReplayOptionsC19unmaskedViewClassesSayyXlXpGvg", + "moduleName": "Sentry", + "implicit": true, + "objc_name": "unmaskedViewClasses", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setUnmaskedViewClasses:", + "mangledName": "$s6Sentry0A13ReplayOptionsC19unmaskedViewClassesSayyXlXpGvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableExperimentalViewRenderer", + "printedName": "enableExperimentalViewRenderer", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)enableExperimentalViewRenderer", + "mangledName": "$s6Sentry0A13ReplayOptionsC30enableExperimentalViewRendererSbvp", + "moduleName": "Sentry", + "deprecated": true, + "declAttributes": [ + "Available", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)enableExperimentalViewRenderer", + "mangledName": "$s6Sentry0A13ReplayOptionsC30enableExperimentalViewRendererSbvg", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setEnableExperimentalViewRenderer:", + "mangledName": "$s6Sentry0A13ReplayOptionsC30enableExperimentalViewRendererSbvs", + "moduleName": "Sentry", + "objc_name": "setEnableExperimentalViewRenderer:", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableViewRendererV2", + "printedName": "enableViewRendererV2", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)enableViewRendererV2", + "mangledName": "$s6Sentry0A13ReplayOptionsC20enableViewRendererV2Sbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)enableViewRendererV2", + "mangledName": "$s6Sentry0A13ReplayOptionsC20enableViewRendererV2Sbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setEnableViewRendererV2:", + "mangledName": "$s6Sentry0A13ReplayOptionsC20enableViewRendererV2Sbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableFastViewRendering", + "printedName": "enableFastViewRendering", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)enableFastViewRendering", + "mangledName": "$s6Sentry0A13ReplayOptionsC23enableFastViewRenderingSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)enableFastViewRendering", + "mangledName": "$s6Sentry0A13ReplayOptionsC23enableFastViewRenderingSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setEnableFastViewRendering:", + "mangledName": "$s6Sentry0A13ReplayOptionsC23enableFastViewRenderingSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayOptions", + "printedName": "Sentry.SentryReplayOptions", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)init", + "mangledName": "$s6Sentry0A13ReplayOptionsCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Convenience" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(sessionSampleRate:onErrorSampleRate:maskAllText:maskAllImages:enableViewRendererV2:enableFastViewRendering:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayOptions", + "printedName": "Sentry.SentryReplayOptions", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions" + }, + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "hasDefaultArg": true, + "usr": "s:Sf" + }, + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "hasDefaultArg": true, + "usr": "s:Sf" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)initWithSessionSampleRate:onErrorSampleRate:maskAllText:maskAllImages:enableViewRendererV2:enableFastViewRendering:", + "mangledName": "$s6Sentry0A13ReplayOptionsC17sessionSampleRate07onErroreF011maskAllText0iJ6Images20enableViewRendererV20m4FastN9RenderingACSf_SfS4btcfc", + "moduleName": "Sentry", + "objc_name": "initWithSessionSampleRate:onErrorSampleRate:maskAllText:maskAllImages:enableViewRendererV2:enableFastViewRendering:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Convenience" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions", + "mangledName": "$s6Sentry0A13ReplayOptionsC", + "moduleName": "Sentry", + "declAttributes": [ + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "hasMissingDesignatedInitializers": true, + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "SentryRedactOptions", + "printedName": "SentryRedactOptions", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions", + "mangledName": "$s6Sentry0A13RedactOptionsP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryEventDecoder", + "printedName": "SentryEventDecoder", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryEventDecoder", + "printedName": "Sentry.SentryEventDecoder", + "usr": "c:@M@Sentry@objc(cs)SentryEventDecoder" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryEventDecoder(im)init", + "mangledName": "$s6Sentry0A12EventDecoderCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryEventDecoder", + "mangledName": "$s6Sentry0A12EventDecoderC", + "moduleName": "Sentry", + "declAttributes": [ + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryUserFeedbackConfiguration", + "printedName": "SentryUserFeedbackConfiguration", + "children": [ + { + "kind": "Var", + "name": "animations", + "printedName": "animations", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)animations", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10animationsSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)animations", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10animationsSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setAnimations:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10animationsSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "configureWidget", + "printedName": "configureWidget", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackWidgetConfiguration", + "printedName": "Sentry.SentryUserFeedbackWidgetConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)configureWidget", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15configureWidgetyAA0abcfD0CcSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackWidgetConfiguration", + "printedName": "Sentry.SentryUserFeedbackWidgetConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)configureWidget", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15configureWidgetyAA0abcfD0CcSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackWidgetConfiguration", + "printedName": "Sentry.SentryUserFeedbackWidgetConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setConfigureWidget:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15configureWidgetyAA0abcfD0CcSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "useShakeGesture", + "printedName": "useShakeGesture", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)useShakeGesture", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15useShakeGestureSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)useShakeGesture", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15useShakeGestureSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setUseShakeGesture:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15useShakeGestureSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "showFormForScreenshots", + "printedName": "showFormForScreenshots", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)showFormForScreenshots", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC22showFormForScreenshotsSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)showFormForScreenshots", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC22showFormForScreenshotsSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setShowFormForScreenshots:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC22showFormForScreenshotsSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "customButton", + "printedName": "customButton", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "UIKit.UIButton?", + "children": [ + { + "kind": "TypeNominal", + "name": "UIButton", + "printedName": "UIKit.UIButton", + "usr": "c:objc(cs)UIButton" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)customButton", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC12customButtonSo8UIButtonCSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "UIKit.UIButton?", + "children": [ + { + "kind": "TypeNominal", + "name": "UIButton", + "printedName": "UIKit.UIButton", + "usr": "c:objc(cs)UIButton" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)customButton", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC12customButtonSo8UIButtonCSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "UIKit.UIButton?", + "children": [ + { + "kind": "TypeNominal", + "name": "UIButton", + "printedName": "UIKit.UIButton", + "usr": "c:objc(cs)UIButton" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setCustomButton:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC12customButtonSo8UIButtonCSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "configureForm", + "printedName": "configureForm", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackFormConfiguration", + "printedName": "Sentry.SentryUserFeedbackFormConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)configureForm", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13configureFormyAA0abcfD0CcSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackFormConfiguration", + "printedName": "Sentry.SentryUserFeedbackFormConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)configureForm", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13configureFormyAA0abcfD0CcSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackFormConfiguration", + "printedName": "Sentry.SentryUserFeedbackFormConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setConfigureForm:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13configureFormyAA0abcfD0CcSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "tags", + "printedName": "tags", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)tags", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC4tagsSDySSypGSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)tags", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC4tagsSDySSypGSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setTags:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC4tagsSDySSypGSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "onFormOpen", + "printedName": "onFormOpen", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(() -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)onFormOpen", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10onFormOpenyycSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(() -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)onFormOpen", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10onFormOpenyycSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(() -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setOnFormOpen:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10onFormOpenyycSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "onFormClose", + "printedName": "onFormClose", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(() -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)onFormClose", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC11onFormCloseyycSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(() -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)onFormClose", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC11onFormCloseyycSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(() -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setOnFormClose:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC11onFormCloseyycSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "onSubmitSuccess", + "printedName": "onSubmitSuccess", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(([Swift.String : Any]) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "([Swift.String : Any]) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)onSubmitSuccess", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15onSubmitSuccessySDySSypGcSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(([Swift.String : Any]) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "([Swift.String : Any]) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)onSubmitSuccess", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15onSubmitSuccessySDySSypGcSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(([Swift.String : Any]) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "([Swift.String : Any]) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setOnSubmitSuccess:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15onSubmitSuccessySDySSypGcSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "onSubmitError", + "printedName": "onSubmitError", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((any Swift.Error) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(any Swift.Error) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)onSubmitError", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13onSubmitErrorys0G0_pcSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((any Swift.Error) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(any Swift.Error) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)onSubmitError", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13onSubmitErrorys0G0_pcSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((any Swift.Error) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(any Swift.Error) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setOnSubmitError:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13onSubmitErrorys0G0_pcSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "configureTheme", + "printedName": "configureTheme", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)configureTheme", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC14configureThemeyAA0abcfD0CcSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)configureTheme", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC14configureThemeyAA0abcfD0CcSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setConfigureTheme:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC14configureThemeyAA0abcfD0CcSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "configureDarkTheme", + "printedName": "configureDarkTheme", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)configureDarkTheme", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC18configureDarkThemeyAA0abcgD0CcSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)configureDarkTheme", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC18configureDarkThemeyAA0abcgD0CcSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setConfigureDarkTheme:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC18configureDarkThemeyAA0abcgD0CcSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackConfiguration", + "printedName": "Sentry.SentryUserFeedbackConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)init", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC", + "moduleName": "Sentry", + "intro_iOS": "13.0", + "declAttributes": [ + "Available", + "ObjCMembers", + "Available", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryProfileOptions", + "printedName": "SentryProfileOptions", + "children": [ + { + "kind": "TypeDecl", + "name": "SentryProfileLifecycle", + "printedName": "SentryProfileLifecycle", + "children": [ + { + "kind": "Var", + "name": "manual", + "printedName": "manual", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryProfileOptions.SentryProfileLifecycle.Type) -> Sentry.SentryProfileOptions.SentryProfileLifecycle", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO6manualyA2EmF", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO6manualyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "trace", + "printedName": "trace", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryProfileOptions.SentryProfileLifecycle.Type) -> Sentry.SentryProfileOptions.SentryProfileLifecycle", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO5traceyA2EmF", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO5traceyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueAESgSi_tcfc", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueAESgSi_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO8RawValuea", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO8RawValuea", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueSivp", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueSivp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueSivg", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueSivg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + } + ], + "declKind": "Enum", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, + { + "kind": "Var", + "name": "lifecycle", + "printedName": "lifecycle", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(py)lifecycle", + "mangledName": "$s6Sentry0A14ProfileOptionsC9lifecycleAC0aB9LifecycleOvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)lifecycle", + "mangledName": "$s6Sentry0A14ProfileOptionsC9lifecycleAC0aB9LifecycleOvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)setLifecycle:", + "mangledName": "$s6Sentry0A14ProfileOptionsC9lifecycleAC0aB9LifecycleOvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "sessionSampleRate", + "printedName": "sessionSampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(py)sessionSampleRate", + "mangledName": "$s6Sentry0A14ProfileOptionsC17sessionSampleRateSfvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)sessionSampleRate", + "mangledName": "$s6Sentry0A14ProfileOptionsC17sessionSampleRateSfvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)setSessionSampleRate:", + "mangledName": "$s6Sentry0A14ProfileOptionsC17sessionSampleRateSfvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "profileAppStarts", + "printedName": "profileAppStarts", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(py)profileAppStarts", + "mangledName": "$s6Sentry0A14ProfileOptionsC16profileAppStartsSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)profileAppStarts", + "mangledName": "$s6Sentry0A14ProfileOptionsC16profileAppStartsSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)setProfileAppStarts:", + "mangledName": "$s6Sentry0A14ProfileOptionsC16profileAppStartsSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileOptions", + "printedName": "Sentry.SentryProfileOptions", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)init", + "mangledName": "$s6Sentry0A14ProfileOptionsCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions", + "mangledName": "$s6Sentry0A14ProfileOptionsC", + "moduleName": "Sentry", + "declAttributes": [ + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryId", + "printedName": "SentryId", + "children": [ + { + "kind": "Var", + "name": "empty", + "printedName": "empty", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryId(cpy)empty", + "mangledName": "$s6Sentry0A2IdC5emptyACvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryId(cm)empty", + "mangledName": "$s6Sentry0A2IdC5emptyACvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "sentryIdString", + "printedName": "sentryIdString", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryId(py)sentryIdString", + "mangledName": "$s6Sentry0A2IdC06sentryB6StringSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)sentryIdString", + "mangledName": "$s6Sentry0A2IdC06sentryB6StringSSvg", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)init", + "mangledName": "$s6Sentry0A2IdCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(uuid:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "UUID", + "printedName": "Foundation.UUID", + "usr": "s:10Foundation4UUIDV" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)initWithUuid:", + "mangledName": "$s6Sentry0A2IdC4uuidAC10Foundation4UUIDV_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithUuid:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(uuidString:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)initWithUUIDString:", + "mangledName": "$s6Sentry0A2IdC10uuidStringACSS_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithUUIDString:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Function", + "name": "isEqual", + "printedName": "isEqual(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Any?", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)isEqual:", + "mangledName": "$s6Sentry0A2IdC7isEqualySbypSgF", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "isEqual:", + "declAttributes": [ + "ObjC", + "Final", + "Override" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Var", + "name": "description", + "printedName": "description", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryId(py)description", + "mangledName": "$s6Sentry0A2IdC11descriptionSSvp", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "description", + "declAttributes": [ + "ObjC", + "Final", + "Override" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)description", + "mangledName": "$s6Sentry0A2IdC11descriptionSSvg", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "description", + "declAttributes": [ + "Final", + "ObjC", + "Override" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "hash", + "printedName": "hash", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryId(py)hash", + "mangledName": "$s6Sentry0A2IdC4hashSivp", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "hash", + "declAttributes": [ + "ObjC", + "Final", + "Override" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)hash", + "mangledName": "$s6Sentry0A2IdC4hashSivg", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "hash", + "declAttributes": [ + "Final", + "ObjC", + "Override" + ], + "accessorKind": "get" + } + ] + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryId", + "mangledName": "$s6Sentry0A2IdC", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentrySDK", + "printedName": "SentrySDK", + "children": [ + { + "kind": "Var", + "name": "span", + "printedName": "span", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)span", + "mangledName": "$s6Sentry0A3SDKC4spanSo0A4Span_pSgvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)span", + "mangledName": "$s6Sentry0A3SDKC4spanSo0A4Span_pSgvgZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "isEnabled", + "printedName": "isEnabled", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)isEnabled", + "mangledName": "$s6Sentry0A3SDKC9isEnabledSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)isEnabled", + "mangledName": "$s6Sentry0A3SDKC9isEnabledSbvgZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "replay", + "printedName": "replay", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayApi", + "printedName": "Sentry.SentryReplayApi", + "usr": "c:objc(cs)SentryReplayApi" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)replay", + "mangledName": "$s6Sentry0A3SDKC6replaySo0A9ReplayApiCvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayApi", + "printedName": "Sentry.SentryReplayApi", + "usr": "c:objc(cs)SentryReplayApi" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)replay", + "mangledName": "$s6Sentry0A3SDKC6replaySo0A9ReplayApiCvgZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "logger", + "printedName": "logger", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLogger", + "printedName": "Sentry.SentryLogger", + "usr": "c:@M@Sentry@objc(cs)SentryLogger" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)logger", + "mangledName": "$s6Sentry0A3SDKC6loggerAA0A6LoggerCvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLogger", + "printedName": "Sentry.SentryLogger", + "usr": "c:@M@Sentry@objc(cs)SentryLogger" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)logger", + "mangledName": "$s6Sentry0A3SDKC6loggerAA0A6LoggerCvgZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Function", + "name": "start", + "printedName": "start(options:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Options", + "printedName": "Sentry.Options", + "usr": "c:objc(cs)SentryOptions" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startWithOptions:", + "mangledName": "$s6Sentry0A3SDKC5start7optionsySo0A7OptionsC_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startWithOptions:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "start", + "printedName": "start(configureOptions:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Options) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Options", + "printedName": "Sentry.Options", + "usr": "c:objc(cs)SentryOptions" + } + ] + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startWithConfigureOptions:", + "mangledName": "$s6Sentry0A3SDKC5start16configureOptionsyySo0aE0Cc_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startWithConfigureOptions:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(event:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureEvent:", + "mangledName": "$s6Sentry0A3SDKC7capture5eventAA0A2IdCSo0A5EventC_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureEvent:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(event:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureEvent:withScope:", + "mangledName": "$s6Sentry0A3SDKC7capture5event5scopeAA0A2IdCSo0A5EventC_So0A5ScopeCtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureEvent:withScope:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(event:block:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ] + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureEvent:withScopeBlock:", + "mangledName": "$s6Sentry0A3SDKC7capture5event5blockAA0A2IdCSo0A5EventC_ySo0A5ScopeCctFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureEvent:withScopeBlock:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(name:operation:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startTransactionWithName:operation:", + "mangledName": "$s6Sentry0A3SDKC16startTransaction4name9operationSo0A4Span_pSS_SStFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startTransactionWithName:operation:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(name:operation:bindToScope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startTransactionWithName:operation:bindToScope:", + "mangledName": "$s6Sentry0A3SDKC16startTransaction4name9operation11bindToScopeSo0A4Span_pSS_SSSbtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startTransactionWithName:operation:bindToScope:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(transactionContext:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startTransactionWithContext:", + "mangledName": "$s6Sentry0A3SDKC16startTransaction18transactionContextSo0A4Span_pSo0adF0C_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startTransactionWithContext:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(transactionContext:bindToScope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startTransactionWithContext:bindToScope:", + "mangledName": "$s6Sentry0A3SDKC16startTransaction18transactionContext11bindToScopeSo0A4Span_pSo0adF0C_SbtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startTransactionWithContext:bindToScope:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(transactionContext:bindToScope:customSamplingContext:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startTransactionWithContext:bindToScope:customSamplingContext:", + "mangledName": "$s6Sentry0A3SDKC16startTransaction18transactionContext11bindToScope014customSamplingF0So0A4Span_pSo0adF0C_SbSDySSypGtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startTransactionWithContext:bindToScope:customSamplingContext:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(transactionContext:customSamplingContext:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startTransactionWithContext:customSamplingContext:", + "mangledName": "$s6Sentry0A3SDKC16startTransaction18transactionContext014customSamplingF0So0A4Span_pSo0adF0C_SDySSypGtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startTransactionWithContext:customSamplingContext:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(error:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureError:", + "mangledName": "$s6Sentry0A3SDKC7capture5errorAA0A2IdCs5Error_p_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureError:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(error:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureError:withScope:", + "mangledName": "$s6Sentry0A3SDKC7capture5error5scopeAA0A2IdCs5Error_p_So0A5ScopeCtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureError:withScope:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(error:block:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ] + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureError:withScopeBlock:", + "mangledName": "$s6Sentry0A3SDKC7capture5error5blockAA0A2IdCs5Error_p_ySo0A5ScopeCctFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureError:withScopeBlock:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(exception:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "NSException", + "printedName": "Foundation.NSException", + "usr": "c:objc(cs)NSException" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureException:", + "mangledName": "$s6Sentry0A3SDKC7capture9exceptionAA0A2IdCSo11NSExceptionC_tFZ", "moduleName": "Sentry", + "static": true, + "objc_name": "captureException:", "declAttributes": [ - "ObjC" + "Final", + "ObjC", + "DiscardableResult" ], - "enumRawTypeName": "Int", - "conformances": [ + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(exception:scope:)", + "children": [ { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" }, { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" + "kind": "TypeNominal", + "name": "NSException", + "printedName": "Foundation.NSException", + "usr": "c:objc(cs)NSException" }, { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureException:withScope:", + "mangledName": "$s6Sentry0A3SDKC7capture9exception5scopeAA0A2IdCSo11NSExceptionC_So0A5ScopeCtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureException:withScope:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(exception:block:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" }, { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" + "kind": "TypeNominal", + "name": "NSException", + "printedName": "Foundation.NSException", + "usr": "c:objc(cs)NSException" }, { - "kind": "Conformance", - "name": "RawRepresentable", - "printedName": "RawRepresentable", + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Swift.Void", "children": [ { - "kind": "TypeWitness", - "name": "RawValue", - "printedName": "RawValue", + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", "children": [ { - "kind": "TypeNameAlias", - "name": "RawValue", - "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle.RawValue", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ] + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" } ] + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" } - ], - "usr": "s:SY", - "mangledName": "$sSY" + ] } - ] + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureException:withScopeBlock:", + "mangledName": "$s6Sentry0A3SDKC7capture9exception5blockAA0A2IdCSo11NSExceptionC_ySo0A5ScopeCctFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureException:withScopeBlock:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" }, { - "kind": "Var", - "name": "lifecycle", - "printedName": "lifecycle", + "kind": "Function", + "name": "capture", + "printedName": "capture(message:)", "children": [ { "kind": "TypeNominal", - "name": "SentryProfileLifecycle", - "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" } ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(py)lifecycle", - "mangledName": "$s6Sentry0A14ProfileOptionsC9lifecycleAC0aB9LifecycleOvp", + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureMessage:", + "mangledName": "$s6Sentry0A3SDKC7capture7messageAA0A2IdCSS_tFZ", "moduleName": "Sentry", + "static": true, + "objc_name": "captureMessage:", "declAttributes": [ + "Final", "ObjC", - "HasStorage" + "DiscardableResult" ], - "hasStorage": true, - "accessors": [ + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(message:scope:)", + "children": [ { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "SentryProfileLifecycle", - "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)lifecycle", - "mangledName": "$s6Sentry0A14ProfileOptionsC9lifecycleAC0aB9LifecycleOvg", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "get" + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" }, { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureMessage:withScope:", + "mangledName": "$s6Sentry0A3SDKC7capture7message5scopeAA0A2IdCSS_So0A5ScopeCtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureMessage:withScope:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(message:block:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Swift.Void", "children": [ { - "kind": "TypeNominal", + "kind": "TypeNameAlias", "name": "Void", - "printedName": "()" + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] }, { "kind": "TypeNominal", - "name": "SentryProfileLifecycle", - "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", - "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)setLifecycle:", - "mangledName": "$s6Sentry0A14ProfileOptionsC9lifecycleAC0aB9LifecycleOvs", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" + ] } - ] + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureMessage:withScopeBlock:", + "mangledName": "$s6Sentry0A3SDKC7capture7message5blockAA0A2IdCSS_ySo0A5ScopeCctFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureMessage:withScopeBlock:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" }, { - "kind": "Var", - "name": "sessionSampleRate", - "printedName": "sessionSampleRate", + "kind": "Function", + "name": "capture", + "printedName": "capture(userFeedback:)", "children": [ { "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "usr": "s:Sf" + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UserFeedback", + "printedName": "Sentry.UserFeedback", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedback" } ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(py)sessionSampleRate", - "mangledName": "$s6Sentry0A14ProfileOptionsC17sessionSampleRateSfvp", + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureUserFeedback:", + "mangledName": "$s6Sentry0A3SDKC7capture12userFeedbackyAA04UserE0C_tFZ", "moduleName": "Sentry", + "static": true, + "deprecated": true, + "objc_name": "captureUserFeedback:", "declAttributes": [ + "Final", "ObjC", - "HasStorage" + "Available" ], - "hasStorage": true, - "accessors": [ + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(feedback:)", + "children": [ { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "usr": "s:Sf" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)sessionSampleRate", - "mangledName": "$s6Sentry0A14ProfileOptionsC17sessionSampleRateSfvg", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "get" + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" }, { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - }, - { - "kind": "TypeNominal", - "name": "Float", - "printedName": "Swift.Float", - "usr": "s:Sf" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)setSessionSampleRate:", - "mangledName": "$s6Sentry0A14ProfileOptionsC17sessionSampleRateSfvs", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" + "kind": "TypeNominal", + "name": "SentryFeedback", + "printedName": "Sentry.SentryFeedback", + "usr": "c:@M@Sentry@objc(cs)SentryFeedback" } - ] + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureFeedback:", + "mangledName": "$s6Sentry0A3SDKC7capture8feedbackyAA0A8FeedbackC_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureFeedback:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" }, { "kind": "Var", - "name": "profileAppStarts", - "printedName": "profileAppStarts", + "name": "feedback", + "printedName": "feedback", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentryFeedbackAPI", + "printedName": "Sentry.SentryFeedbackAPI", + "usr": "c:objc(cs)SentryFeedbackAPI" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(py)profileAppStarts", - "mangledName": "$s6Sentry0A14ProfileOptionsC16profileAppStartsSbvp", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)feedback", + "mangledName": "$s6Sentry0A3SDKC8feedbackSo0A11FeedbackAPICvpZ", "moduleName": "Sentry", + "static": true, + "intro_iOS": "13.0", "declAttributes": [ + "Final", "ObjC", + "Available", "HasStorage" ], + "isLet": true, "hasStorage": true, "accessors": [ { @@ -48941,176 +54666,123 @@ "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" + "name": "SentryFeedbackAPI", + "printedName": "Sentry.SentryFeedbackAPI", + "usr": "c:objc(cs)SentryFeedbackAPI" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)profileAppStarts", - "mangledName": "$s6Sentry0A14ProfileOptionsC16profileAppStartsSbvg", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)feedback", + "mangledName": "$s6Sentry0A3SDKC8feedbackSo0A11FeedbackAPICvgZ", "moduleName": "Sentry", + "static": true, "implicit": true, "declAttributes": [ + "Final", "ObjC" ], "accessorKind": "get" - }, - { - "kind": "Accessor", - "name": "Set", - "printedName": "Set()", - "children": [ - { - "kind": "TypeNominal", - "name": "Void", - "printedName": "()" - }, - { - "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)setProfileAppStarts:", - "mangledName": "$s6Sentry0A14ProfileOptionsC16profileAppStartsSbvs", - "moduleName": "Sentry", - "implicit": true, - "declAttributes": [ - "ObjC" - ], - "accessorKind": "set" } ] }, { - "kind": "Constructor", - "name": "init", - "printedName": "init()", + "kind": "Function", + "name": "addBreadcrumb", + "printedName": "addBreadcrumb(_:)", "children": [ { "kind": "TypeNominal", - "name": "SentryProfileOptions", - "printedName": "Sentry.SentryProfileOptions", - "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions" + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" } ], - "declKind": "Constructor", - "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)init", - "mangledName": "$s6Sentry0A14ProfileOptionsCACycfc", + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)addBreadcrumb:", + "mangledName": "$s6Sentry0A3SDKC13addBreadcrumbyySo0aD0CFZ", "moduleName": "Sentry", - "overriding": true, - "objc_name": "init", + "static": true, + "objc_name": "addBreadcrumb:", "declAttributes": [ - "ObjC", - "Dynamic", - "Override" - ], - "init_kind": "Designated" - } - ], - "declKind": "Class", - "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions", - "mangledName": "$s6Sentry0A14ProfileOptionsC", - "moduleName": "Sentry", - "declAttributes": [ - "ObjCMembers", - "ObjC" - ], - "superclassUsr": "c:objc(cs)NSObject", - "inheritsConvenienceInitializers": true, - "superclassNames": [ - "ObjectiveC.NSObject" - ], - "conformances": [ - { - "kind": "Conformance", - "name": "Copyable", - "printedName": "Copyable", - "usr": "s:s8CopyableP", - "mangledName": "$ss8CopyableP" - }, - { - "kind": "Conformance", - "name": "Escapable", - "printedName": "Escapable", - "usr": "s:s9EscapableP", - "mangledName": "$ss9EscapableP" - }, - { - "kind": "Conformance", - "name": "NSObjectProtocol", - "printedName": "NSObjectProtocol", - "usr": "c:objc(pl)NSObject" - }, - { - "kind": "Conformance", - "name": "Equatable", - "printedName": "Equatable", - "usr": "s:SQ", - "mangledName": "$sSQ" - }, - { - "kind": "Conformance", - "name": "Hashable", - "printedName": "Hashable", - "usr": "s:SH", - "mangledName": "$sSH" - }, - { - "kind": "Conformance", - "name": "CVarArg", - "printedName": "CVarArg", - "usr": "s:s7CVarArgP", - "mangledName": "$ss7CVarArgP" - }, - { - "kind": "Conformance", - "name": "CustomStringConvertible", - "printedName": "CustomStringConvertible", - "usr": "s:s23CustomStringConvertibleP", - "mangledName": "$ss23CustomStringConvertibleP" + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" }, { - "kind": "Conformance", - "name": "CustomDebugStringConvertible", - "printedName": "CustomDebugStringConvertible", - "usr": "s:s28CustomDebugStringConvertibleP", - "mangledName": "$ss28CustomDebugStringConvertibleP" - } - ] - }, - { - "kind": "TypeDecl", - "name": "SentryId", - "printedName": "SentryId", - "children": [ + "kind": "Function", + "name": "configureScope", + "printedName": "configureScope(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ] + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)configureScope:", + "mangledName": "$s6Sentry0A3SDKC14configureScopeyyySo0aD0CcFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "configureScope:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, { "kind": "Var", - "name": "empty", - "printedName": "empty", + "name": "crashedLastRun", + "printedName": "crashedLastRun", "children": [ { "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryId(cpy)empty", - "mangledName": "$s6Sentry0A2IdC5emptyACvpZ", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)crashedLastRun", + "mangledName": "$s6Sentry0A3SDKC14crashedLastRunSbvpZ", "moduleName": "Sentry", "static": true, "declAttributes": [ "Final", - "ObjC", - "HasStorage" + "ObjC" ], - "isLet": true, - "hasStorage": true, "accessors": [ { "kind": "Accessor", @@ -49119,17 +54791,16 @@ "children": [ { "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryId(cm)empty", - "mangledName": "$s6Sentry0A2IdC5emptyACvgZ", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)crashedLastRun", + "mangledName": "$s6Sentry0A3SDKC14crashedLastRunSbvgZ", "moduleName": "Sentry", "static": true, - "implicit": true, "declAttributes": [ "Final", "ObjC" @@ -49140,20 +54811,21 @@ }, { "kind": "Var", - "name": "sentryIdString", - "printedName": "sentryIdString", + "name": "detectedStartUpCrash", + "printedName": "detectedStartUpCrash", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryId(py)sentryIdString", - "mangledName": "$s6Sentry0A2IdC06sentryB6StringSSvp", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)detectedStartUpCrash", + "mangledName": "$s6Sentry0A3SDKC20detectedStartUpCrashSbvpZ", "moduleName": "Sentry", + "static": true, "declAttributes": [ "Final", "ObjC" @@ -49166,15 +54838,16 @@ "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" } ], "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryId(im)sentryIdString", - "mangledName": "$s6Sentry0A2IdC06sentryB6StringSSvg", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)detectedStartUpCrash", + "mangledName": "$s6Sentry0A3SDKC20detectedStartUpCrashSbvgZ", "moduleName": "Sentry", + "static": true, "declAttributes": [ "Final", "ObjC" @@ -49184,234 +54857,307 @@ ] }, { - "kind": "Constructor", - "name": "init", - "printedName": "init()", + "kind": "Function", + "name": "setUser", + "printedName": "setUser(_:)", "children": [ { "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.User?", + "children": [ + { + "kind": "TypeNominal", + "name": "User", + "printedName": "Sentry.User", + "usr": "c:objc(cs)SentryUser" + } + ], + "usr": "s:Sq" } ], - "declKind": "Constructor", - "usr": "c:@M@Sentry@objc(cs)SentryId(im)init", - "mangledName": "$s6Sentry0A2IdCACycfc", + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)setUser:", + "mangledName": "$s6Sentry0A3SDKC7setUseryySo0aD0CSgFZ", "moduleName": "Sentry", - "overriding": true, - "objc_name": "init", + "static": true, "declAttributes": [ - "ObjC", - "Dynamic", - "Override" + "Final", + "ObjC" ], - "init_kind": "Designated" + "funcSelfKind": "NonMutating" }, { - "kind": "Constructor", - "name": "init", - "printedName": "init(uuid:)", + "kind": "Function", + "name": "startSession", + "printedName": "startSession()", "children": [ { "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - }, + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startSession", + "mangledName": "$s6Sentry0A3SDKC12startSessionyyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "endSession", + "printedName": "endSession()", + "children": [ { "kind": "TypeNominal", - "name": "UUID", - "printedName": "Foundation.UUID", - "usr": "s:10Foundation4UUIDV" + "name": "Void", + "printedName": "()" } ], - "declKind": "Constructor", - "usr": "c:@M@Sentry@objc(cs)SentryId(im)initWithUuid:", - "mangledName": "$s6Sentry0A2IdC4uuidAC10Foundation4UUIDV_tcfc", + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)endSession", + "mangledName": "$s6Sentry0A3SDKC10endSessionyyFZ", "moduleName": "Sentry", - "objc_name": "initWithUuid:", + "static": true, "declAttributes": [ + "Final", "ObjC" ], - "init_kind": "Designated" + "funcSelfKind": "NonMutating" }, { - "kind": "Constructor", - "name": "init", - "printedName": "init(uuidString:)", + "kind": "Function", + "name": "crash", + "printedName": "crash()", "children": [ { "kind": "TypeNominal", - "name": "SentryId", - "printedName": "Sentry.SentryId", - "usr": "c:@M@Sentry@objc(cs)SentryId" - }, + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)crash", + "mangledName": "$s6Sentry0A3SDKC5crashyyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "reportFullyDisplayed", + "printedName": "reportFullyDisplayed()", + "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Void", + "printedName": "()" } ], - "declKind": "Constructor", - "usr": "c:@M@Sentry@objc(cs)SentryId(im)initWithUUIDString:", - "mangledName": "$s6Sentry0A2IdC10uuidStringACSS_tcfc", + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)reportFullyDisplayed", + "mangledName": "$s6Sentry0A3SDKC20reportFullyDisplayedyyFZ", "moduleName": "Sentry", - "objc_name": "initWithUUIDString:", + "static": true, "declAttributes": [ + "Final", "ObjC" ], - "init_kind": "Designated" + "funcSelfKind": "NonMutating" }, { "kind": "Function", - "name": "isEqual", - "printedName": "isEqual(_:)", + "name": "pauseAppHangTracking", + "printedName": "pauseAppHangTracking()", "children": [ { "kind": "TypeNominal", - "name": "Bool", - "printedName": "Swift.Bool", - "usr": "s:Sb" - }, + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)pauseAppHangTracking", + "mangledName": "$s6Sentry0A3SDKC20pauseAppHangTrackingyyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "resumeAppHangTracking", + "printedName": "resumeAppHangTracking()", + "children": [ { "kind": "TypeNominal", - "name": "Optional", - "printedName": "Any?", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)resumeAppHangTracking", + "mangledName": "$s6Sentry0A3SDKC21resumeAppHangTrackingyyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "flush", + "printedName": "flush(timeout:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNameAlias", + "name": "TimeInterval", + "printedName": "Foundation.TimeInterval", "children": [ { "kind": "TypeNominal", - "name": "ProtocolComposition", - "printedName": "Any" + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" } - ], - "usr": "s:Sq" + ] } ], "declKind": "Func", - "usr": "c:@M@Sentry@objc(cs)SentryId(im)isEqual:", - "mangledName": "$s6Sentry0A2IdC7isEqualySbypSgF", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)flush:", + "mangledName": "$s6Sentry0A3SDKC5flush7timeoutySd_tFZ", "moduleName": "Sentry", - "overriding": true, - "objc_name": "isEqual:", + "static": true, + "objc_name": "flush:", "declAttributes": [ - "ObjC", "Final", - "Override" + "ObjC" ], "funcSelfKind": "NonMutating" }, { - "kind": "Var", - "name": "description", - "printedName": "description", + "kind": "Function", + "name": "close", + "printedName": "close()", "children": [ { "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" + "name": "Void", + "printedName": "()" } ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryId(py)description", - "mangledName": "$s6Sentry0A2IdC11descriptionSSvp", + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)close", + "mangledName": "$s6Sentry0A3SDKC5closeyyFZ", "moduleName": "Sentry", - "overriding": true, - "objc_name": "description", + "static": true, "declAttributes": [ - "ObjC", "Final", - "Override" + "ObjC" ], - "accessors": [ + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startProfiler", + "printedName": "startProfiler()", + "children": [ { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "String", - "printedName": "Swift.String", - "usr": "s:SS" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryId(im)description", - "mangledName": "$s6Sentry0A2IdC11descriptionSSvg", - "moduleName": "Sentry", - "overriding": true, - "objc_name": "description", - "declAttributes": [ - "Final", - "ObjC", - "Override" - ], - "accessorKind": "get" + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" } - ] + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startProfiler", + "mangledName": "$s6Sentry0A3SDKC13startProfileryyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" }, { - "kind": "Var", - "name": "hash", - "printedName": "hash", + "kind": "Function", + "name": "stopProfiler", + "printedName": "stopProfiler()", "children": [ { "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" + "name": "Void", + "printedName": "()" } ], - "declKind": "Var", - "usr": "c:@M@Sentry@objc(cs)SentryId(py)hash", - "mangledName": "$s6Sentry0A2IdC4hashSivp", + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)stopProfiler", + "mangledName": "$s6Sentry0A3SDKC12stopProfileryyFZ", "moduleName": "Sentry", - "overriding": true, - "objc_name": "hash", + "static": true, "declAttributes": [ - "ObjC", "Final", - "Override" + "ObjC" ], - "accessors": [ + "funcSelfKind": "NonMutating" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ { - "kind": "Accessor", - "name": "Get", - "printedName": "Get()", - "children": [ - { - "kind": "TypeNominal", - "name": "Int", - "printedName": "Swift.Int", - "usr": "s:Si" - } - ], - "declKind": "Accessor", - "usr": "c:@M@Sentry@objc(cs)SentryId(im)hash", - "mangledName": "$s6Sentry0A2IdC4hashSivg", - "moduleName": "Sentry", - "overriding": true, - "objc_name": "hash", - "declAttributes": [ - "Final", - "ObjC", - "Override" - ], - "accessorKind": "get" + "kind": "TypeNominal", + "name": "SentrySDK", + "printedName": "Sentry.SentrySDK", + "usr": "c:@M@Sentry@objc(cs)SentrySDK" } - ] + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(im)init", + "mangledName": "$s6Sentry0A3SDKCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" } ], "declKind": "Class", - "usr": "c:@M@Sentry@objc(cs)SentryId", - "mangledName": "$s6Sentry0A2IdC", + "usr": "c:@M@Sentry@objc(cs)SentrySDK", + "mangledName": "$s6Sentry0A3SDKC", "moduleName": "Sentry", + "isOpen": true, "declAttributes": [ - "Final", - "ObjCMembers", "ObjC" ], "superclassUsr": "c:objc(cs)NSObject", @@ -49420,13 +55166,6 @@ "ObjectiveC.NSObject" ], "conformances": [ - { - "kind": "Conformance", - "name": "Sendable", - "printedName": "Sendable", - "usr": "s:s8SendableP", - "mangledName": "$ss8SendableP" - }, { "kind": "Conformance", "name": "Copyable", @@ -51143,6 +56882,79 @@ } ] }, + { + "kind": "Var", + "name": "enableLogs", + "printedName": "enableLogs", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(py)enableLogs", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC10enableLogsSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)enableLogs", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC10enableLogsSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)setEnableLogs:", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC10enableLogsSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, { "kind": "Constructor", "name": "init", diff --git a/sdk_api_V9.json b/sdk_api_V9.json new file mode 100644 index 00000000000..78bc4500dce --- /dev/null +++ b/sdk_api_V9.json @@ -0,0 +1,59239 @@ +{ + "ABIRoot": { + "kind": "Root", + "name": "Sentry", + "printedName": "Sentry", + "children": [ + { + "kind": "Import", + "name": "Foundation", + "printedName": "Foundation", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryAttachment", + "printedName": "Sentry.SentryAttachment", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryBaggage", + "printedName": "Sentry.SentryBaggage", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryBreadcrumb", + "printedName": "Sentry.SentryBreadcrumb", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryClient", + "printedName": "Sentry.SentryClient", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryCrashExceptionApplication", + "printedName": "Sentry.SentryCrashExceptionApplication", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryDebugImageProvider", + "printedName": "Sentry.SentryDebugImageProvider", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryDebugMeta", + "printedName": "Sentry.SentryDebugMeta", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryDefines", + "printedName": "Sentry.SentryDefines", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryDsn", + "printedName": "Sentry.SentryDsn", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryEnvelopeItemHeader", + "printedName": "Sentry.SentryEnvelopeItemHeader", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryError", + "printedName": "Sentry.SentryError", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryEvent", + "printedName": "Sentry.SentryEvent", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryException", + "printedName": "Sentry.SentryException", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryFeedbackAPI", + "printedName": "Sentry.SentryFeedbackAPI", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryFrame", + "printedName": "Sentry.SentryFrame", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryGeo", + "printedName": "Sentry.SentryGeo", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryHttpStatusCodeRange", + "printedName": "Sentry.SentryHttpStatusCodeRange", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryHub", + "printedName": "Sentry.SentryHub", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryIntegrationProtocol", + "printedName": "Sentry.SentryIntegrationProtocol", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryMeasurementUnit", + "printedName": "Sentry.SentryMeasurementUnit", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryMechanism", + "printedName": "Sentry.SentryMechanism", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryMechanismMeta", + "printedName": "Sentry.SentryMechanismMeta", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryMessage", + "printedName": "Sentry.SentryMessage", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryNSError", + "printedName": "Sentry.SentryNSError", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryOptions", + "printedName": "Sentry.SentryOptions", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryReplayApi", + "printedName": "Sentry.SentryReplayApi", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryRequest", + "printedName": "Sentry.SentryRequest", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentrySamplingContext", + "printedName": "Sentry.SentrySamplingContext", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryScope", + "printedName": "Sentry.SentryScope", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentrySerializable", + "printedName": "Sentry.SentrySerializable", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentrySpanContext", + "printedName": "Sentry.SentrySpanContext", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentrySpanId", + "printedName": "Sentry.SentrySpanId", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentrySpanProtocol", + "printedName": "Sentry.SentrySpanProtocol", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryThread", + "printedName": "Sentry.SentryThread", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryTraceContext", + "printedName": "Sentry.SentryTraceContext", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryTraceHeader", + "printedName": "Sentry.SentryTraceHeader", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryTransactionContext", + "printedName": "Sentry.SentryTransactionContext", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryUser", + "printedName": "Sentry.SentryUser", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "Sentry.SentryWithoutUIKit", + "printedName": "Sentry.SentryWithoutUIKit", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "TypeDecl", + "name": "Attachment", + "printedName": "Attachment", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(data:filename:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attachment", + "printedName": "Sentry.Attachment", + "usr": "c:objc(cs)SentryAttachment" + }, + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryAttachment(im)initWithData:filename:", + "moduleName": "Sentry", + "objc_name": "initWithData:filename:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(data:filename:contentType:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attachment", + "printedName": "Sentry.Attachment", + "usr": "c:objc(cs)SentryAttachment" + }, + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryAttachment(im)initWithData:filename:contentType:", + "moduleName": "Sentry", + "objc_name": "initWithData:filename:contentType:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(path:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attachment", + "printedName": "Sentry.Attachment", + "usr": "c:objc(cs)SentryAttachment" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryAttachment(im)initWithPath:", + "moduleName": "Sentry", + "objc_name": "initWithPath:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(path:filename:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attachment", + "printedName": "Sentry.Attachment", + "usr": "c:objc(cs)SentryAttachment" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryAttachment(im)initWithPath:filename:", + "moduleName": "Sentry", + "objc_name": "initWithPath:filename:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(path:filename:contentType:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attachment", + "printedName": "Sentry.Attachment", + "usr": "c:objc(cs)SentryAttachment" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryAttachment(im)initWithPath:filename:contentType:", + "moduleName": "Sentry", + "objc_name": "initWithPath:filename:contentType:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "data", + "printedName": "data", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Data?", + "children": [ + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryAttachment(py)data", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "data", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Data?", + "children": [ + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryAttachment(im)data", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "data", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "path", + "printedName": "path", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryAttachment(py)path", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "path", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryAttachment(im)path", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "path", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "filename", + "printedName": "filename", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryAttachment(py)filename", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "filename", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryAttachment(im)filename", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "filename", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "contentType", + "printedName": "contentType", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryAttachment(py)contentType", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "contentType", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryAttachment(im)contentType", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "contentType", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryAttachment", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryAttachment", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "Baggage", + "printedName": "Baggage", + "children": [ + { + "kind": "Var", + "name": "traceId", + "printedName": "traceId", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBaggage(py)traceId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "traceId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBaggage(im)traceId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "traceId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "publicKey", + "printedName": "publicKey", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBaggage(py)publicKey", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "publicKey", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBaggage(im)publicKey", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "publicKey", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "releaseName", + "printedName": "releaseName", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBaggage(py)releaseName", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "releaseName", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBaggage(im)releaseName", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "releaseName", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "environment", + "printedName": "environment", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBaggage(py)environment", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "environment", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBaggage(im)environment", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "environment", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "transaction", + "printedName": "transaction", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBaggage(py)transaction", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "transaction", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBaggage(im)transaction", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "transaction", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "userId", + "printedName": "userId", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBaggage(py)userId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "userId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBaggage(im)userId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "userId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "sampleRand", + "printedName": "sampleRand", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBaggage(py)sampleRand", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRand", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBaggage(im)sampleRand", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRand", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "sampleRate", + "printedName": "sampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBaggage(py)sampleRate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRate", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBaggage(im)sampleRate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRate", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "sampled", + "printedName": "sampled", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBaggage(py)sampled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampled", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBaggage(im)sampled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampled", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBaggage(im)setSampled:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSampled:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "replayId", + "printedName": "replayId", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBaggage(py)replayId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "replayId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBaggage(im)replayId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "replayId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBaggage(im)setReplayId:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setReplayId:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(trace:publicKey:releaseName:environment:transaction:sampleRate:sampled:replayId:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Baggage", + "printedName": "Sentry.Baggage", + "usr": "c:objc(cs)SentryBaggage" + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryBaggage(im)initWithTraceId:publicKey:releaseName:environment:transaction:sampleRate:sampled:replayId:", + "moduleName": "Sentry", + "objc_name": "initWithTraceId:publicKey:releaseName:environment:transaction:sampleRate:sampled:replayId:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(trace:publicKey:releaseName:environment:transaction:sampleRate:sampleRand:sampled:replayId:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Baggage", + "printedName": "Sentry.Baggage", + "usr": "c:objc(cs)SentryBaggage" + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryBaggage(im)initWithTraceId:publicKey:releaseName:environment:transaction:sampleRate:sampleRand:sampled:replayId:", + "moduleName": "Sentry", + "objc_name": "initWithTraceId:publicKey:releaseName:environment:transaction:sampleRate:sampleRand:sampled:replayId:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Function", + "name": "toHTTPHeader", + "printedName": "toHTTPHeader(withOriginalBaggage:)", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.AnyHashable : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.AnyHashable : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "AnyHashable", + "printedName": "Swift.AnyHashable", + "usr": "s:s11AnyHashableV" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryBaggage(im)toHTTPHeaderWithOriginalBaggage:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "toHTTPHeaderWithOriginalBaggage:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "Baggage", + "printedName": "Sentry.Baggage", + "usr": "c:objc(cs)SentryBaggage" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)NSObject(im)init", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryBaggage", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryBaggage", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "Breadcrumb", + "printedName": "Breadcrumb", + "children": [ + { + "kind": "Var", + "name": "level", + "printedName": "level", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBreadcrumb(py)level", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "level", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)level", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "level", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)setLevel:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setLevel:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "category", + "printedName": "category", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBreadcrumb(py)category", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "category", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)category", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "category", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)setCategory:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setCategory:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "timestamp", + "printedName": "timestamp", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Date?", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBreadcrumb(py)timestamp", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "timestamp", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Date?", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)timestamp", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "timestamp", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Date?", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)setTimestamp:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setTimestamp:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "type", + "printedName": "type", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBreadcrumb(py)type", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "type", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)type", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "type", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)setType:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setType:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "message", + "printedName": "message", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBreadcrumb(py)message", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "message", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)message", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "message", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)setMessage:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setMessage:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "origin", + "printedName": "origin", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBreadcrumb(py)origin", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "origin", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)origin", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "origin", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)setOrigin:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setOrigin:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "data", + "printedName": "data", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryBreadcrumb(py)data", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "data", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)data", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "data", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryBreadcrumb(im)setData:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setData:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(level:category:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + }, + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryBreadcrumb(im)initWithLevel:category:", + "moduleName": "Sentry", + "objc_name": "initWithLevel:category:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryBreadcrumb(im)init", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Function", + "name": "isEqual", + "printedName": "isEqual(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Any?", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryBreadcrumb(im)isEqual:", + "moduleName": "Sentry", + "overriding": true, + "isOpen": true, + "objc_name": "isEqual:", + "declAttributes": [ + "DiscardableResult", + "Override", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "isEqual", + "printedName": "isEqual(to:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryBreadcrumb(im)isEqualToBreadcrumb:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "isEqualToBreadcrumb:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "hash", + "printedName": "hash()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryBreadcrumb(im)hash", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "hash", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryBreadcrumb", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryBreadcrumb", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "DebugMeta", + "printedName": "DebugMeta", + "children": [ + { + "kind": "Var", + "name": "uuid", + "printedName": "uuid", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryDebugMeta(py)uuid", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "uuid", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)uuid", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "uuid", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)setUuid:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setUuid:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "debugID", + "printedName": "debugID", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryDebugMeta(py)debugID", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "debugID", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)debugID", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "debugID", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)setDebugID:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setDebugID:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "type", + "printedName": "type", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryDebugMeta(py)type", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "type", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)type", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "type", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)setType:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setType:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "name", + "printedName": "name", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryDebugMeta(py)name", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "name", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)name", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "name", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)setName:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setName:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "imageSize", + "printedName": "imageSize", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryDebugMeta(py)imageSize", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "imageSize", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)imageSize", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "imageSize", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)setImageSize:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setImageSize:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "imageAddress", + "printedName": "imageAddress", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryDebugMeta(py)imageAddress", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "imageAddress", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)imageAddress", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "imageAddress", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)setImageAddress:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setImageAddress:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "imageVmAddress", + "printedName": "imageVmAddress", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryDebugMeta(py)imageVmAddress", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "imageVmAddress", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)imageVmAddress", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "imageVmAddress", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)setImageVmAddress:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setImageVmAddress:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "codeFile", + "printedName": "codeFile", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryDebugMeta(py)codeFile", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "codeFile", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)codeFile", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "codeFile", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDebugMeta(im)setCodeFile:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setCodeFile:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "DebugMeta", + "printedName": "Sentry.DebugMeta", + "usr": "c:objc(cs)SentryDebugMeta" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryDebugMeta(im)init", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryDebugMeta", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryDebugMeta", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "Event", + "printedName": "Event", + "children": [ + { + "kind": "Var", + "name": "eventId", + "printedName": "eventId", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)eventId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "eventId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)eventId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "eventId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setEventId:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEventId:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "message", + "printedName": "message", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryMessage?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryMessage", + "printedName": "Sentry.SentryMessage", + "usr": "c:objc(cs)SentryMessage" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)message", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "message", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryMessage?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryMessage", + "printedName": "Sentry.SentryMessage", + "usr": "c:objc(cs)SentryMessage" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)message", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "message", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryMessage?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryMessage", + "printedName": "Sentry.SentryMessage", + "usr": "c:objc(cs)SentryMessage" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setMessage:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setMessage:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "error", + "printedName": "error", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Swift.Error)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)error", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "error", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Swift.Error)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)error", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "error", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Swift.Error)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setError:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setError:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "timestamp", + "printedName": "timestamp", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Date?", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)timestamp", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "timestamp", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Date?", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)timestamp", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "timestamp", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Date?", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setTimestamp:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setTimestamp:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "startTimestamp", + "printedName": "startTimestamp", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Date?", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)startTimestamp", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "startTimestamp", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Date?", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)startTimestamp", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "startTimestamp", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Date?", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setStartTimestamp:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setStartTimestamp:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "level", + "printedName": "level", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)level", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "level", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)level", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "level", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setLevel:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setLevel:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "platform", + "printedName": "platform", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)platform", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "platform", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)platform", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "platform", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setPlatform:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setPlatform:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "logger", + "printedName": "logger", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)logger", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "logger", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)logger", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "logger", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setLogger:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setLogger:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "serverName", + "printedName": "serverName", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)serverName", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "serverName", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)serverName", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "serverName", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setServerName:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setServerName:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "releaseName", + "printedName": "releaseName", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)releaseName", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "releaseName", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)releaseName", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "releaseName", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setReleaseName:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setReleaseName:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "dist", + "printedName": "dist", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)dist", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "dist", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)dist", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "dist", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setDist:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setDist:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "environment", + "printedName": "environment", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)environment", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "environment", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)environment", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "environment", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setEnvironment:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnvironment:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "transaction", + "printedName": "transaction", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)transaction", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "transaction", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)transaction", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "transaction", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setTransaction:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setTransaction:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "type", + "printedName": "type", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)type", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "type", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)type", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "type", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setType:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setType:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "tags", + "printedName": "tags", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)tags", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "tags", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)tags", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "tags", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setTags:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setTags:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "extra", + "printedName": "extra", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)extra", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "extra", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)extra", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "extra", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setExtra:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setExtra:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "sdk", + "printedName": "sdk", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)sdk", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sdk", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)sdk", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sdk", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setSdk:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSdk:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "modules", + "printedName": "modules", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)modules", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "modules", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)modules", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "modules", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setModules:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setModules:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "fingerprint", + "printedName": "fingerprint", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)fingerprint", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "fingerprint", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)fingerprint", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "fingerprint", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setFingerprint:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setFingerprint:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "user", + "printedName": "user", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.User?", + "children": [ + { + "kind": "TypeNominal", + "name": "User", + "printedName": "Sentry.User", + "usr": "c:objc(cs)SentryUser" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)user", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "user", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.User?", + "children": [ + { + "kind": "TypeNominal", + "name": "User", + "printedName": "Sentry.User", + "usr": "c:objc(cs)SentryUser" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)user", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "user", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.User?", + "children": [ + { + "kind": "TypeNominal", + "name": "User", + "printedName": "Sentry.User", + "usr": "c:objc(cs)SentryUser" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setUser:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setUser:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "context", + "printedName": "context", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : [Swift.String : Any]]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : [Swift.String : Any]]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)context", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "context", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : [Swift.String : Any]]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : [Swift.String : Any]]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)context", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "context", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : [Swift.String : Any]]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : [Swift.String : Any]]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setContext:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setContext:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "threads", + "printedName": "threads", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Sentry.SentryThread]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.SentryThread]", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryThread", + "printedName": "Sentry.SentryThread", + "usr": "c:objc(cs)SentryThread" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)threads", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "threads", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Sentry.SentryThread]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.SentryThread]", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryThread", + "printedName": "Sentry.SentryThread", + "usr": "c:objc(cs)SentryThread" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)threads", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "threads", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Sentry.SentryThread]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.SentryThread]", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryThread", + "printedName": "Sentry.SentryThread", + "usr": "c:objc(cs)SentryThread" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setThreads:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setThreads:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "exceptions", + "printedName": "exceptions", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Sentry.Exception]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.Exception]", + "children": [ + { + "kind": "TypeNominal", + "name": "Exception", + "printedName": "Sentry.Exception", + "usr": "c:objc(cs)SentryException" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)exceptions", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "exceptions", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Sentry.Exception]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.Exception]", + "children": [ + { + "kind": "TypeNominal", + "name": "Exception", + "printedName": "Sentry.Exception", + "usr": "c:objc(cs)SentryException" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)exceptions", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "exceptions", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Sentry.Exception]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.Exception]", + "children": [ + { + "kind": "TypeNominal", + "name": "Exception", + "printedName": "Sentry.Exception", + "usr": "c:objc(cs)SentryException" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setExceptions:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setExceptions:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "stacktrace", + "printedName": "stacktrace", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryStacktrace?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)stacktrace", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "stacktrace", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryStacktrace?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)stacktrace", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "stacktrace", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryStacktrace?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setStacktrace:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setStacktrace:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "debugMeta", + "printedName": "debugMeta", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Sentry.DebugMeta]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.DebugMeta]", + "children": [ + { + "kind": "TypeNominal", + "name": "DebugMeta", + "printedName": "Sentry.DebugMeta", + "usr": "c:objc(cs)SentryDebugMeta" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)debugMeta", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "debugMeta", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Sentry.DebugMeta]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.DebugMeta]", + "children": [ + { + "kind": "TypeNominal", + "name": "DebugMeta", + "printedName": "Sentry.DebugMeta", + "usr": "c:objc(cs)SentryDebugMeta" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)debugMeta", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "debugMeta", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Sentry.DebugMeta]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.DebugMeta]", + "children": [ + { + "kind": "TypeNominal", + "name": "DebugMeta", + "printedName": "Sentry.DebugMeta", + "usr": "c:objc(cs)SentryDebugMeta" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setDebugMeta:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setDebugMeta:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "breadcrumbs", + "printedName": "breadcrumbs", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Sentry.Breadcrumb]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.Breadcrumb]", + "children": [ + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)breadcrumbs", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "breadcrumbs", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Sentry.Breadcrumb]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.Breadcrumb]", + "children": [ + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)breadcrumbs", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "breadcrumbs", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Sentry.Breadcrumb]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.Breadcrumb]", + "children": [ + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setBreadcrumbs:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setBreadcrumbs:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "request", + "printedName": "request", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryRequest?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRequest", + "printedName": "Sentry.SentryRequest", + "usr": "c:objc(cs)SentryRequest" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEvent(py)request", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "request", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryRequest?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRequest", + "printedName": "Sentry.SentryRequest", + "usr": "c:objc(cs)SentryRequest" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)request", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "request", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryRequest?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRequest", + "printedName": "Sentry.SentryRequest", + "usr": "c:objc(cs)SentryRequest" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEvent(im)setRequest:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setRequest:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryEvent(im)init", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(level:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + }, + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryEvent(im)initWithLevel:", + "moduleName": "Sentry", + "objc_name": "initWithLevel:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(error:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryEvent(im)initWithError:", + "moduleName": "Sentry", + "objc_name": "initWithError:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Convenience" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryEvent", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryEvent", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "Exception", + "printedName": "Exception", + "children": [ + { + "kind": "Var", + "name": "value", + "printedName": "value", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryException(py)value", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "value", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryException(im)value", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "value", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryException(im)setValue:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setValue:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "type", + "printedName": "type", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryException(py)type", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "type", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryException(im)type", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "type", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryException(im)setType:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setType:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "mechanism", + "printedName": "mechanism", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Mechanism?", + "children": [ + { + "kind": "TypeNominal", + "name": "Mechanism", + "printedName": "Sentry.Mechanism", + "usr": "c:objc(cs)SentryMechanism" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryException(py)mechanism", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "mechanism", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Mechanism?", + "children": [ + { + "kind": "TypeNominal", + "name": "Mechanism", + "printedName": "Sentry.Mechanism", + "usr": "c:objc(cs)SentryMechanism" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryException(im)mechanism", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "mechanism", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Mechanism?", + "children": [ + { + "kind": "TypeNominal", + "name": "Mechanism", + "printedName": "Sentry.Mechanism", + "usr": "c:objc(cs)SentryMechanism" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryException(im)setMechanism:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setMechanism:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "module", + "printedName": "module", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryException(py)module", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "module", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryException(im)module", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "module", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryException(im)setModule:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setModule:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "threadId", + "printedName": "threadId", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryException(py)threadId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "threadId", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryException(im)threadId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "threadId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryException(im)setThreadId:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setThreadId:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "stacktrace", + "printedName": "stacktrace", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryStacktrace?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryException(py)stacktrace", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "stacktrace", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryStacktrace?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryException(im)stacktrace", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "stacktrace", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryStacktrace?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryException(im)setStacktrace:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setStacktrace:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(value:type:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Exception", + "printedName": "Sentry.Exception", + "usr": "c:objc(cs)SentryException" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryException(im)initWithValue:type:", + "moduleName": "Sentry", + "objc_name": "initWithValue:type:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryException", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryException", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "Frame", + "printedName": "Frame", + "children": [ + { + "kind": "Var", + "name": "symbolAddress", + "printedName": "symbolAddress", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)symbolAddress", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "symbolAddress", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)symbolAddress", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "symbolAddress", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setSymbolAddress:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSymbolAddress:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "fileName", + "printedName": "fileName", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)fileName", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "fileName", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)fileName", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "fileName", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setFileName:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setFileName:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "function", + "printedName": "function", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)function", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "function", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)function", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "function", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setFunction:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setFunction:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "module", + "printedName": "module", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)module", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "module", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)module", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "module", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setModule:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setModule:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "package", + "printedName": "package", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)package", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "package", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)package", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "package", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setPackage:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setPackage:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "imageAddress", + "printedName": "imageAddress", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)imageAddress", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "imageAddress", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)imageAddress", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "imageAddress", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setImageAddress:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setImageAddress:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "platform", + "printedName": "platform", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)platform", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "platform", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)platform", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "platform", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setPlatform:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setPlatform:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "instructionAddress", + "printedName": "instructionAddress", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)instructionAddress", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "instructionAddress", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)instructionAddress", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "instructionAddress", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setInstructionAddress:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setInstructionAddress:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "instruction", + "printedName": "instruction", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)instruction", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "instruction", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)instruction", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "instruction", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setInstruction:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setInstruction:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "lineNumber", + "printedName": "lineNumber", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)lineNumber", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "lineNumber", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)lineNumber", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "lineNumber", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setLineNumber:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setLineNumber:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "columnNumber", + "printedName": "columnNumber", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)columnNumber", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "columnNumber", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)columnNumber", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "columnNumber", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setColumnNumber:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setColumnNumber:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "contextLine", + "printedName": "contextLine", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)contextLine", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "contextLine", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)contextLine", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "contextLine", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setContextLine:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setContextLine:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "preContext", + "printedName": "preContext", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)preContext", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "preContext", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)preContext", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "preContext", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setPreContext:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setPreContext:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "postContext", + "printedName": "postContext", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)postContext", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "postContext", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)postContext", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "postContext", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setPostContext:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setPostContext:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "inApp", + "printedName": "inApp", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)inApp", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "inApp", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)inApp", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "inApp", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setInApp:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setInApp:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "stackStart", + "printedName": "stackStart", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)stackStart", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "stackStart", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)stackStart", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "stackStart", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setStackStart:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setStackStart:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "vars", + "printedName": "vars", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryFrame(py)vars", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "vars", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)vars", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "vars", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryFrame(im)setVars:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setVars:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "Frame", + "printedName": "Sentry.Frame", + "usr": "c:objc(cs)SentryFrame" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryFrame(im)init", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryFrame", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryFrame", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "Geo", + "printedName": "Geo", + "children": [ + { + "kind": "Var", + "name": "city", + "printedName": "city", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryGeo(py)city", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "city", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryGeo(im)city", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "city", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryGeo(im)setCity:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setCity:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "countryCode", + "printedName": "countryCode", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryGeo(py)countryCode", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "countryCode", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryGeo(im)countryCode", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "countryCode", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryGeo(im)setCountryCode:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setCountryCode:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "region", + "printedName": "region", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryGeo(py)region", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "region", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryGeo(im)region", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "region", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryGeo(im)setRegion:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setRegion:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Function", + "name": "isEqual", + "printedName": "isEqual(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Any?", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryGeo(im)isEqual:", + "moduleName": "Sentry", + "overriding": true, + "isOpen": true, + "objc_name": "isEqual:", + "declAttributes": [ + "DiscardableResult", + "Override", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "isEqual", + "printedName": "isEqual(to:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Geo", + "printedName": "Sentry.Geo", + "usr": "c:objc(cs)SentryGeo" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryGeo(im)isEqualToGeo:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "isEqualToGeo:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "hash", + "printedName": "hash()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryGeo(im)hash", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "hash", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "Geo", + "printedName": "Sentry.Geo", + "usr": "c:objc(cs)SentryGeo" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)NSObject(im)init", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryGeo", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryGeo", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "NSCopying", + "printedName": "NSCopying", + "usr": "c:objc(pl)NSCopying" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "HttpStatusCodeRange", + "printedName": "HttpStatusCodeRange", + "children": [ + { + "kind": "Var", + "name": "min", + "printedName": "min", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryHttpStatusCodeRange(py)min", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "min", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryHttpStatusCodeRange(im)min", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "min", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "max", + "printedName": "max", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryHttpStatusCodeRange(py)max", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "max", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryHttpStatusCodeRange(im)max", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "max", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(min:max:)", + "children": [ + { + "kind": "TypeNominal", + "name": "HttpStatusCodeRange", + "printedName": "Sentry.HttpStatusCodeRange", + "usr": "c:objc(cs)SentryHttpStatusCodeRange" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryHttpStatusCodeRange(im)initWithMin:max:", + "moduleName": "Sentry", + "objc_name": "initWithMin:max:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(statusCode:)", + "children": [ + { + "kind": "TypeNominal", + "name": "HttpStatusCodeRange", + "printedName": "Sentry.HttpStatusCodeRange", + "usr": "c:objc(cs)SentryHttpStatusCodeRange" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryHttpStatusCodeRange(im)initWithStatusCode:", + "moduleName": "Sentry", + "objc_name": "initWithStatusCode:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryHttpStatusCodeRange", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryHttpStatusCodeRange", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "Level", + "printedName": "Level", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Level?", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:So24SentryStructuredLogLevelV8rawValueABSgSi_tcfc", + "mangledName": "$sSo24SentryStructuredLogLevelV8rawValueABSgSi_tcfc", + "moduleName": "Sentry", + "implicit": true, + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:So24SentryStructuredLogLevelV8rawValueSivp", + "mangledName": "$sSo24SentryStructuredLogLevelV8rawValueSivp", + "moduleName": "Sentry", + "implicit": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:So24SentryStructuredLogLevelV8rawValueSivg", + "mangledName": "$sSo24SentryStructuredLogLevelV8rawValueSivg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:So24SentryStructuredLogLevelV8RawValuea", + "mangledName": "$sSo24SentryStructuredLogLevelV8RawValuea", + "moduleName": "Sentry", + "implicit": true + }, + { + "kind": "Var", + "name": "trace", + "printedName": "trace", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Level.Type) -> Sentry.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel@SentryStructuredLogLevelTrace", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "debug", + "printedName": "debug", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Level.Type) -> Sentry.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel@SentryStructuredLogLevelDebug", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "info", + "printedName": "info", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Level.Type) -> Sentry.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel@SentryStructuredLogLevelInfo", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "warn", + "printedName": "warn", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Level.Type) -> Sentry.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel@SentryStructuredLogLevelWarn", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "error", + "printedName": "error", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Level.Type) -> Sentry.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel@SentryStructuredLogLevelError", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "fatal", + "printedName": "fatal", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Level.Type) -> Sentry.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.Level", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel@SentryStructuredLogLevelFatal", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentryStructuredLogLevel", + "moduleName": "Sentry", + "objc_name": "SentryStructuredLogLevel", + "declAttributes": [ + "SynthesizedProtocol", + "ObjC", + "SynthesizedProtocol", + "Sendable", + "Dynamic" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.Level.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + }, + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + } + ] + }, + { + "kind": "TypeDecl", + "name": "MeasurementUnit", + "printedName": "MeasurementUnit", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(unit:)", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnit", + "printedName": "Sentry.MeasurementUnit", + "usr": "c:objc(cs)SentryMeasurementUnit" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryMeasurementUnit(im)initWithUnit:", + "moduleName": "Sentry", + "objc_name": "initWithUnit:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "unit", + "printedName": "unit", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnit(py)unit", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "unit", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnit(im)unit", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "unit", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "none", + "printedName": "none", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnit", + "printedName": "Sentry.MeasurementUnit", + "usr": "c:objc(cs)SentryMeasurementUnit" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnit(cpy)none", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "none", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnit", + "printedName": "Sentry.MeasurementUnit", + "usr": "c:objc(cs)SentryMeasurementUnit" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnit(cm)none", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "none", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryMeasurementUnit", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryMeasurementUnit", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "NSCopying", + "printedName": "NSCopying", + "usr": "c:objc(pl)NSCopying" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "MeasurementUnitDuration", + "printedName": "MeasurementUnitDuration", + "children": [ + { + "kind": "Var", + "name": "nanosecond", + "printedName": "nanosecond", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)nanosecond", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "nanosecond", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)nanosecond", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "nanosecond", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "microsecond", + "printedName": "microsecond", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)microsecond", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "microsecond", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)microsecond", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "microsecond", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "millisecond", + "printedName": "millisecond", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)millisecond", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "millisecond", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)millisecond", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "millisecond", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "second", + "printedName": "second", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)second", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "second", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)second", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "second", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "minute", + "printedName": "minute", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)minute", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "minute", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)minute", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "minute", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "hour", + "printedName": "hour", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)hour", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "hour", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)hour", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "hour", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "day", + "printedName": "day", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)day", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "day", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)day", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "day", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "week", + "printedName": "week", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cpy)week", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "week", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitDuration(cm)week", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "week", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(unit:)", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitDuration", + "printedName": "Sentry.MeasurementUnitDuration", + "usr": "c:objc(cs)SentryMeasurementUnitDuration" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryMeasurementUnit(im)initWithUnit:", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "initWithUnit:", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryMeasurementUnitDuration", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryMeasurementUnitDuration", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)SentryMeasurementUnit", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "Sentry.MeasurementUnit", + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "NSCopying", + "printedName": "NSCopying", + "usr": "c:objc(pl)NSCopying" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "MeasurementUnitFraction", + "printedName": "MeasurementUnitFraction", + "children": [ + { + "kind": "Var", + "name": "ratio", + "printedName": "ratio", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitFraction", + "printedName": "Sentry.MeasurementUnitFraction", + "usr": "c:objc(cs)SentryMeasurementUnitFraction" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitFraction(cpy)ratio", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "ratio", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitFraction", + "printedName": "Sentry.MeasurementUnitFraction", + "usr": "c:objc(cs)SentryMeasurementUnitFraction" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitFraction(cm)ratio", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "ratio", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "percent", + "printedName": "percent", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitFraction", + "printedName": "Sentry.MeasurementUnitFraction", + "usr": "c:objc(cs)SentryMeasurementUnitFraction" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitFraction(cpy)percent", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "percent", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitFraction", + "printedName": "Sentry.MeasurementUnitFraction", + "usr": "c:objc(cs)SentryMeasurementUnitFraction" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitFraction(cm)percent", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "percent", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(unit:)", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitFraction", + "printedName": "Sentry.MeasurementUnitFraction", + "usr": "c:objc(cs)SentryMeasurementUnitFraction" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryMeasurementUnit(im)initWithUnit:", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "initWithUnit:", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryMeasurementUnitFraction", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryMeasurementUnitFraction", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)SentryMeasurementUnit", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "Sentry.MeasurementUnit", + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "NSCopying", + "printedName": "NSCopying", + "usr": "c:objc(pl)NSCopying" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "MeasurementUnitInformation", + "printedName": "MeasurementUnitInformation", + "children": [ + { + "kind": "Var", + "name": "bit", + "printedName": "bit", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)bit", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "bit", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)bit", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "bit", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "byte", + "printedName": "byte", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)byte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "byte", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)byte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "byte", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "kilobyte", + "printedName": "kilobyte", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)kilobyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "kilobyte", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)kilobyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "kilobyte", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "kibibyte", + "printedName": "kibibyte", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)kibibyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "kibibyte", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)kibibyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "kibibyte", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "megabyte", + "printedName": "megabyte", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)megabyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "megabyte", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)megabyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "megabyte", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "mebibyte", + "printedName": "mebibyte", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)mebibyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "mebibyte", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)mebibyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "mebibyte", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "gigabyte", + "printedName": "gigabyte", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)gigabyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "gigabyte", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)gigabyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "gigabyte", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "gibibyte", + "printedName": "gibibyte", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)gibibyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "gibibyte", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)gibibyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "gibibyte", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "terabyte", + "printedName": "terabyte", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)terabyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "terabyte", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)terabyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "terabyte", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "tebibyte", + "printedName": "tebibyte", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)tebibyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "tebibyte", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)tebibyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "tebibyte", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "petabyte", + "printedName": "petabyte", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)petabyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "petabyte", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)petabyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "petabyte", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "pebibyte", + "printedName": "pebibyte", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)pebibyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "pebibyte", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)pebibyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "pebibyte", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "exabyte", + "printedName": "exabyte", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)exabyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "exabyte", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)exabyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "exabyte", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "exbibyte", + "printedName": "exbibyte", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cpy)exbibyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "exbibyte", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMeasurementUnitInformation(cm)exbibyte", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "exbibyte", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(unit:)", + "children": [ + { + "kind": "TypeNominal", + "name": "MeasurementUnitInformation", + "printedName": "Sentry.MeasurementUnitInformation", + "usr": "c:objc(cs)SentryMeasurementUnitInformation" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryMeasurementUnit(im)initWithUnit:", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "initWithUnit:", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryMeasurementUnitInformation", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryMeasurementUnitInformation", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)SentryMeasurementUnit", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "Sentry.MeasurementUnit", + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "NSCopying", + "printedName": "NSCopying", + "usr": "c:objc(pl)NSCopying" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "Mechanism", + "printedName": "Mechanism", + "children": [ + { + "kind": "Var", + "name": "type", + "printedName": "type", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMechanism(py)type", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "type", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)type", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "type", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)setType:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setType:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "desc", + "printedName": "desc", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMechanism(py)desc", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "desc", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)desc", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "desc", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)setDesc:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setDesc:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "data", + "printedName": "data", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMechanism(py)data", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "data", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)data", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "data", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)setData:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setData:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "handled", + "printedName": "handled", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMechanism(py)handled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "handled", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)handled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "handled", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)setHandled:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setHandled:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "synthetic", + "printedName": "synthetic", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMechanism(py)synthetic", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "synthetic", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)synthetic", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "synthetic", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)setSynthetic:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSynthetic:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "helpLink", + "printedName": "helpLink", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMechanism(py)helpLink", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "helpLink", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)helpLink", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "helpLink", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)setHelpLink:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setHelpLink:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "meta", + "printedName": "meta", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.MechanismMeta?", + "children": [ + { + "kind": "TypeNominal", + "name": "MechanismMeta", + "printedName": "Sentry.MechanismMeta", + "usr": "c:objc(cs)SentryMechanismMeta" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMechanism(py)meta", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "meta", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.MechanismMeta?", + "children": [ + { + "kind": "TypeNominal", + "name": "MechanismMeta", + "printedName": "Sentry.MechanismMeta", + "usr": "c:objc(cs)SentryMechanismMeta" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)meta", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "meta", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.MechanismMeta?", + "children": [ + { + "kind": "TypeNominal", + "name": "MechanismMeta", + "printedName": "Sentry.MechanismMeta", + "usr": "c:objc(cs)SentryMechanismMeta" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanism(im)setMeta:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setMeta:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(type:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Mechanism", + "printedName": "Sentry.Mechanism", + "usr": "c:objc(cs)SentryMechanism" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryMechanism(im)initWithType:", + "moduleName": "Sentry", + "objc_name": "initWithType:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryMechanism", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryMechanism", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "MechanismMeta", + "printedName": "MechanismMeta", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "MechanismMeta", + "printedName": "Sentry.MechanismMeta", + "usr": "c:objc(cs)SentryMechanismMeta" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryMechanismMeta(im)init", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "signal", + "printedName": "signal", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMechanismMeta(py)signal", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "signal", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanismMeta(im)signal", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "signal", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanismMeta(im)setSignal:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSignal:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "machException", + "printedName": "machException", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMechanismMeta(py)machException", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "machException", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanismMeta(im)machException", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "machException", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanismMeta(im)setMachException:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setMachException:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "error", + "printedName": "error", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryNSError?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryNSError", + "printedName": "Sentry.SentryNSError", + "usr": "c:objc(cs)SentryNSError" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMechanismMeta(py)error", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "error", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryNSError?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryNSError", + "printedName": "Sentry.SentryNSError", + "usr": "c:objc(cs)SentryNSError" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanismMeta(im)error", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "error", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryNSError?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryNSError", + "printedName": "Sentry.SentryNSError", + "usr": "c:objc(cs)SentryNSError" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMechanismMeta(im)setError:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setError:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryMechanismMeta", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryMechanismMeta", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "Function", + "name": "NSErrorFromSentryError", + "printedName": "NSErrorFromSentryError(_:_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Swift.Error)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@F@NSErrorFromSentryError", + "moduleName": "Sentry", + "declAttributes": [ + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "NSErrorFromSentryErrorWithException", + "printedName": "NSErrorFromSentryErrorWithException(_:_:_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Swift.Error)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "NSException", + "printedName": "Foundation.NSException", + "usr": "c:objc(cs)NSException" + } + ], + "declKind": "Func", + "usr": "c:@F@NSErrorFromSentryErrorWithException", + "moduleName": "Sentry", + "declAttributes": [ + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "NSErrorFromSentryErrorWithKernelError", + "printedName": "NSErrorFromSentryErrorWithKernelError(_:_:_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Swift.Error)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNameAlias", + "name": "kern_return_t", + "printedName": "Darwin.kern_return_t", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ] + } + ], + "declKind": "Func", + "usr": "c:@F@NSErrorFromSentryErrorWithKernelError", + "moduleName": "Sentry", + "declAttributes": [ + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "NSErrorFromSentryErrorWithUnderlyingError", + "printedName": "NSErrorFromSentryErrorWithUnderlyingError(_:_:_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Swift.Error)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "declKind": "Func", + "usr": "c:@F@NSErrorFromSentryErrorWithUnderlyingError", + "moduleName": "Sentry", + "declAttributes": [ + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "TypeDecl", + "name": "Options", + "printedName": "Options", + "children": [ + { + "kind": "Var", + "name": "dsn", + "printedName": "dsn", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)dsn", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "dsn", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)dsn", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "dsn", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setDsn:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setDsn:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "parsedDsn", + "printedName": "parsedDsn", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryDsn?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryDsn", + "printedName": "Sentry.SentryDsn", + "usr": "c:objc(cs)SentryDsn" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)parsedDsn", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "parsedDsn", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryDsn?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryDsn", + "printedName": "Sentry.SentryDsn", + "usr": "c:objc(cs)SentryDsn" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)parsedDsn", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "parsedDsn", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryDsn?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryDsn", + "printedName": "Sentry.SentryDsn", + "usr": "c:objc(cs)SentryDsn" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setParsedDsn:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setParsedDsn:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "debug", + "printedName": "debug", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)debug", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "debug", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)debug", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "debug", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setDebug:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setDebug:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "diagnosticLevel", + "printedName": "diagnosticLevel", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)diagnosticLevel", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "diagnosticLevel", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)diagnosticLevel", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "diagnosticLevel", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setDiagnosticLevel:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setDiagnosticLevel:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "releaseName", + "printedName": "releaseName", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)releaseName", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "releaseName", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)releaseName", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "releaseName", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setReleaseName:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setReleaseName:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "dist", + "printedName": "dist", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)dist", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "dist", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)dist", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "dist", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setDist:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setDist:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "environment", + "printedName": "environment", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)environment", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "environment", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)environment", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "environment", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnvironment:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnvironment:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enabled", + "printedName": "enabled", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enabled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enabled", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enabled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enabled", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnabled:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnabled:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "shutdownTimeInterval", + "printedName": "shutdownTimeInterval", + "children": [ + { + "kind": "TypeNameAlias", + "name": "TimeInterval", + "printedName": "Foundation.TimeInterval", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ] + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)shutdownTimeInterval", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "shutdownTimeInterval", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "TimeInterval", + "printedName": "Foundation.TimeInterval", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ] + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)shutdownTimeInterval", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "shutdownTimeInterval", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNameAlias", + "name": "TimeInterval", + "printedName": "Foundation.TimeInterval", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ] + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setShutdownTimeInterval:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setShutdownTimeInterval:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableCrashHandler", + "printedName": "enableCrashHandler", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableCrashHandler", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableCrashHandler", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableCrashHandler", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableCrashHandler", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableCrashHandler:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableCrashHandler:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableSigtermReporting", + "printedName": "enableSigtermReporting", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableSigtermReporting", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableSigtermReporting", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableSigtermReporting", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableSigtermReporting", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableSigtermReporting:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableSigtermReporting:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "maxBreadcrumbs", + "printedName": "maxBreadcrumbs", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)maxBreadcrumbs", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "maxBreadcrumbs", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)maxBreadcrumbs", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "maxBreadcrumbs", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setMaxBreadcrumbs:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setMaxBreadcrumbs:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableNetworkBreadcrumbs", + "printedName": "enableNetworkBreadcrumbs", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableNetworkBreadcrumbs", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableNetworkBreadcrumbs", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableNetworkBreadcrumbs", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableNetworkBreadcrumbs", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableNetworkBreadcrumbs:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableNetworkBreadcrumbs:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "maxCacheItems", + "printedName": "maxCacheItems", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)maxCacheItems", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "maxCacheItems", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)maxCacheItems", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "maxCacheItems", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setMaxCacheItems:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setMaxCacheItems:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "beforeSend", + "printedName": "beforeSend", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Sentry.Event?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Sentry.Event?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Event?", + "children": [ + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)beforeSend", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeSend", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Sentry.Event?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Sentry.Event?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Event?", + "children": [ + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)beforeSend", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeSend", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Sentry.Event?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Sentry.Event?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Event?", + "children": [ + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setBeforeSend:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setBeforeSend:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "beforeSendSpan", + "printedName": "beforeSendSpan", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((any Sentry.Span) -> (any Sentry.Span)?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(any Sentry.Span) -> (any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)beforeSendSpan", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeSendSpan", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((any Sentry.Span) -> (any Sentry.Span)?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(any Sentry.Span) -> (any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)beforeSendSpan", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeSendSpan", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((any Sentry.Span) -> (any Sentry.Span)?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(any Sentry.Span) -> (any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setBeforeSendSpan:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setBeforeSendSpan:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "beforeSendLog", + "printedName": "beforeSendLog", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryLog) -> Sentry.SentryLog?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog) -> Sentry.SentryLog?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryLog?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)beforeSendLog", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeSendLog", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryLog) -> Sentry.SentryLog?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog) -> Sentry.SentryLog?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryLog?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)beforeSendLog", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeSendLog", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryLog) -> Sentry.SentryLog?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog) -> Sentry.SentryLog?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryLog?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setBeforeSendLog:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setBeforeSendLog:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "beforeBreadcrumb", + "printedName": "beforeBreadcrumb", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Breadcrumb) -> Sentry.Breadcrumb?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Breadcrumb) -> Sentry.Breadcrumb?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Breadcrumb?", + "children": [ + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)beforeBreadcrumb", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeBreadcrumb", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Breadcrumb) -> Sentry.Breadcrumb?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Breadcrumb) -> Sentry.Breadcrumb?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Breadcrumb?", + "children": [ + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)beforeBreadcrumb", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeBreadcrumb", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Breadcrumb) -> Sentry.Breadcrumb?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Breadcrumb) -> Sentry.Breadcrumb?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Breadcrumb?", + "children": [ + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setBeforeBreadcrumb:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setBeforeBreadcrumb:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "beforeCaptureScreenshot", + "printedName": "beforeCaptureScreenshot", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Swift.Bool)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Bool", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)beforeCaptureScreenshot", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeCaptureScreenshot", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Swift.Bool)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Bool", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)beforeCaptureScreenshot", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeCaptureScreenshot", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Swift.Bool)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Bool", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setBeforeCaptureScreenshot:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setBeforeCaptureScreenshot:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "beforeCaptureViewHierarchy", + "printedName": "beforeCaptureViewHierarchy", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Swift.Bool)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Bool", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)beforeCaptureViewHierarchy", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeCaptureViewHierarchy", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Swift.Bool)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Bool", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)beforeCaptureViewHierarchy", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "beforeCaptureViewHierarchy", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Swift.Bool)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Bool", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setBeforeCaptureViewHierarchy:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setBeforeCaptureViewHierarchy:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "onCrashedLastRun", + "printedName": "onCrashedLastRun", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)onCrashedLastRun", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "onCrashedLastRun", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)onCrashedLastRun", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "onCrashedLastRun", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.Event) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setOnCrashedLastRun:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setOnCrashedLastRun:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Function", + "name": "defaultIntegrations", + "printedName": "defaultIntegrations()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryOptions(cm)defaultIntegrations", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "defaultIntegrations", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Var", + "name": "sampleRate", + "printedName": "sampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)sampleRate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRate", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)sampleRate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRate", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setSampleRate:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSampleRate:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableAutoSessionTracking", + "printedName": "enableAutoSessionTracking", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableAutoSessionTracking", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableAutoSessionTracking", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableAutoSessionTracking", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableAutoSessionTracking", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableAutoSessionTracking:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableAutoSessionTracking:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableGraphQLOperationTracking", + "printedName": "enableGraphQLOperationTracking", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableGraphQLOperationTracking", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableGraphQLOperationTracking", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableGraphQLOperationTracking", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableGraphQLOperationTracking", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableGraphQLOperationTracking:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableGraphQLOperationTracking:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableWatchdogTerminationTracking", + "printedName": "enableWatchdogTerminationTracking", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableWatchdogTerminationTracking", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableWatchdogTerminationTracking", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableWatchdogTerminationTracking", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableWatchdogTerminationTracking", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableWatchdogTerminationTracking:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableWatchdogTerminationTracking:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "sessionTrackingIntervalMillis", + "printedName": "sessionTrackingIntervalMillis", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)sessionTrackingIntervalMillis", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sessionTrackingIntervalMillis", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)sessionTrackingIntervalMillis", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sessionTrackingIntervalMillis", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setSessionTrackingIntervalMillis:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSessionTrackingIntervalMillis:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "attachStacktrace", + "printedName": "attachStacktrace", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)attachStacktrace", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "attachStacktrace", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)attachStacktrace", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "attachStacktrace", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setAttachStacktrace:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setAttachStacktrace:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "maxAttachmentSize", + "printedName": "maxAttachmentSize", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)maxAttachmentSize", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "maxAttachmentSize", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)maxAttachmentSize", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "maxAttachmentSize", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setMaxAttachmentSize:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setMaxAttachmentSize:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "sendDefaultPii", + "printedName": "sendDefaultPii", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)sendDefaultPii", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sendDefaultPii", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)sendDefaultPii", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sendDefaultPii", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setSendDefaultPii:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSendDefaultPii:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableAutoPerformanceTracing", + "printedName": "enableAutoPerformanceTracing", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableAutoPerformanceTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableAutoPerformanceTracing", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableAutoPerformanceTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableAutoPerformanceTracing", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableAutoPerformanceTracing:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableAutoPerformanceTracing:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enablePerformanceV2", + "printedName": "enablePerformanceV2", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enablePerformanceV2", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enablePerformanceV2", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enablePerformanceV2", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enablePerformanceV2", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnablePerformanceV2:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnablePerformanceV2:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enablePersistingTracesWhenCrashing", + "printedName": "enablePersistingTracesWhenCrashing", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enablePersistingTracesWhenCrashing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enablePersistingTracesWhenCrashing", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enablePersistingTracesWhenCrashing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enablePersistingTracesWhenCrashing", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnablePersistingTracesWhenCrashing:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnablePersistingTracesWhenCrashing:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "initialScope", + "printedName": "initialScope", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Sentry.Scope", + "children": [ + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ] + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)initialScope", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "initialScope", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Sentry.Scope", + "children": [ + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ] + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)initialScope", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "initialScope", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Sentry.Scope", + "children": [ + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ] + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setInitialScope:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setInitialScope:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableUIViewControllerTracing", + "printedName": "enableUIViewControllerTracing", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableUIViewControllerTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableUIViewControllerTracing", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableUIViewControllerTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableUIViewControllerTracing", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableUIViewControllerTracing:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableUIViewControllerTracing:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "attachScreenshot", + "printedName": "attachScreenshot", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)attachScreenshot", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "attachScreenshot", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)attachScreenshot", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "attachScreenshot", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setAttachScreenshot:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setAttachScreenshot:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "screenshot", + "printedName": "screenshot", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryViewScreenshotOptions", + "printedName": "Sentry.SentryViewScreenshotOptions", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)screenshot", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "screenshot", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryViewScreenshotOptions", + "printedName": "Sentry.SentryViewScreenshotOptions", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)screenshot", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "screenshot", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryViewScreenshotOptions", + "printedName": "Sentry.SentryViewScreenshotOptions", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setScreenshot:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setScreenshot:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "attachViewHierarchy", + "printedName": "attachViewHierarchy", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)attachViewHierarchy", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "attachViewHierarchy", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)attachViewHierarchy", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "attachViewHierarchy", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setAttachViewHierarchy:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setAttachViewHierarchy:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "reportAccessibilityIdentifier", + "printedName": "reportAccessibilityIdentifier", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)reportAccessibilityIdentifier", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "reportAccessibilityIdentifier", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)reportAccessibilityIdentifier", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "reportAccessibilityIdentifier", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setReportAccessibilityIdentifier:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setReportAccessibilityIdentifier:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableUserInteractionTracing", + "printedName": "enableUserInteractionTracing", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableUserInteractionTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableUserInteractionTracing", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableUserInteractionTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableUserInteractionTracing", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableUserInteractionTracing:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableUserInteractionTracing:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "idleTimeout", + "printedName": "idleTimeout", + "children": [ + { + "kind": "TypeNameAlias", + "name": "TimeInterval", + "printedName": "Foundation.TimeInterval", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ] + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)idleTimeout", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "idleTimeout", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "TimeInterval", + "printedName": "Foundation.TimeInterval", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ] + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)idleTimeout", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "idleTimeout", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNameAlias", + "name": "TimeInterval", + "printedName": "Foundation.TimeInterval", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ] + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setIdleTimeout:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setIdleTimeout:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enablePreWarmedAppStartTracing", + "printedName": "enablePreWarmedAppStartTracing", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enablePreWarmedAppStartTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enablePreWarmedAppStartTracing", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enablePreWarmedAppStartTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enablePreWarmedAppStartTracing", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnablePreWarmedAppStartTracing:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnablePreWarmedAppStartTracing:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "sessionReplay", + "printedName": "sessionReplay", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayOptions", + "printedName": "Sentry.SentryReplayOptions", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)sessionReplay", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sessionReplay", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayOptions", + "printedName": "Sentry.SentryReplayOptions", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)sessionReplay", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sessionReplay", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryReplayOptions", + "printedName": "Sentry.SentryReplayOptions", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setSessionReplay:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSessionReplay:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableNetworkTracking", + "printedName": "enableNetworkTracking", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableNetworkTracking", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableNetworkTracking", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableNetworkTracking", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableNetworkTracking", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableNetworkTracking:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableNetworkTracking:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableFileIOTracing", + "printedName": "enableFileIOTracing", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableFileIOTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableFileIOTracing", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableFileIOTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableFileIOTracing", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableFileIOTracing:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableFileIOTracing:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "tracesSampleRate", + "printedName": "tracesSampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)tracesSampleRate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "tracesSampleRate", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)tracesSampleRate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "tracesSampleRate", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setTracesSampleRate:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setTracesSampleRate:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "tracesSampler", + "printedName": "tracesSampler", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SamplingContext) -> Foundation.NSNumber?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SamplingContext) -> Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SamplingContext", + "printedName": "Sentry.SamplingContext", + "usr": "c:objc(cs)SentrySamplingContext" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)tracesSampler", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "tracesSampler", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SamplingContext) -> Foundation.NSNumber?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SamplingContext) -> Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SamplingContext", + "printedName": "Sentry.SamplingContext", + "usr": "c:objc(cs)SentrySamplingContext" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)tracesSampler", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "tracesSampler", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SamplingContext) -> Foundation.NSNumber?)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SamplingContext) -> Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SamplingContext", + "printedName": "Sentry.SamplingContext", + "usr": "c:objc(cs)SentrySamplingContext" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setTracesSampler:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setTracesSampler:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "isTracingEnabled", + "printedName": "isTracingEnabled", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)isTracingEnabled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "isTracingEnabled", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)isTracingEnabled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "isTracingEnabled", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "inAppIncludes", + "printedName": "inAppIncludes", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)inAppIncludes", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "inAppIncludes", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)inAppIncludes", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "inAppIncludes", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Function", + "name": "add", + "printedName": "add(inAppInclude:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryOptions(im)addInAppInclude:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "addInAppInclude:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Var", + "name": "inAppExcludes", + "printedName": "inAppExcludes", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)inAppExcludes", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "inAppExcludes", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)inAppExcludes", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "inAppExcludes", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Function", + "name": "add", + "printedName": "add(inAppExclude:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryOptions(im)addInAppExclude:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "addInAppExclude:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Var", + "name": "urlSessionDelegate", + "printedName": "urlSessionDelegate", + "children": [ + { + "kind": "TypeNominal", + "name": "WeakStorage", + "printedName": "(any Foundation.URLSessionDelegate)?" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)urlSessionDelegate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "urlSessionDelegate", + "declAttributes": [ + "ReferenceOwnership", + "ObjC", + "Dynamic" + ], + "ownership": 1, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Foundation.URLSessionDelegate)?", + "children": [ + { + "kind": "TypeNominal", + "name": "URLSessionDelegate", + "printedName": "any Foundation.URLSessionDelegate", + "usr": "c:objc(pl)NSURLSessionDelegate" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)urlSessionDelegate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "urlSessionDelegate", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Foundation.URLSessionDelegate)?", + "children": [ + { + "kind": "TypeNominal", + "name": "URLSessionDelegate", + "printedName": "any Foundation.URLSessionDelegate", + "usr": "c:objc(pl)NSURLSessionDelegate" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setUrlSessionDelegate:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setUrlSessionDelegate:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "urlSession", + "printedName": "urlSession", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.URLSession?", + "children": [ + { + "kind": "TypeNominal", + "name": "URLSession", + "printedName": "Foundation.URLSession", + "usr": "c:objc(cs)NSURLSession" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)urlSession", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "urlSession", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.URLSession?", + "children": [ + { + "kind": "TypeNominal", + "name": "URLSession", + "printedName": "Foundation.URLSession", + "usr": "c:objc(cs)NSURLSession" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)urlSession", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "urlSession", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.URLSession?", + "children": [ + { + "kind": "TypeNominal", + "name": "URLSession", + "printedName": "Foundation.URLSession", + "usr": "c:objc(cs)NSURLSession" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setUrlSession:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setUrlSession:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableSwizzling", + "printedName": "enableSwizzling", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableSwizzling", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableSwizzling", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableSwizzling", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableSwizzling", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableSwizzling:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableSwizzling:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "swizzleClassNameExcludes", + "printedName": "swizzleClassNameExcludes", + "children": [ + { + "kind": "TypeNominal", + "name": "Set", + "printedName": "Swift.Set", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sh" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)swizzleClassNameExcludes", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "swizzleClassNameExcludes", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Set", + "printedName": "Swift.Set", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sh" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)swizzleClassNameExcludes", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "swizzleClassNameExcludes", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Set", + "printedName": "Swift.Set", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sh" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setSwizzleClassNameExcludes:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSwizzleClassNameExcludes:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableCoreDataTracing", + "printedName": "enableCoreDataTracing", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableCoreDataTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableCoreDataTracing", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableCoreDataTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableCoreDataTracing", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableCoreDataTracing:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableCoreDataTracing:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "configureProfiling", + "printedName": "configureProfiling", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryProfilingConfigurationBlock?", + "children": [ + { + "kind": "TypeNameAlias", + "name": "SentryProfilingConfigurationBlock", + "printedName": "Sentry.SentryProfilingConfigurationBlock", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryProfileOptions) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryProfileOptions", + "printedName": "Sentry.SentryProfileOptions", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions" + } + ] + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)configureProfiling", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "configureProfiling", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryProfilingConfigurationBlock?", + "children": [ + { + "kind": "TypeNameAlias", + "name": "SentryProfilingConfigurationBlock", + "printedName": "Sentry.SentryProfilingConfigurationBlock", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryProfileOptions) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryProfileOptions", + "printedName": "Sentry.SentryProfileOptions", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions" + } + ] + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)configureProfiling", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "configureProfiling", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryProfilingConfigurationBlock?", + "children": [ + { + "kind": "TypeNameAlias", + "name": "SentryProfilingConfigurationBlock", + "printedName": "Sentry.SentryProfilingConfigurationBlock", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryProfileOptions) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryProfileOptions", + "printedName": "Sentry.SentryProfileOptions", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions" + } + ] + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setConfigureProfiling:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setConfigureProfiling:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "sendClientReports", + "printedName": "sendClientReports", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)sendClientReports", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sendClientReports", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)sendClientReports", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sendClientReports", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setSendClientReports:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSendClientReports:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableAppHangTracking", + "printedName": "enableAppHangTracking", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableAppHangTracking", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableAppHangTracking", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableAppHangTracking", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableAppHangTracking", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableAppHangTracking:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableAppHangTracking:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableReportNonFullyBlockingAppHangs", + "printedName": "enableReportNonFullyBlockingAppHangs", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableReportNonFullyBlockingAppHangs", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableReportNonFullyBlockingAppHangs", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableReportNonFullyBlockingAppHangs", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableReportNonFullyBlockingAppHangs", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableReportNonFullyBlockingAppHangs:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableReportNonFullyBlockingAppHangs:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "appHangTimeoutInterval", + "printedName": "appHangTimeoutInterval", + "children": [ + { + "kind": "TypeNameAlias", + "name": "TimeInterval", + "printedName": "Foundation.TimeInterval", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ] + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)appHangTimeoutInterval", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "appHangTimeoutInterval", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "TimeInterval", + "printedName": "Foundation.TimeInterval", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ] + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)appHangTimeoutInterval", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "appHangTimeoutInterval", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNameAlias", + "name": "TimeInterval", + "printedName": "Foundation.TimeInterval", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ] + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setAppHangTimeoutInterval:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setAppHangTimeoutInterval:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableAutoBreadcrumbTracking", + "printedName": "enableAutoBreadcrumbTracking", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableAutoBreadcrumbTracking", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableAutoBreadcrumbTracking", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableAutoBreadcrumbTracking", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableAutoBreadcrumbTracking", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableAutoBreadcrumbTracking:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableAutoBreadcrumbTracking:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "tracePropagationTargets", + "printedName": "tracePropagationTargets", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)tracePropagationTargets", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "tracePropagationTargets", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)tracePropagationTargets", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "tracePropagationTargets", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setTracePropagationTargets:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setTracePropagationTargets:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableCaptureFailedRequests", + "printedName": "enableCaptureFailedRequests", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableCaptureFailedRequests", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableCaptureFailedRequests", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableCaptureFailedRequests", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableCaptureFailedRequests", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableCaptureFailedRequests:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableCaptureFailedRequests:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "failedRequestStatusCodes", + "printedName": "failedRequestStatusCodes", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.HttpStatusCodeRange]", + "children": [ + { + "kind": "TypeNominal", + "name": "HttpStatusCodeRange", + "printedName": "Sentry.HttpStatusCodeRange", + "usr": "c:objc(cs)SentryHttpStatusCodeRange" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)failedRequestStatusCodes", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "failedRequestStatusCodes", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.HttpStatusCodeRange]", + "children": [ + { + "kind": "TypeNominal", + "name": "HttpStatusCodeRange", + "printedName": "Sentry.HttpStatusCodeRange", + "usr": "c:objc(cs)SentryHttpStatusCodeRange" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)failedRequestStatusCodes", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "failedRequestStatusCodes", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.HttpStatusCodeRange]", + "children": [ + { + "kind": "TypeNominal", + "name": "HttpStatusCodeRange", + "printedName": "Sentry.HttpStatusCodeRange", + "usr": "c:objc(cs)SentryHttpStatusCodeRange" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setFailedRequestStatusCodes:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setFailedRequestStatusCodes:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "failedRequestTargets", + "printedName": "failedRequestTargets", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)failedRequestTargets", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "failedRequestTargets", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)failedRequestTargets", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "failedRequestTargets", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setFailedRequestTargets:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setFailedRequestTargets:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableMetricKit", + "printedName": "enableMetricKit", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableMetricKit", + "moduleName": "Sentry", + "isOpen": true, + "intro_iOS": "15.0", + "objc_name": "enableMetricKit", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableMetricKit", + "moduleName": "Sentry", + "isOpen": true, + "intro_iOS": "15.0", + "objc_name": "enableMetricKit", + "declAttributes": [ + "DiscardableResult", + "Available", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableMetricKit:", + "moduleName": "Sentry", + "isOpen": true, + "intro_iOS": "15.0", + "objc_name": "setEnableMetricKit:", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableMetricKitRawPayload", + "printedName": "enableMetricKitRawPayload", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableMetricKitRawPayload", + "moduleName": "Sentry", + "isOpen": true, + "intro_iOS": "15.0", + "objc_name": "enableMetricKitRawPayload", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableMetricKitRawPayload", + "moduleName": "Sentry", + "isOpen": true, + "intro_iOS": "15.0", + "objc_name": "enableMetricKitRawPayload", + "declAttributes": [ + "DiscardableResult", + "Available", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableMetricKitRawPayload:", + "moduleName": "Sentry", + "isOpen": true, + "intro_iOS": "15.0", + "objc_name": "setEnableMetricKitRawPayload:", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableTimeToFullDisplayTracing", + "printedName": "enableTimeToFullDisplayTracing", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableTimeToFullDisplayTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableTimeToFullDisplayTracing", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableTimeToFullDisplayTracing", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableTimeToFullDisplayTracing", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableTimeToFullDisplayTracing:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableTimeToFullDisplayTracing:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "swiftAsyncStacktraces", + "printedName": "swiftAsyncStacktraces", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)swiftAsyncStacktraces", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "swiftAsyncStacktraces", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)swiftAsyncStacktraces", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "swiftAsyncStacktraces", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setSwiftAsyncStacktraces:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSwiftAsyncStacktraces:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "cacheDirectoryPath", + "printedName": "cacheDirectoryPath", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)cacheDirectoryPath", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "cacheDirectoryPath", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)cacheDirectoryPath", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "cacheDirectoryPath", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setCacheDirectoryPath:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setCacheDirectoryPath:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableSpotlight", + "printedName": "enableSpotlight", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)enableSpotlight", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableSpotlight", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)enableSpotlight", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "enableSpotlight", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setEnableSpotlight:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnableSpotlight:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "spotlightUrl", + "printedName": "spotlightUrl", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)spotlightUrl", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "spotlightUrl", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)spotlightUrl", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "spotlightUrl", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setSpotlightUrl:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSpotlightUrl:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "_swiftExperimentalOptions", + "printedName": "_swiftExperimentalOptions", + "children": [ + { + "kind": "TypeNominal", + "name": "NSObject", + "printedName": "ObjectiveC.NSObject", + "usr": "c:objc(cs)NSObject" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)_swiftExperimentalOptions", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "_swiftExperimentalOptions", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "NSObject", + "printedName": "ObjectiveC.NSObject", + "usr": "c:objc(cs)NSObject" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)_swiftExperimentalOptions", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "_swiftExperimentalOptions", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "configureUserFeedback", + "printedName": "configureUserFeedback", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryUserFeedbackConfigurationBlock?", + "children": [ + { + "kind": "TypeNameAlias", + "name": "SentryUserFeedbackConfigurationBlock", + "printedName": "Sentry.SentryUserFeedbackConfigurationBlock", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackConfiguration", + "printedName": "Sentry.SentryUserFeedbackConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration" + } + ] + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryOptions(py)configureUserFeedback", + "moduleName": "Sentry", + "isOpen": true, + "intro_iOS": "13.0", + "objc_name": "configureUserFeedback", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryUserFeedbackConfigurationBlock?", + "children": [ + { + "kind": "TypeNameAlias", + "name": "SentryUserFeedbackConfigurationBlock", + "printedName": "Sentry.SentryUserFeedbackConfigurationBlock", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackConfiguration", + "printedName": "Sentry.SentryUserFeedbackConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration" + } + ] + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)configureUserFeedback", + "moduleName": "Sentry", + "isOpen": true, + "intro_iOS": "13.0", + "objc_name": "configureUserFeedback", + "declAttributes": [ + "DiscardableResult", + "Available", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryUserFeedbackConfigurationBlock?", + "children": [ + { + "kind": "TypeNameAlias", + "name": "SentryUserFeedbackConfigurationBlock", + "printedName": "Sentry.SentryUserFeedbackConfigurationBlock", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackConfiguration", + "printedName": "Sentry.SentryUserFeedbackConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration" + } + ] + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryOptions(im)setConfigureUserFeedback:", + "moduleName": "Sentry", + "isOpen": true, + "intro_iOS": "13.0", + "objc_name": "setConfigureUserFeedback:", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "Options", + "printedName": "Sentry.Options", + "usr": "c:objc(cs)SentryOptions" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)NSObject(im)init", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "experimental", + "printedName": "experimental", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryExperimentalOptions", + "printedName": "Sentry.SentryExperimentalOptions", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions" + } + ], + "declKind": "Var", + "usr": "c:@CM@Sentry@@objc(cs)SentryOptions(py)experimental", + "mangledName": "$sSo13SentryOptionsC0A0E12experimentalAC0a12ExperimentalB0Cvp", + "moduleName": "Sentry", + "isOpen": true, + "declAttributes": [ + "Dynamic", + "ObjC" + ], + "isFromExtension": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryExperimentalOptions", + "printedName": "Sentry.SentryExperimentalOptions", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions" + } + ], + "declKind": "Accessor", + "usr": "c:@CM@Sentry@@objc(cs)SentryOptions(im)experimental", + "mangledName": "$sSo13SentryOptionsC0A0E12experimentalAC0a12ExperimentalB0Cvg", + "moduleName": "Sentry", + "isOpen": true, + "declAttributes": [ + "Dynamic", + "ObjC" + ], + "isFromExtension": true, + "accessorKind": "get" + } + ] + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryOptions", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryOptions", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "Var", + "name": "SENTRY_BAGGAGE_HEADER", + "printedName": "SENTRY_BAGGAGE_HEADER", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@SENTRY_BAGGAGE_HEADER", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "SENTRY_TRACE_HEADER", + "printedName": "SENTRY_TRACE_HEADER", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@SENTRY_TRACE_HEADER", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "SENTRY_TRACE_TYPE", + "printedName": "SENTRY_TRACE_TYPE", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@SENTRY_TRACE_TYPE", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "TypeDecl", + "name": "SamplingContext", + "printedName": "SamplingContext", + "children": [ + { + "kind": "Var", + "name": "transactionContext", + "printedName": "transactionContext", + "children": [ + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentrySamplingContext(py)transactionContext", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "transactionContext", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentrySamplingContext(im)transactionContext", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "transactionContext", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "customSamplingContext", + "printedName": "customSamplingContext", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentrySamplingContext(py)customSamplingContext", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "customSamplingContext", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentrySamplingContext(im)customSamplingContext", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "customSamplingContext", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(transactionContext:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SamplingContext", + "printedName": "Sentry.SamplingContext", + "usr": "c:objc(cs)SentrySamplingContext" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentrySamplingContext(im)initWithTransactionContext:", + "moduleName": "Sentry", + "objc_name": "initWithTransactionContext:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(transactionContext:customSamplingContext:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SamplingContext", + "printedName": "Sentry.SamplingContext", + "usr": "c:objc(cs)SentrySamplingContext" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentrySamplingContext(im)initWithTransactionContext:customSamplingContext:", + "moduleName": "Sentry", + "objc_name": "initWithTransactionContext:customSamplingContext:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SamplingContext", + "printedName": "Sentry.SamplingContext", + "usr": "c:objc(cs)SentrySamplingContext" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)NSObject(im)init", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentrySamplingContext", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentrySamplingContext", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "Scope", + "printedName": "Scope", + "children": [ + { + "kind": "Var", + "name": "span", + "printedName": "span", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryScope(py)span", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "span", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryScope(im)span", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "span", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "replayId", + "printedName": "replayId", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryScope(py)replayId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "replayId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryScope(im)replayId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "replayId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryScope(im)setReplayId:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setReplayId:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "tags", + "printedName": "tags", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryScope(py)tags", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "tags", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryScope(im)tags", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "tags", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(maxBreadcrumbs:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryScope(im)initWithMaxBreadcrumbs:", + "moduleName": "Sentry", + "objc_name": "initWithMaxBreadcrumbs:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryScope(im)init", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Convenience" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryScope(im)initWithScope:", + "moduleName": "Sentry", + "objc_name": "initWithScope:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Convenience" + }, + { + "kind": "Function", + "name": "setUser", + "printedName": "setUser(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.User?", + "children": [ + { + "kind": "TypeNominal", + "name": "User", + "printedName": "Sentry.User", + "usr": "c:objc(cs)SentryUser" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)setUser:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setUser:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setTag", + "printedName": "setTag(value:key:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)setTagValue:forKey:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setTagValue:forKey:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "removeTag", + "printedName": "removeTag(key:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)removeTagForKey:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "removeTagForKey:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setTags", + "printedName": "setTags(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)setTags:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setTags:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setExtras", + "printedName": "setExtras(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)setExtras:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setExtras:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setExtra", + "printedName": "setExtra(value:key:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Any?", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)setExtraValue:forKey:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setExtraValue:forKey:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "removeExtra", + "printedName": "removeExtra(key:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)removeExtraForKey:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "removeExtraForKey:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setDist", + "printedName": "setDist(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)setDist:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setDist:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setEnvironment", + "printedName": "setEnvironment(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)setEnvironment:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEnvironment:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setFingerprint", + "printedName": "setFingerprint(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)setFingerprint:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setFingerprint:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setLevel", + "printedName": "setLevel(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)setLevel:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setLevel:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "addBreadcrumb", + "printedName": "addBreadcrumb(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)addBreadcrumb:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "addBreadcrumb:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "add", + "printedName": "add(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)add:", + "moduleName": "Sentry", + "deprecated": true, + "isOpen": true, + "objc_name": "add:", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "clearBreadcrumbs", + "printedName": "clearBreadcrumbs()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)clearBreadcrumbs", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "clearBreadcrumbs", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setContext", + "printedName": "setContext(value:key:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)setContextValue:forKey:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setContextValue:forKey:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "removeContext", + "printedName": "removeContext(key:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)removeContextForKey:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "removeContextForKey:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "addAttachment", + "printedName": "addAttachment(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Attachment", + "printedName": "Sentry.Attachment", + "usr": "c:objc(cs)SentryAttachment" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)addAttachment:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "addAttachment:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "add", + "printedName": "add(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Attachment", + "printedName": "Sentry.Attachment", + "usr": "c:objc(cs)SentryAttachment" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)includeAttachment:", + "moduleName": "Sentry", + "deprecated": true, + "isOpen": true, + "objc_name": "includeAttachment:", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "clearAttachments", + "printedName": "clearAttachments()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)clearAttachments", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "clearAttachments", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "clear", + "printedName": "clear()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryScope(im)clear", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "clear", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryScope", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryScope", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryANRType", + "printedName": "SentryANRType", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryANRType?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryANRType", + "printedName": "Sentry.SentryANRType", + "usr": "c:@M@Sentry@E@SentryANRType" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:So13SentryANRTypeV8rawValueABSgSi_tcfc", + "mangledName": "$sSo13SentryANRTypeV8rawValueABSgSi_tcfc", + "moduleName": "Sentry", + "implicit": true, + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:So13SentryANRTypeV8rawValueSivp", + "mangledName": "$sSo13SentryANRTypeV8rawValueSivp", + "moduleName": "Sentry", + "implicit": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:So13SentryANRTypeV8rawValueSivg", + "mangledName": "$sSo13SentryANRTypeV8rawValueSivg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:So13SentryANRTypeV8RawValuea", + "mangledName": "$sSo13SentryANRTypeV8RawValuea", + "moduleName": "Sentry", + "implicit": true + }, + { + "kind": "Var", + "name": "fatalFullyBlocking", + "printedName": "fatalFullyBlocking", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryANRType.Type) -> Sentry.SentryANRType", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryANRType", + "printedName": "Sentry.SentryANRType", + "usr": "c:@M@Sentry@E@SentryANRType" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryANRType.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryANRType", + "printedName": "Sentry.SentryANRType", + "usr": "c:@M@Sentry@E@SentryANRType" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryANRType@SentryANRTypeFatalFullyBlocking", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "fatalNonFullyBlocking", + "printedName": "fatalNonFullyBlocking", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryANRType.Type) -> Sentry.SentryANRType", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryANRType", + "printedName": "Sentry.SentryANRType", + "usr": "c:@M@Sentry@E@SentryANRType" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryANRType.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryANRType", + "printedName": "Sentry.SentryANRType", + "usr": "c:@M@Sentry@E@SentryANRType" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryANRType@SentryANRTypeFatalNonFullyBlocking", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "fullyBlocking", + "printedName": "fullyBlocking", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryANRType.Type) -> Sentry.SentryANRType", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryANRType", + "printedName": "Sentry.SentryANRType", + "usr": "c:@M@Sentry@E@SentryANRType" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryANRType.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryANRType", + "printedName": "Sentry.SentryANRType", + "usr": "c:@M@Sentry@E@SentryANRType" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryANRType@SentryANRTypeFullyBlocking", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "nonFullyBlocking", + "printedName": "nonFullyBlocking", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryANRType.Type) -> Sentry.SentryANRType", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryANRType", + "printedName": "Sentry.SentryANRType", + "usr": "c:@M@Sentry@E@SentryANRType" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryANRType.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryANRType", + "printedName": "Sentry.SentryANRType", + "usr": "c:@M@Sentry@E@SentryANRType" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryANRType@SentryANRTypeNonFullyBlocking", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "unknown", + "printedName": "unknown", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryANRType.Type) -> Sentry.SentryANRType", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryANRType", + "printedName": "Sentry.SentryANRType", + "usr": "c:@M@Sentry@E@SentryANRType" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryANRType.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryANRType", + "printedName": "Sentry.SentryANRType", + "usr": "c:@M@Sentry@E@SentryANRType" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryANRType@SentryANRTypeUnknown", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentryANRType", + "moduleName": "Sentry", + "objc_name": "SentryANRType", + "declAttributes": [ + "SynthesizedProtocol", + "ObjC", + "SynthesizedProtocol", + "Sendable", + "Dynamic" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryANRType.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + }, + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + } + ] + }, + { + "kind": "TypeAlias", + "name": "SentryBeforeBreadcrumbCallback", + "printedName": "SentryBeforeBreadcrumbCallback", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Breadcrumb) -> Sentry.Breadcrumb?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Breadcrumb?", + "children": [ + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryBeforeBreadcrumbCallback", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "SentryBeforeCaptureScreenshotCallback", + "printedName": "SentryBeforeCaptureScreenshotCallback", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Bool", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryBeforeCaptureScreenshotCallback", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "SentryBeforeCaptureViewHierarchyCallback", + "printedName": "SentryBeforeCaptureViewHierarchyCallback", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Bool", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryBeforeCaptureViewHierarchyCallback", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "SentryBeforeSendEventCallback", + "printedName": "SentryBeforeSendEventCallback", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Sentry.Event?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Event?", + "children": [ + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryBeforeSendEventCallback", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "SentryBeforeSendLogCallback", + "printedName": "SentryBeforeSendLogCallback", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog) -> Sentry.SentryLog?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryLog?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentryLog", + "printedName": "Sentry.SentryLog", + "usr": "c:@M@Sentry@objc(cs)SentryLog" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryBeforeSendLogCallback", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "SentryBeforeSendSpanCallback", + "printedName": "SentryBeforeSendSpanCallback", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(any Sentry.Span) -> (any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryBeforeSendSpanCallback", + "moduleName": "Sentry" + }, + { + "kind": "TypeDecl", + "name": "SentryClient", + "printedName": "SentryClient", + "children": [ + { + "kind": "Var", + "name": "isEnabled", + "printedName": "isEnabled", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryClient(py)isEnabled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "isEnabled", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryClient(im)isEnabled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "isEnabled", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "options", + "printedName": "options", + "children": [ + { + "kind": "TypeNominal", + "name": "Options", + "printedName": "Sentry.Options", + "usr": "c:objc(cs)SentryOptions" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryClient(py)options", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "options", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Options", + "printedName": "Sentry.Options", + "usr": "c:objc(cs)SentryOptions" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryClient(im)options", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "options", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Options", + "printedName": "Sentry.Options", + "usr": "c:objc(cs)SentryOptions" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryClient(im)setOptions:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setOptions:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(options:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryClient?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryClient", + "printedName": "Sentry.SentryClient", + "usr": "c:objc(cs)SentryClient" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Options", + "printedName": "Sentry.Options", + "usr": "c:objc(cs)SentryOptions" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryClient(im)initWithOptions:", + "moduleName": "Sentry", + "objc_name": "initWithOptions:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(event:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryClient(im)captureEvent:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureEvent:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(event:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryClient(im)captureEvent:withScope:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureEvent:withScope:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(error:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryClient(im)captureError:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureError:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(error:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryClient(im)captureError:withScope:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureError:withScope:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(exception:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "NSException", + "printedName": "Foundation.NSException", + "usr": "c:objc(cs)NSException" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryClient(im)captureException:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureException:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(exception:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "NSException", + "printedName": "Foundation.NSException", + "usr": "c:objc(cs)NSException" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryClient(im)captureException:withScope:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureException:withScope:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(message:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryClient(im)captureMessage:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureMessage:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(message:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryClient(im)captureMessage:withScope:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureMessage:withScope:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(feedback:scope:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryFeedback", + "printedName": "Sentry.SentryFeedback", + "usr": "c:@M@Sentry@objc(cs)SentryFeedback" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryClient(im)captureFeedback:withScope:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureFeedback:withScope:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "flush", + "printedName": "flush(timeout:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNameAlias", + "name": "TimeInterval", + "printedName": "Foundation.TimeInterval", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryClient(im)flush:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "flush:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "close", + "printedName": "close()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryClient(im)close", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "close", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryClient", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryClient", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryDsn", + "printedName": "SentryDsn", + "children": [ + { + "kind": "Var", + "name": "url", + "printedName": "url", + "children": [ + { + "kind": "TypeNominal", + "name": "URL", + "printedName": "Foundation.URL", + "usr": "s:10Foundation3URLV" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryDsn(py)url", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "url", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "URL", + "printedName": "Foundation.URL", + "usr": "s:10Foundation3URLV" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryDsn(im)url", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "url", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(string:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryDsn", + "printedName": "Sentry.SentryDsn", + "usr": "c:objc(cs)SentryDsn" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryDsn(im)initWithString:didFailWithError:", + "moduleName": "Sentry", + "objc_name": "initWithString:didFailWithError:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "throwing": true, + "init_kind": "Designated" + }, + { + "kind": "Function", + "name": "getHash", + "printedName": "getHash()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryDsn(im)getHash", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "getHash", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "getEnvelopeEndpoint", + "printedName": "getEnvelopeEndpoint()", + "children": [ + { + "kind": "TypeNominal", + "name": "URL", + "printedName": "Foundation.URL", + "usr": "s:10Foundation3URLV" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryDsn(im)getEnvelopeEndpoint", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "getEnvelopeEndpoint", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryDsn", + "printedName": "Sentry.SentryDsn", + "usr": "c:objc(cs)SentryDsn" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)NSObject(im)init", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryDsn", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryDsn", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryEnvelopeItemHeader", + "printedName": "SentryEnvelopeItemHeader", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(type:length:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryEnvelopeItemHeader", + "printedName": "Sentry.SentryEnvelopeItemHeader", + "usr": "c:objc(cs)SentryEnvelopeItemHeader" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(im)initWithType:length:", + "moduleName": "Sentry", + "objc_name": "initWithType:length:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(type:length:contentType:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryEnvelopeItemHeader", + "printedName": "Sentry.SentryEnvelopeItemHeader", + "usr": "c:objc(cs)SentryEnvelopeItemHeader" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(im)initWithType:length:contentType:", + "moduleName": "Sentry", + "objc_name": "initWithType:length:contentType:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Convenience" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(type:length:filenname:contentType:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryEnvelopeItemHeader", + "printedName": "Sentry.SentryEnvelopeItemHeader", + "usr": "c:objc(cs)SentryEnvelopeItemHeader" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(im)initWithType:length:filenname:contentType:", + "moduleName": "Sentry", + "objc_name": "initWithType:length:filenname:contentType:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Convenience" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(type:length:contentType:itemCount:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryEnvelopeItemHeader", + "printedName": "Sentry.SentryEnvelopeItemHeader", + "usr": "c:objc(cs)SentryEnvelopeItemHeader" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(im)initWithType:length:contentType:itemCount:", + "moduleName": "Sentry", + "objc_name": "initWithType:length:contentType:itemCount:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Convenience" + }, + { + "kind": "Var", + "name": "type", + "printedName": "type", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(py)type", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "type", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(im)type", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "type", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "length", + "printedName": "length", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(py)length", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "length", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(im)length", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "length", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "filename", + "printedName": "filename", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(py)filename", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "filename", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(im)filename", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "filename", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "contentType", + "printedName": "contentType", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(py)contentType", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "contentType", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(im)contentType", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "contentType", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "itemCount", + "printedName": "itemCount", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(py)itemCount", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "itemCount", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(im)itemCount", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "itemCount", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "platform", + "printedName": "platform", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(py)platform", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "platform", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(im)platform", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "platform", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryEnvelopeItemHeader(im)setPlatform:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setPlatform:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryEnvelopeItemHeader", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryEnvelopeItemHeader", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryError", + "printedName": "SentryError", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryError?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:So11SentryErrorV8rawValueABSgSi_tcfc", + "mangledName": "$sSo11SentryErrorV8rawValueABSgSi_tcfc", + "moduleName": "Sentry", + "implicit": true, + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:So11SentryErrorV8rawValueSivp", + "mangledName": "$sSo11SentryErrorV8rawValueSivp", + "moduleName": "Sentry", + "implicit": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:So11SentryErrorV8rawValueSivg", + "mangledName": "$sSo11SentryErrorV8rawValueSivg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:So11SentryErrorV8RawValuea", + "mangledName": "$sSo11SentryErrorV8RawValuea", + "moduleName": "Sentry", + "implicit": true + }, + { + "kind": "Var", + "name": "unknownError", + "printedName": "unknownError", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryError.Type) -> Sentry.SentryError", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryError.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentryError@kSentryErrorUnknownError", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "invalidDsnError", + "printedName": "invalidDsnError", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryError.Type) -> Sentry.SentryError", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryError.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentryError@kSentryErrorInvalidDsnError", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "sentryCrashNotInstalledError", + "printedName": "sentryCrashNotInstalledError", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryError.Type) -> Sentry.SentryError", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryError.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentryError@kSentryErrorSentryCrashNotInstalledError", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "invalidCrashReportError", + "printedName": "invalidCrashReportError", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryError.Type) -> Sentry.SentryError", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryError.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentryError@kSentryErrorInvalidCrashReportError", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "compressionError", + "printedName": "compressionError", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryError.Type) -> Sentry.SentryError", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryError.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentryError@kSentryErrorCompressionError", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "jsonConversionError", + "printedName": "jsonConversionError", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryError.Type) -> Sentry.SentryError", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryError.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentryError@kSentryErrorJsonConversionError", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "couldNotFindDirectory", + "printedName": "couldNotFindDirectory", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryError.Type) -> Sentry.SentryError", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryError.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentryError@kSentryErrorCouldNotFindDirectory", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "requestError", + "printedName": "requestError", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryError.Type) -> Sentry.SentryError", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryError.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentryError@kSentryErrorRequestError", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "eventNotSent", + "printedName": "eventNotSent", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryError.Type) -> Sentry.SentryError", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryError.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentryError@kSentryErrorEventNotSent", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "fileIO", + "printedName": "fileIO", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryError.Type) -> Sentry.SentryError", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryError.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentryError@kSentryErrorFileIO", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "kernel", + "printedName": "kernel", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryError.Type) -> Sentry.SentryError", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryError.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryError", + "printedName": "Sentry.SentryError", + "usr": "c:@E@SentryError" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentryError@kSentryErrorKernel", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + } + ], + "declKind": "Enum", + "usr": "c:@E@SentryError", + "moduleName": "Sentry", + "objc_name": "SentryError", + "declAttributes": [ + "SynthesizedProtocol", + "ObjC", + "SynthesizedProtocol", + "Sendable", + "Dynamic" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryError.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + }, + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + } + ] + }, + { + "kind": "Var", + "name": "SentryErrorDomain", + "printedName": "SentryErrorDomain", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@SentryErrorDomain", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "TypeDecl", + "name": "SentryFeedbackAPI", + "printedName": "SentryFeedbackAPI", + "children": [ + { + "kind": "Function", + "name": "showWidget", + "printedName": "showWidget()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryFeedbackAPI(im)showWidget", + "moduleName": "Sentry", + "isOpen": true, + "intro_iOS": "13.0", + "objc_name": "showWidget", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "hideWidget", + "printedName": "hideWidget()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryFeedbackAPI(im)hideWidget", + "moduleName": "Sentry", + "isOpen": true, + "intro_iOS": "13.0", + "objc_name": "hideWidget", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackAPI", + "printedName": "Sentry.SentryFeedbackAPI", + "usr": "c:objc(cs)SentryFeedbackAPI" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)NSObject(im)init", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryFeedbackAPI", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryFeedbackAPI", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryFeedbackSource", + "printedName": "SentryFeedbackSource", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryFeedbackSource?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedbackSource", + "usr": "c:@M@Sentry@E@SentryFeedbackSource" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:So20SentryFeedbackSourceV8rawValueABSgSi_tcfc", + "mangledName": "$sSo20SentryFeedbackSourceV8rawValueABSgSi_tcfc", + "moduleName": "Sentry", + "implicit": true, + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:So20SentryFeedbackSourceV8rawValueSivp", + "mangledName": "$sSo20SentryFeedbackSourceV8rawValueSivp", + "moduleName": "Sentry", + "implicit": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:So20SentryFeedbackSourceV8rawValueSivg", + "mangledName": "$sSo20SentryFeedbackSourceV8rawValueSivg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:So20SentryFeedbackSourceV8RawValuea", + "mangledName": "$sSo20SentryFeedbackSourceV8RawValuea", + "moduleName": "Sentry", + "implicit": true + }, + { + "kind": "Var", + "name": "widget", + "printedName": "widget", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryFeedbackSource.Type) -> Sentry.SentryFeedbackSource", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedbackSource", + "usr": "c:@M@Sentry@E@SentryFeedbackSource" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryFeedbackSource.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedbackSource", + "usr": "c:@M@Sentry@E@SentryFeedbackSource" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryFeedbackSource@SentryFeedbackSourceWidget", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "custom", + "printedName": "custom", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryFeedbackSource.Type) -> Sentry.SentryFeedbackSource", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedbackSource", + "usr": "c:@M@Sentry@E@SentryFeedbackSource" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryFeedbackSource.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedbackSource", + "usr": "c:@M@Sentry@E@SentryFeedbackSource" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryFeedbackSource@SentryFeedbackSourceCustom", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentryFeedbackSource", + "moduleName": "Sentry", + "objc_name": "SentryFeedbackSource", + "declAttributes": [ + "SynthesizedProtocol", + "ObjC", + "SynthesizedProtocol", + "Sendable", + "Dynamic" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryFeedbackSource.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + }, + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryHub", + "printedName": "SentryHub", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(client:andScope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryHub", + "printedName": "Sentry.SentryHub", + "usr": "c:objc(cs)SentryHub" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryClient?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryClient", + "printedName": "Sentry.SentryClient", + "usr": "c:objc(cs)SentryClient" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Scope?", + "children": [ + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryHub(im)initWithClient:andScope:", + "moduleName": "Sentry", + "objc_name": "initWithClient:andScope:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Function", + "name": "startSession", + "printedName": "startSession()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)startSession", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "startSession", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "endSession", + "printedName": "endSession()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)endSession", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "endSession", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "endSession", + "printedName": "endSession(withTimestamp:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)endSessionWithTimestamp:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "endSessionWithTimestamp:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(event:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)captureEvent:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureEvent:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(event:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)captureEvent:withScope:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureEvent:withScope:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(name:operation:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)startTransactionWithName:operation:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "startTransactionWithName:operation:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(name:operation:bindToScope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)startTransactionWithName:operation:bindToScope:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "startTransactionWithName:operation:bindToScope:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(transactionContext:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)startTransactionWithContext:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "startTransactionWithContext:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(transactionContext:bindToScope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)startTransactionWithContext:bindToScope:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "startTransactionWithContext:bindToScope:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(transactionContext:bindToScope:customSamplingContext:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)startTransactionWithContext:bindToScope:customSamplingContext:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "startTransactionWithContext:bindToScope:customSamplingContext:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(transactionContext:customSamplingContext:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)startTransactionWithContext:customSamplingContext:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "startTransactionWithContext:customSamplingContext:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(error:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)captureError:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureError:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(error:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)captureError:withScope:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureError:withScope:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(exception:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "NSException", + "printedName": "Foundation.NSException", + "usr": "c:objc(cs)NSException" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)captureException:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureException:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(exception:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "NSException", + "printedName": "Foundation.NSException", + "usr": "c:objc(cs)NSException" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)captureException:withScope:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureException:withScope:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(message:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)captureMessage:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureMessage:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(message:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)captureMessage:withScope:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureMessage:withScope:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryFeedback", + "printedName": "Sentry.SentryFeedback", + "usr": "c:@M@Sentry@objc(cs)SentryFeedback" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)captureFeedback:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "captureFeedback:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "configureScope", + "printedName": "configureScope(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)configureScope:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "configureScope:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "add", + "printedName": "add(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)addBreadcrumb:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "addBreadcrumb:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "getClient", + "printedName": "getClient()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryClient?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryClient", + "printedName": "Sentry.SentryClient", + "usr": "c:objc(cs)SentryClient" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)getClient", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "getClient", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Var", + "name": "scope", + "printedName": "scope", + "children": [ + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryHub(py)scope", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "scope", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryHub(im)scope", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "scope", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Function", + "name": "bindClient", + "printedName": "bindClient(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryClient?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryClient", + "printedName": "Sentry.SentryClient", + "usr": "c:objc(cs)SentryClient" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)bindClient:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "bindClient:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "hasIntegration", + "printedName": "hasIntegration(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)hasIntegration:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "hasIntegration:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "isIntegrationInstalled", + "printedName": "isIntegrationInstalled(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)isIntegrationInstalled:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "isIntegrationInstalled:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setUser", + "printedName": "setUser(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.User?", + "children": [ + { + "kind": "TypeNominal", + "name": "User", + "printedName": "Sentry.User", + "usr": "c:objc(cs)SentryUser" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)setUser:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setUser:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "reportFullyDisplayed", + "printedName": "reportFullyDisplayed()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)reportFullyDisplayed", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "reportFullyDisplayed", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "flush", + "printedName": "flush(timeout:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNameAlias", + "name": "TimeInterval", + "printedName": "Foundation.TimeInterval", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)flush:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "flush:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "close", + "printedName": "close()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryHub(im)close", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "close", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryHub", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryHub", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryIntegrationProtocol", + "printedName": "SentryIntegrationProtocol", + "children": [ + { + "kind": "Function", + "name": "install", + "printedName": "install(with:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Options", + "printedName": "Sentry.Options", + "usr": "c:objc(cs)SentryOptions" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentryIntegrationProtocol(im)installWithOptions:", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "installWithOptions:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "uninstall", + "printedName": "uninstall()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentryIntegrationProtocol(im)uninstall", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "uninstall", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Protocol", + "usr": "c:objc(pl)SentryIntegrationProtocol", + "moduleName": "Sentry", + "genericSig": "", + "objc_name": "SentryIntegrationProtocol", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + } + ] + }, + { + "kind": "Var", + "name": "SentryLevelNames", + "printedName": "SentryLevelNames", + "children": [ + { + "kind": "TypeNominal", + "name": "Tuple", + "printedName": "(Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString)", + "children": [ + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + } + ] + } + ], + "declKind": "Var", + "usr": "c:@SentryLevelNames", + "moduleName": "Sentry", + "deprecated": true, + "declAttributes": [ + "Available" + ], + "isLet": true, + "hasStorage": true + }, + { + "kind": "TypeDecl", + "name": "SentryMessage", + "printedName": "SentryMessage", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(formatted:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryMessage", + "printedName": "Sentry.SentryMessage", + "usr": "c:objc(cs)SentryMessage" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryMessage(im)initWithFormatted:", + "moduleName": "Sentry", + "objc_name": "initWithFormatted:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "formatted", + "printedName": "formatted", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMessage(py)formatted", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "formatted", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMessage(im)formatted", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "formatted", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "message", + "printedName": "message", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMessage(py)message", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "message", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMessage(im)message", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "message", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMessage(im)setMessage:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setMessage:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "params", + "printedName": "params", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryMessage(py)params", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "params", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMessage(im)params", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "params", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sa" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryMessage(im)setParams:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setParams:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryMessage", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryMessage", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryNSError", + "printedName": "SentryNSError", + "children": [ + { + "kind": "Var", + "name": "domain", + "printedName": "domain", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryNSError(py)domain", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "domain", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryNSError(im)domain", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "domain", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryNSError(im)setDomain:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setDomain:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "code", + "printedName": "code", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryNSError(py)code", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "code", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryNSError(im)code", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "code", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryNSError(im)setCode:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setCode:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(domain:code:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryNSError", + "printedName": "Sentry.SentryNSError", + "usr": "c:objc(cs)SentryNSError" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryNSError(im)initWithDomain:code:", + "moduleName": "Sentry", + "objc_name": "initWithDomain:code:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryNSError", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryNSError", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeAlias", + "name": "SentryOnCrashedLastRunCallback", + "printedName": "SentryOnCrashedLastRunCallback", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Event) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryOnCrashedLastRunCallback", + "moduleName": "Sentry" + }, + { + "kind": "TypeDecl", + "name": "SentryProfileLifecycle", + "printedName": "SentryProfileLifecycle", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryProfileLifecycle?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileLifecycle", + "usr": "c:@M@Sentry@E@SentryProfileLifecycle" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:So22SentryProfileLifecycleV8rawValueABSgSi_tcfc", + "mangledName": "$sSo22SentryProfileLifecycleV8rawValueABSgSi_tcfc", + "moduleName": "Sentry", + "implicit": true, + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:So22SentryProfileLifecycleV8rawValueSivp", + "mangledName": "$sSo22SentryProfileLifecycleV8rawValueSivp", + "moduleName": "Sentry", + "implicit": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:So22SentryProfileLifecycleV8rawValueSivg", + "mangledName": "$sSo22SentryProfileLifecycleV8rawValueSivg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:So22SentryProfileLifecycleV8RawValuea", + "mangledName": "$sSo22SentryProfileLifecycleV8RawValuea", + "moduleName": "Sentry", + "implicit": true + }, + { + "kind": "Var", + "name": "manual", + "printedName": "manual", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryProfileLifecycle.Type) -> Sentry.SentryProfileLifecycle", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileLifecycle", + "usr": "c:@M@Sentry@E@SentryProfileLifecycle" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryProfileLifecycle.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileLifecycle", + "usr": "c:@M@Sentry@E@SentryProfileLifecycle" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryProfileLifecycle@SentryProfileLifecycleManual", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "trace", + "printedName": "trace", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryProfileLifecycle.Type) -> Sentry.SentryProfileLifecycle", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileLifecycle", + "usr": "c:@M@Sentry@E@SentryProfileLifecycle" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryProfileLifecycle.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileLifecycle", + "usr": "c:@M@Sentry@E@SentryProfileLifecycle" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryProfileLifecycle@SentryProfileLifecycleTrace", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentryProfileLifecycle", + "moduleName": "Sentry", + "objc_name": "SentryProfileLifecycle", + "declAttributes": [ + "SynthesizedProtocol", + "ObjC", + "SynthesizedProtocol", + "Sendable", + "Dynamic" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryProfileLifecycle.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + }, + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + } + ] + }, + { + "kind": "TypeAlias", + "name": "SentryProfilingConfigurationBlock", + "printedName": "SentryProfilingConfigurationBlock", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryProfileOptions) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryProfileOptions", + "printedName": "Sentry.SentryProfileOptions", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryProfilingConfigurationBlock", + "moduleName": "Sentry" + }, + { + "kind": "TypeDecl", + "name": "SentryReplayApi", + "printedName": "SentryReplayApi", + "children": [ + { + "kind": "Function", + "name": "maskView", + "printedName": "maskView(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "UIView", + "printedName": "UIKit.UIView", + "usr": "c:objc(cs)UIView" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryReplayApi(im)maskView:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "maskView:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "unmaskView", + "printedName": "unmaskView(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "UIView", + "printedName": "UIKit.UIView", + "usr": "c:objc(cs)UIView" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryReplayApi(im)unmaskView:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "unmaskView:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "pause", + "printedName": "pause()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryReplayApi(im)pause", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "pause", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "resume", + "printedName": "resume()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryReplayApi(im)resume", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "resume", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "start", + "printedName": "start()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryReplayApi(im)start", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "start", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "stop", + "printedName": "stop()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryReplayApi(im)stop", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "stop", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "showMaskPreview", + "printedName": "showMaskPreview()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryReplayApi(im)showMaskPreview", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "showMaskPreview", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "showMaskPreview", + "printedName": "showMaskPreview(_:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "CGFloat", + "printedName": "CoreGraphics.CGFloat", + "usr": "s:14CoreFoundation7CGFloatV" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryReplayApi(im)showMaskPreview:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "showMaskPreview:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "hideMaskPreview", + "printedName": "hideMaskPreview()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryReplayApi(im)hideMaskPreview", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "hideMaskPreview", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayApi", + "printedName": "Sentry.SentryReplayApi", + "usr": "c:objc(cs)SentryReplayApi" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)NSObject(im)init", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryReplayApi", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryReplayApi", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryReplayQuality", + "printedName": "SentryReplayQuality", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryReplayQuality?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayQuality", + "usr": "c:@M@Sentry@E@SentryReplayQuality" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:So19SentryReplayQualityV8rawValueABSgSi_tcfc", + "mangledName": "$sSo19SentryReplayQualityV8rawValueABSgSi_tcfc", + "moduleName": "Sentry", + "implicit": true, + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:So19SentryReplayQualityV8rawValueSivp", + "mangledName": "$sSo19SentryReplayQualityV8rawValueSivp", + "moduleName": "Sentry", + "implicit": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:So19SentryReplayQualityV8rawValueSivg", + "mangledName": "$sSo19SentryReplayQualityV8rawValueSivg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:So19SentryReplayQualityV8RawValuea", + "mangledName": "$sSo19SentryReplayQualityV8RawValuea", + "moduleName": "Sentry", + "implicit": true + }, + { + "kind": "Var", + "name": "low", + "printedName": "low", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryReplayQuality.Type) -> Sentry.SentryReplayQuality", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayQuality", + "usr": "c:@M@Sentry@E@SentryReplayQuality" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryReplayQuality.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayQuality", + "usr": "c:@M@Sentry@E@SentryReplayQuality" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryReplayQuality@SentryReplayQualityLow", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "medium", + "printedName": "medium", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryReplayQuality.Type) -> Sentry.SentryReplayQuality", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayQuality", + "usr": "c:@M@Sentry@E@SentryReplayQuality" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryReplayQuality.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayQuality", + "usr": "c:@M@Sentry@E@SentryReplayQuality" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryReplayQuality@SentryReplayQualityMedium", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "high", + "printedName": "high", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryReplayQuality.Type) -> Sentry.SentryReplayQuality", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayQuality", + "usr": "c:@M@Sentry@E@SentryReplayQuality" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryReplayQuality.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayQuality", + "usr": "c:@M@Sentry@E@SentryReplayQuality" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryReplayQuality@SentryReplayQualityHigh", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentryReplayQuality", + "moduleName": "Sentry", + "objc_name": "SentryReplayQuality", + "declAttributes": [ + "SynthesizedProtocol", + "ObjC", + "SynthesizedProtocol", + "Sendable", + "Dynamic" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryReplayQuality.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + }, + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryReplayType", + "printedName": "SentryReplayType", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryReplayType?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayType", + "printedName": "Sentry.SentryReplayType", + "usr": "c:@M@Sentry@E@SentryReplayType" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:So16SentryReplayTypeV8rawValueABSgSi_tcfc", + "mangledName": "$sSo16SentryReplayTypeV8rawValueABSgSi_tcfc", + "moduleName": "Sentry", + "implicit": true, + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:So16SentryReplayTypeV8rawValueSivp", + "mangledName": "$sSo16SentryReplayTypeV8rawValueSivp", + "moduleName": "Sentry", + "implicit": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:So16SentryReplayTypeV8rawValueSivg", + "mangledName": "$sSo16SentryReplayTypeV8rawValueSivg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:So16SentryReplayTypeV8RawValuea", + "mangledName": "$sSo16SentryReplayTypeV8RawValuea", + "moduleName": "Sentry", + "implicit": true + }, + { + "kind": "Var", + "name": "session", + "printedName": "session", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryReplayType.Type) -> Sentry.SentryReplayType", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayType", + "printedName": "Sentry.SentryReplayType", + "usr": "c:@M@Sentry@E@SentryReplayType" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryReplayType.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayType", + "printedName": "Sentry.SentryReplayType", + "usr": "c:@M@Sentry@E@SentryReplayType" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryReplayType@SentryReplayTypeSession", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "buffer", + "printedName": "buffer", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryReplayType.Type) -> Sentry.SentryReplayType", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayType", + "printedName": "Sentry.SentryReplayType", + "usr": "c:@M@Sentry@E@SentryReplayType" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryReplayType.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayType", + "printedName": "Sentry.SentryReplayType", + "usr": "c:@M@Sentry@E@SentryReplayType" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryReplayType@SentryReplayTypeBuffer", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentryReplayType", + "moduleName": "Sentry", + "objc_name": "SentryReplayType", + "declAttributes": [ + "SynthesizedProtocol", + "ObjC", + "SynthesizedProtocol", + "Sendable", + "Dynamic" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryReplayType.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + }, + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryRequest", + "printedName": "SentryRequest", + "children": [ + { + "kind": "Var", + "name": "bodySize", + "printedName": "bodySize", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryRequest(py)bodySize", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "bodySize", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)bodySize", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "bodySize", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)setBodySize:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setBodySize:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "cookies", + "printedName": "cookies", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryRequest(py)cookies", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "cookies", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)cookies", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "cookies", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)setCookies:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setCookies:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "headers", + "printedName": "headers", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryRequest(py)headers", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "headers", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)headers", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "headers", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Swift.String]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)setHeaders:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setHeaders:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "fragment", + "printedName": "fragment", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryRequest(py)fragment", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "fragment", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)fragment", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "fragment", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)setFragment:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setFragment:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "method", + "printedName": "method", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryRequest(py)method", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "method", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)method", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "method", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)setMethod:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setMethod:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "queryString", + "printedName": "queryString", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryRequest(py)queryString", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "queryString", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)queryString", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "queryString", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)setQueryString:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setQueryString:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "url", + "printedName": "url", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryRequest(py)url", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "url", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)url", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "url", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryRequest(im)setUrl:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setUrl:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRequest", + "printedName": "Sentry.SentryRequest", + "usr": "c:objc(cs)SentryRequest" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryRequest(im)init", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryRequest", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryRequest", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeAlias", + "name": "SentryRequestFinished", + "printedName": "SentryRequestFinished", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "((any Swift.Error)?) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Swift.Error)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "usr": "s:Sq" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryRequestFinished", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "SentryRequestOperationFinished", + "printedName": "SentryRequestOperationFinished", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Foundation.HTTPURLResponse?, (any Swift.Error)?) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Tuple", + "printedName": "(Foundation.HTTPURLResponse?, (any Swift.Error)?)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.HTTPURLResponse?", + "children": [ + { + "kind": "TypeNominal", + "name": "HTTPURLResponse", + "printedName": "Foundation.HTTPURLResponse", + "usr": "c:objc(cs)NSHTTPURLResponse" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Swift.Error)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "usr": "s:Sq" + } + ] + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryRequestOperationFinished", + "moduleName": "Sentry" + }, + { + "kind": "TypeDecl", + "name": "SentrySampleDecision", + "printedName": "SentrySampleDecision", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentrySampleDecision?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Constructor", + "usr": "s:So20SentrySampleDecisionV8rawValueABSgSu_tcfc", + "mangledName": "$sSo20SentrySampleDecisionV8rawValueABSgSu_tcfc", + "moduleName": "Sentry", + "implicit": true, + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Var", + "usr": "s:So20SentrySampleDecisionV8rawValueSuvp", + "mangledName": "$sSo20SentrySampleDecisionV8rawValueSuvp", + "moduleName": "Sentry", + "implicit": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Accessor", + "usr": "s:So20SentrySampleDecisionV8rawValueSuvg", + "mangledName": "$sSo20SentrySampleDecisionV8rawValueSuvg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "TypeAlias", + "usr": "s:So20SentrySampleDecisionV8RawValuea", + "mangledName": "$sSo20SentrySampleDecisionV8RawValuea", + "moduleName": "Sentry", + "implicit": true + }, + { + "kind": "Var", + "name": "undecided", + "printedName": "undecided", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySampleDecision.Type) -> Sentry.SentrySampleDecision", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySampleDecision.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySampleDecision@kSentrySampleDecisionUndecided", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "yes", + "printedName": "yes", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySampleDecision.Type) -> Sentry.SentrySampleDecision", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySampleDecision.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySampleDecision@kSentrySampleDecisionYes", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "no", + "printedName": "no", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySampleDecision.Type) -> Sentry.SentrySampleDecision", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySampleDecision.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySampleDecision@kSentrySampleDecisionNo", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + } + ], + "declKind": "Enum", + "usr": "c:@E@SentrySampleDecision", + "moduleName": "Sentry", + "objc_name": "SentrySampleDecision", + "declAttributes": [ + "SynthesizedProtocol", + "ObjC", + "SynthesizedProtocol", + "Sendable", + "Dynamic" + ], + "enumRawTypeName": "UInt", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentrySampleDecision.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + }, + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentrySerializable", + "printedName": "SentrySerializable", + "children": [ + { + "kind": "Function", + "name": "serialize", + "printedName": "serialize()", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySerializable(im)serialize", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "serialize", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Protocol", + "usr": "c:objc(pl)SentrySerializable", + "moduleName": "Sentry", + "genericSig": "", + "objc_name": "SentrySerializable", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentrySessionStatus", + "printedName": "SentrySessionStatus", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentrySessionStatus?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Constructor", + "usr": "s:So19SentrySessionStatusV8rawValueABSgSu_tcfc", + "mangledName": "$sSo19SentrySessionStatusV8rawValueABSgSu_tcfc", + "moduleName": "Sentry", + "implicit": true, + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Var", + "usr": "s:So19SentrySessionStatusV8rawValueSuvp", + "mangledName": "$sSo19SentrySessionStatusV8rawValueSuvp", + "moduleName": "Sentry", + "implicit": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Accessor", + "usr": "s:So19SentrySessionStatusV8rawValueSuvg", + "mangledName": "$sSo19SentrySessionStatusV8rawValueSuvg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "TypeAlias", + "usr": "s:So19SentrySessionStatusV8RawValuea", + "mangledName": "$sSo19SentrySessionStatusV8RawValuea", + "moduleName": "Sentry", + "implicit": true + }, + { + "kind": "Var", + "name": "ok", + "printedName": "ok", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySessionStatus.Type) -> Sentry.SentrySessionStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySessionStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentrySessionStatus@SentrySessionStatusOk", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "exited", + "printedName": "exited", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySessionStatus.Type) -> Sentry.SentrySessionStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySessionStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentrySessionStatus@SentrySessionStatusExited", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "crashed", + "printedName": "crashed", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySessionStatus.Type) -> Sentry.SentrySessionStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySessionStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentrySessionStatus@SentrySessionStatusCrashed", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "abnormal", + "printedName": "abnormal", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySessionStatus.Type) -> Sentry.SentrySessionStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySessionStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySessionStatus", + "printedName": "Sentry.SentrySessionStatus", + "usr": "c:@M@Sentry@E@SentrySessionStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentrySessionStatus@SentrySessionStatusAbnormal", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentrySessionStatus", + "moduleName": "Sentry", + "objc_name": "SentrySessionStatus", + "declAttributes": [ + "SynthesizedProtocol", + "ObjC", + "SynthesizedProtocol", + "Sendable", + "Dynamic" + ], + "enumRawTypeName": "UInt", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentrySessionStatus.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + }, + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + } + ] + }, + { + "kind": "TypeAlias", + "name": "SentryShouldQueueEvent", + "printedName": "SentryShouldQueueEvent", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Foundation.HTTPURLResponse?, (any Swift.Error)?) -> Swift.Bool", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Tuple", + "printedName": "(Foundation.HTTPURLResponse?, (any Swift.Error)?)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.HTTPURLResponse?", + "children": [ + { + "kind": "TypeNominal", + "name": "HTTPURLResponse", + "printedName": "Foundation.HTTPURLResponse", + "usr": "c:objc(cs)NSHTTPURLResponse" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Swift.Error)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "usr": "s:Sq" + } + ] + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryShouldQueueEvent", + "moduleName": "Sentry" + }, + { + "kind": "TypeDecl", + "name": "SentrySpanStatus", + "printedName": "SentrySpanStatus", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentrySpanStatus?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Constructor", + "usr": "s:So16SentrySpanStatusV8rawValueABSgSu_tcfc", + "mangledName": "$sSo16SentrySpanStatusV8rawValueABSgSu_tcfc", + "moduleName": "Sentry", + "implicit": true, + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Var", + "usr": "s:So16SentrySpanStatusV8rawValueSuvp", + "mangledName": "$sSo16SentrySpanStatusV8rawValueSuvp", + "moduleName": "Sentry", + "implicit": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Accessor", + "usr": "s:So16SentrySpanStatusV8rawValueSuvg", + "mangledName": "$sSo16SentrySpanStatusV8rawValueSuvg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "TypeAlias", + "usr": "s:So16SentrySpanStatusV8RawValuea", + "mangledName": "$sSo16SentrySpanStatusV8RawValuea", + "moduleName": "Sentry", + "implicit": true + }, + { + "kind": "Var", + "name": "undefined", + "printedName": "undefined", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUndefined", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "ok", + "printedName": "ok", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusOk", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "deadlineExceeded", + "printedName": "deadlineExceeded", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusDeadlineExceeded", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "unauthenticated", + "printedName": "unauthenticated", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUnauthenticated", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "permissionDenied", + "printedName": "permissionDenied", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusPermissionDenied", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "notFound", + "printedName": "notFound", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusNotFound", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "resourceExhausted", + "printedName": "resourceExhausted", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusResourceExhausted", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "invalidArgument", + "printedName": "invalidArgument", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusInvalidArgument", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "unimplemented", + "printedName": "unimplemented", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUnimplemented", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "unavailable", + "printedName": "unavailable", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUnavailable", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "internalError", + "printedName": "internalError", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusInternalError", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "unknownError", + "printedName": "unknownError", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusUnknownError", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "cancelled", + "printedName": "cancelled", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusCancelled", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "alreadyExists", + "printedName": "alreadyExists", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusAlreadyExists", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "failedPrecondition", + "printedName": "failedPrecondition", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusFailedPrecondition", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "aborted", + "printedName": "aborted", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusAborted", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "outOfRange", + "printedName": "outOfRange", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusOutOfRange", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "dataLoss", + "printedName": "dataLoss", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentrySpanStatus.Type) -> Sentry.SentrySpanStatus", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentrySpanStatus.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@E@SentrySpanStatus@kSentrySpanStatusDataLoss", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + } + ], + "declKind": "Enum", + "usr": "c:@E@SentrySpanStatus", + "moduleName": "Sentry", + "objc_name": "SentrySpanStatus", + "declAttributes": [ + "SynthesizedProtocol", + "ObjC", + "SynthesizedProtocol", + "Sendable", + "Dynamic" + ], + "enumRawTypeName": "UInt", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentrySpanStatus.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + }, + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + } + ] + }, + { + "kind": "Var", + "name": "SentrySpanStatusNames", + "printedName": "SentrySpanStatusNames", + "children": [ + { + "kind": "TypeNominal", + "name": "Tuple", + "printedName": "(Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString, Foundation.NSString)", + "children": [ + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + }, + { + "kind": "TypeNominal", + "name": "NSString", + "printedName": "Foundation.NSString", + "usr": "c:objc(cs)NSString" + } + ] + } + ], + "declKind": "Var", + "usr": "c:@SentrySpanStatusNames", + "moduleName": "Sentry", + "deprecated": true, + "declAttributes": [ + "Available" + ], + "isLet": true, + "hasStorage": true + }, + { + "kind": "TypeDecl", + "name": "SentryStacktrace", + "printedName": "SentryStacktrace", + "children": [ + { + "kind": "Var", + "name": "frames", + "printedName": "frames", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.Frame]", + "children": [ + { + "kind": "TypeNominal", + "name": "Frame", + "printedName": "Sentry.Frame", + "usr": "c:objc(cs)SentryFrame" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryStacktrace(py)frames", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "frames", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.Frame]", + "children": [ + { + "kind": "TypeNominal", + "name": "Frame", + "printedName": "Sentry.Frame", + "usr": "c:objc(cs)SentryFrame" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryStacktrace(im)frames", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "frames", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.Frame]", + "children": [ + { + "kind": "TypeNominal", + "name": "Frame", + "printedName": "Sentry.Frame", + "usr": "c:objc(cs)SentryFrame" + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryStacktrace(im)setFrames:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setFrames:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "registers", + "printedName": "registers", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryStacktrace(py)registers", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "registers", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryStacktrace(im)registers", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "registers", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryStacktrace(im)setRegisters:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setRegisters:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "snapshot", + "printedName": "snapshot", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryStacktrace(py)snapshot", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "snapshot", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryStacktrace(im)snapshot", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "snapshot", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryStacktrace(im)setSnapshot:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSnapshot:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(frames:registers:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Sentry.Frame]", + "children": [ + { + "kind": "TypeNominal", + "name": "Frame", + "printedName": "Sentry.Frame", + "usr": "c:objc(cs)SentryFrame" + } + ], + "usr": "s:Sa" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryStacktrace(im)initWithFrames:registers:", + "moduleName": "Sentry", + "objc_name": "initWithFrames:registers:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Function", + "name": "fixDuplicateFrames", + "printedName": "fixDuplicateFrames()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryStacktrace(im)fixDuplicateFrames", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "fixDuplicateFrames", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryStacktrace", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryStacktrace", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryThread", + "printedName": "SentryThread", + "children": [ + { + "kind": "Var", + "name": "threadId", + "printedName": "threadId", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryThread(py)threadId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "threadId", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryThread(im)threadId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "threadId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryThread(im)setThreadId:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setThreadId:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "name", + "printedName": "name", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryThread(py)name", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "name", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryThread(im)name", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "name", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryThread(im)setName:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setName:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "stacktrace", + "printedName": "stacktrace", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryStacktrace?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryThread(py)stacktrace", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "stacktrace", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryStacktrace?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryThread(im)stacktrace", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "stacktrace", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryStacktrace?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryStacktrace", + "printedName": "Sentry.SentryStacktrace", + "usr": "c:objc(cs)SentryStacktrace" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryThread(im)setStacktrace:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setStacktrace:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "crashed", + "printedName": "crashed", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryThread(py)crashed", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "crashed", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryThread(im)crashed", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "crashed", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryThread(im)setCrashed:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setCrashed:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "current", + "printedName": "current", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryThread(py)current", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "current", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryThread(im)current", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "current", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryThread(im)setCurrent:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setCurrent:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "isMain", + "printedName": "isMain", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryThread(py)isMain", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "isMain", + "declAttributes": [ + "NSCopying", + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryThread(im)isMain", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "isMain", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryThread(im)setIsMain:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setIsMain:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(threadId:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryThread", + "printedName": "Sentry.SentryThread", + "usr": "c:objc(cs)SentryThread" + }, + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryThread(im)initWithThreadId:", + "moduleName": "Sentry", + "objc_name": "initWithThreadId:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryThread", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryThread", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeAlias", + "name": "SentryTracesSamplerCallback", + "printedName": "SentryTracesSamplerCallback", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SamplingContext) -> Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SamplingContext", + "printedName": "Sentry.SamplingContext", + "usr": "c:objc(cs)SentrySamplingContext" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryTracesSamplerCallback", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "SentryUserFeedbackConfigurationBlock", + "printedName": "SentryUserFeedbackConfigurationBlock", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackConfiguration", + "printedName": "Sentry.SentryUserFeedbackConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@SentryUserFeedbackConfigurationBlock", + "moduleName": "Sentry", + "intro_iOS": "13.0", + "declAttributes": [ + "Available" + ] + }, + { + "kind": "Var", + "name": "SentryVersionNumber", + "printedName": "SentryVersionNumber", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ], + "declKind": "Var", + "usr": "c:@SentryVersionNumber", + "moduleName": "Sentry", + "hasStorage": true + }, + { + "kind": "Var", + "name": "SentryVersionString", + "printedName": "SentryVersionString", + "children": [ + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "<>" + } + ], + "declKind": "Var", + "usr": "c:@SentryVersionString", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "TypeDecl", + "name": "Span", + "printedName": "Span", + "children": [ + { + "kind": "Var", + "name": "traceId", + "printedName": "traceId", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)traceId", + "moduleName": "Sentry", + "protocolReq": true, + "objc_name": "traceId", + "declAttributes": [ + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Var", + "name": "spanId", + "printedName": "spanId", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)spanId", + "moduleName": "Sentry", + "protocolReq": true, + "objc_name": "spanId", + "declAttributes": [ + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Var", + "name": "parentSpanId", + "printedName": "parentSpanId", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SpanId?", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)parentSpanId", + "moduleName": "Sentry", + "protocolReq": true, + "objc_name": "parentSpanId", + "declAttributes": [ + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Var", + "name": "sampled", + "printedName": "sampled", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)sampled", + "moduleName": "Sentry", + "protocolReq": true, + "objc_name": "sampled", + "declAttributes": [ + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Var", + "name": "operation", + "printedName": "operation", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)operation", + "moduleName": "Sentry", + "protocolReq": true, + "objc_name": "operation", + "declAttributes": [ + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Var", + "name": "origin", + "printedName": "origin", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)origin", + "moduleName": "Sentry", + "protocolReq": true, + "objc_name": "origin", + "declAttributes": [ + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Var", + "name": "spanDescription", + "printedName": "spanDescription", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)spanDescription", + "moduleName": "Sentry", + "protocolReq": true, + "objc_name": "spanDescription", + "declAttributes": [ + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Var", + "name": "status", + "printedName": "status", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)status", + "moduleName": "Sentry", + "protocolReq": true, + "objc_name": "status", + "declAttributes": [ + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Var", + "name": "timestamp", + "printedName": "timestamp", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Date?", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)timestamp", + "moduleName": "Sentry", + "protocolReq": true, + "intro_iOS": "8.0", + "objc_name": "timestamp", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Var", + "name": "startTimestamp", + "printedName": "startTimestamp", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Date?", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)startTimestamp", + "moduleName": "Sentry", + "protocolReq": true, + "intro_iOS": "8.0", + "objc_name": "startTimestamp", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Var", + "name": "data", + "printedName": "data", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)data", + "moduleName": "Sentry", + "protocolReq": true, + "objc_name": "data", + "declAttributes": [ + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Var", + "name": "tags", + "printedName": "tags", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Swift.String]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)tags", + "moduleName": "Sentry", + "protocolReq": true, + "objc_name": "tags", + "declAttributes": [ + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Var", + "name": "isFinished", + "printedName": "isFinished", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)isFinished", + "moduleName": "Sentry", + "protocolReq": true, + "objc_name": "isFinished", + "declAttributes": [ + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Var", + "name": "traceContext", + "printedName": "traceContext", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.TraceContext?", + "children": [ + { + "kind": "TypeNominal", + "name": "TraceContext", + "printedName": "Sentry.TraceContext", + "usr": "c:objc(cs)SentryTraceContext" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(pl)SentrySpan(py)traceContext", + "moduleName": "Sentry", + "protocolReq": true, + "objc_name": "traceContext", + "declAttributes": [ + "ObjC", + "Dynamic" + ] + }, + { + "kind": "Function", + "name": "startChild", + "printedName": "startChild(operation:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)startChildWithOperation:", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "startChildWithOperation:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startChild", + "printedName": "startChild(operation:description:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)startChildWithOperation:description:", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "startChildWithOperation:description:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setData", + "printedName": "setData(value:key:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Any?", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)setDataValue:forKey:", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "setDataValue:forKey:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "removeData", + "printedName": "removeData(key:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)removeDataForKey:", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "removeDataForKey:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setTag", + "printedName": "setTag(value:key:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)setTagValue:forKey:", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "setTagValue:forKey:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "removeTag", + "printedName": "removeTag(key:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)removeTagForKey:", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "removeTagForKey:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setMeasurement", + "printedName": "setMeasurement(name:value:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)setMeasurement:value:", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "setMeasurement:value:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "setMeasurement", + "printedName": "setMeasurement(name:value:unit:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + }, + { + "kind": "TypeNominal", + "name": "MeasurementUnit", + "printedName": "Sentry.MeasurementUnit", + "usr": "c:objc(cs)SentryMeasurementUnit" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)setMeasurement:value:unit:", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "setMeasurement:value:unit:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "finish", + "printedName": "finish()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)finish", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "finish", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "finish", + "printedName": "finish(status:)", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)finishWithStatus:", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "finishWithStatus:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "toTraceHeader", + "printedName": "toTraceHeader()", + "children": [ + { + "kind": "TypeNominal", + "name": "TraceHeader", + "printedName": "Sentry.TraceHeader", + "usr": "c:objc(cs)SentryTraceHeader" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)toTraceHeader", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "toTraceHeader", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "baggageHttpHeader", + "printedName": "baggageHttpHeader()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)baggageHttpHeader", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "baggageHttpHeader", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "serialize", + "printedName": "serialize()", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:objc(pl)SentrySpan(im)serialize", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "objc_name": "serialize", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "reqNewWitnessTableEntry": true, + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Protocol", + "usr": "c:objc(pl)SentrySpan", + "moduleName": "Sentry", + "genericSig": "", + "objc_name": "SentrySpan", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SpanContext", + "printedName": "SpanContext", + "children": [ + { + "kind": "Var", + "name": "traceId", + "printedName": "traceId", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentrySpanContext(py)traceId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "traceId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentrySpanContext(im)traceId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "traceId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "spanId", + "printedName": "spanId", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentrySpanContext(py)spanId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "spanId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentrySpanContext(im)spanId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "spanId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "parentSpanId", + "printedName": "parentSpanId", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SpanId?", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentrySpanContext(py)parentSpanId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "parentSpanId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SpanId?", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentrySpanContext(im)parentSpanId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "parentSpanId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "sampled", + "printedName": "sampled", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentrySpanContext(py)sampled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampled", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentrySpanContext(im)sampled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampled", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "operation", + "printedName": "operation", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentrySpanContext(py)operation", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "operation", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentrySpanContext(im)operation", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "operation", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "spanDescription", + "printedName": "spanDescription", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentrySpanContext(py)spanDescription", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "spanDescription", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentrySpanContext(im)spanDescription", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "spanDescription", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "origin", + "printedName": "origin", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentrySpanContext(py)origin", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "origin", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentrySpanContext(im)origin", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "origin", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentrySpanContext(im)setOrigin:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setOrigin:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(operation:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanContext", + "printedName": "Sentry.SpanContext", + "usr": "c:objc(cs)SentrySpanContext" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentrySpanContext(im)initWithOperation:", + "moduleName": "Sentry", + "objc_name": "initWithOperation:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(operation:sampled:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanContext", + "printedName": "Sentry.SpanContext", + "usr": "c:objc(cs)SentrySpanContext" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentrySpanContext(im)initWithOperation:sampled:", + "moduleName": "Sentry", + "objc_name": "initWithOperation:sampled:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(trace:spanId:parentId:operation:sampled:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanContext", + "printedName": "Sentry.SpanContext", + "usr": "c:objc(cs)SentrySpanContext" + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SpanId?", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentrySpanContext(im)initWithTraceId:spanId:parentId:operation:sampled:", + "moduleName": "Sentry", + "objc_name": "initWithTraceId:spanId:parentId:operation:sampled:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(trace:spanId:parentId:operation:spanDescription:sampled:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanContext", + "printedName": "Sentry.SpanContext", + "usr": "c:objc(cs)SentrySpanContext" + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SpanId?", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentrySpanContext(im)initWithTraceId:spanId:parentId:operation:spanDescription:sampled:", + "moduleName": "Sentry", + "objc_name": "initWithTraceId:spanId:parentId:operation:spanDescription:sampled:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentrySpanContext", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentrySpanContext", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SpanId", + "printedName": "SpanId", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentrySpanId(im)init", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(uuid:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + }, + { + "kind": "TypeNominal", + "name": "UUID", + "printedName": "Foundation.UUID", + "usr": "s:10Foundation4UUIDV" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentrySpanId(im)initWithUUID:", + "moduleName": "Sentry", + "objc_name": "initWithUUID:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(value:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentrySpanId(im)initWithValue:", + "moduleName": "Sentry", + "objc_name": "initWithValue:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "sentrySpanIdString", + "printedName": "sentrySpanIdString", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentrySpanId(py)sentrySpanIdString", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sentrySpanIdString", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentrySpanId(im)sentrySpanIdString", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sentrySpanIdString", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "empty", + "printedName": "empty", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentrySpanId(cpy)empty", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "empty", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentrySpanId(cm)empty", + "moduleName": "Sentry", + "static": true, + "isOpen": true, + "objc_name": "empty", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentrySpanId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentrySpanId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "NSCopying", + "printedName": "NSCopying", + "usr": "c:objc(pl)NSCopying" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "TraceContext", + "printedName": "TraceContext", + "children": [ + { + "kind": "Var", + "name": "traceId", + "printedName": "traceId", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTraceContext(py)traceId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "traceId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTraceContext(im)traceId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "traceId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "publicKey", + "printedName": "publicKey", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTraceContext(py)publicKey", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "publicKey", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTraceContext(im)publicKey", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "publicKey", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "releaseName", + "printedName": "releaseName", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTraceContext(py)releaseName", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "releaseName", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTraceContext(im)releaseName", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "releaseName", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "environment", + "printedName": "environment", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTraceContext(py)environment", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "environment", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTraceContext(im)environment", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "environment", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "transaction", + "printedName": "transaction", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTraceContext(py)transaction", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "transaction", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTraceContext(im)transaction", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "transaction", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "sampleRate", + "printedName": "sampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTraceContext(py)sampleRate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRate", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTraceContext(im)sampleRate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRate", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "sampleRand", + "printedName": "sampleRand", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTraceContext(py)sampleRand", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRand", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTraceContext(im)sampleRand", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRand", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "sampled", + "printedName": "sampled", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTraceContext(py)sampled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampled", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTraceContext(im)sampled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampled", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "replayId", + "printedName": "replayId", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTraceContext(py)replayId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "replayId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTraceContext(im)replayId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "replayId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(trace:publicKey:releaseName:environment:transaction:sampleRate:sampled:replayId:)", + "children": [ + { + "kind": "TypeNominal", + "name": "TraceContext", + "printedName": "Sentry.TraceContext", + "usr": "c:objc(cs)SentryTraceContext" + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryTraceContext(im)initWithTraceId:publicKey:releaseName:environment:transaction:sampleRate:sampled:replayId:", + "moduleName": "Sentry", + "objc_name": "initWithTraceId:publicKey:releaseName:environment:transaction:sampleRate:sampled:replayId:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(trace:publicKey:releaseName:environment:transaction:sampleRate:sampleRand:sampled:replayId:)", + "children": [ + { + "kind": "TypeNominal", + "name": "TraceContext", + "printedName": "Sentry.TraceContext", + "usr": "c:objc(cs)SentryTraceContext" + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryTraceContext(im)initWithTraceId:publicKey:releaseName:environment:transaction:sampleRate:sampleRand:sampled:replayId:", + "moduleName": "Sentry", + "objc_name": "initWithTraceId:publicKey:releaseName:environment:transaction:sampleRate:sampleRand:sampled:replayId:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(scope:options:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.TraceContext?", + "children": [ + { + "kind": "TypeNominal", + "name": "TraceContext", + "printedName": "Sentry.TraceContext", + "usr": "c:objc(cs)SentryTraceContext" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + }, + { + "kind": "TypeNominal", + "name": "Options", + "printedName": "Sentry.Options", + "usr": "c:objc(cs)SentryOptions" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryTraceContext(im)initWithScope:options:", + "moduleName": "Sentry", + "objc_name": "initWithScope:options:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(dict:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.TraceContext?", + "children": [ + { + "kind": "TypeNominal", + "name": "TraceContext", + "printedName": "Sentry.TraceContext", + "usr": "c:objc(cs)SentryTraceContext" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryTraceContext(im)initWithDict:", + "moduleName": "Sentry", + "objc_name": "initWithDict:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(trace:options:replayId:)", + "children": [ + { + "kind": "TypeNominal", + "name": "TraceContext", + "printedName": "Sentry.TraceContext", + "usr": "c:objc(cs)SentryTraceContext" + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Options", + "printedName": "Sentry.Options", + "usr": "c:objc(cs)SentryOptions" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryTraceContext(im)initWithTraceId:options:replayId:", + "moduleName": "Sentry", + "objc_name": "initWithTraceId:options:replayId:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Function", + "name": "toBaggage", + "printedName": "toBaggage()", + "children": [ + { + "kind": "TypeNominal", + "name": "Baggage", + "printedName": "Sentry.Baggage", + "usr": "c:objc(cs)SentryBaggage" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryTraceContext(im)toBaggage", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "toBaggage", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "TraceContext", + "printedName": "Sentry.TraceContext", + "usr": "c:objc(cs)SentryTraceContext" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)NSObject(im)init", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryTraceContext", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryTraceContext", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "TraceHeader", + "printedName": "TraceHeader", + "children": [ + { + "kind": "Var", + "name": "traceId", + "printedName": "traceId", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTraceHeader(py)traceId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "traceId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTraceHeader(im)traceId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "traceId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "spanId", + "printedName": "spanId", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTraceHeader(py)spanId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "spanId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTraceHeader(im)spanId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "spanId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "sampled", + "printedName": "sampled", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTraceHeader(py)sampled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampled", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTraceHeader(im)sampled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampled", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(trace:spanId:sampled:)", + "children": [ + { + "kind": "TypeNominal", + "name": "TraceHeader", + "printedName": "Sentry.TraceHeader", + "usr": "c:objc(cs)SentryTraceHeader" + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + }, + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryTraceHeader(im)initWithTraceId:spanId:sampled:", + "moduleName": "Sentry", + "objc_name": "initWithTraceId:spanId:sampled:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Function", + "name": "value", + "printedName": "value()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryTraceHeader(im)value", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "value", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryTraceHeader", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryTraceHeader", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "TransactionContext", + "printedName": "TransactionContext", + "children": [ + { + "kind": "Var", + "name": "name", + "printedName": "name", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTransactionContext(py)name", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "name", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)name", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "name", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "nameSource", + "printedName": "nameSource", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTransactionContext(py)nameSource", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "nameSource", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)nameSource", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "nameSource", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "sampleRate", + "printedName": "sampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTransactionContext(py)sampleRate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRate", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)sampleRate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRate", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)setSampleRate:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSampleRate:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "sampleRand", + "printedName": "sampleRand", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTransactionContext(py)sampleRand", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRand", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)sampleRand", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "sampleRand", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)setSampleRand:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setSampleRand:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "parentSampled", + "printedName": "parentSampled", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTransactionContext(py)parentSampled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "parentSampled", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)parentSampled", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "parentSampled", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)setParentSampled:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setParentSampled:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "parentSampleRate", + "printedName": "parentSampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTransactionContext(py)parentSampleRate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "parentSampleRate", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)parentSampleRate", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "parentSampleRate", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)setParentSampleRate:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setParentSampleRate:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "parentSampleRand", + "printedName": "parentSampleRand", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTransactionContext(py)parentSampleRand", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "parentSampleRand", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)parentSampleRand", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "parentSampleRand", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)setParentSampleRand:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setParentSampleRand:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "forNextAppLaunch", + "printedName": "forNextAppLaunch", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryTransactionContext(py)forNextAppLaunch", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "forNextAppLaunch", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)forNextAppLaunch", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "forNextAppLaunch", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryTransactionContext(im)setForNextAppLaunch:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setForNextAppLaunch:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(name:operation:)", + "children": [ + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryTransactionContext(im)initWithName:operation:", + "moduleName": "Sentry", + "objc_name": "initWithName:operation:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(name:operation:sampled:)", + "children": [ + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryTransactionContext(im)initWithName:operation:sampled:", + "moduleName": "Sentry", + "deprecated": true, + "objc_name": "initWithName:operation:sampled:", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(name:operation:sampled:sampleRate:sampleRand:)", + "children": [ + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryTransactionContext(im)initWithName:operation:sampled:sampleRate:sampleRand:", + "moduleName": "Sentry", + "objc_name": "initWithName:operation:sampled:sampleRate:sampleRand:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(name:operation:trace:spanId:parentSpanId:parentSampled:)", + "children": [ + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SpanId?", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryTransactionContext(im)initWithName:operation:traceId:spanId:parentSpanId:parentSampled:", + "moduleName": "Sentry", + "deprecated": true, + "objc_name": "initWithName:operation:traceId:spanId:parentSpanId:parentSampled:", + "declAttributes": [ + "Available", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(name:operation:trace:spanId:parentSpanId:parentSampled:parentSampleRate:parentSampleRand:)", + "children": [ + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SpanId?", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryTransactionContext(im)initWithName:operation:traceId:spanId:parentSpanId:parentSampled:parentSampleRate:parentSampleRand:", + "moduleName": "Sentry", + "objc_name": "initWithName:operation:traceId:spanId:parentSpanId:parentSampled:parentSampleRate:parentSampleRand:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(operation:)", + "children": [ + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentrySpanContext(im)initWithOperation:", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "initWithOperation:", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(operation:sampled:)", + "children": [ + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentrySpanContext(im)initWithOperation:sampled:", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "initWithOperation:sampled:", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(trace:spanId:parentId:operation:sampled:)", + "children": [ + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SpanId?", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentrySpanContext(im)initWithTraceId:spanId:parentId:operation:sampled:", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "initWithTraceId:spanId:parentId:operation:sampled:", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(trace:spanId:parentId:operation:spanDescription:sampled:)", + "children": [ + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SpanId?", + "children": [ + { + "kind": "TypeNominal", + "name": "SpanId", + "printedName": "Sentry.SpanId", + "usr": "c:objc(cs)SentrySpanId" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentrySampleDecision", + "printedName": "Sentry.SentrySampleDecision", + "usr": "c:@E@SentrySampleDecision" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentrySpanContext(im)initWithTraceId:spanId:parentId:operation:spanDescription:sampled:", + "moduleName": "Sentry", + "overriding": true, + "implicit": true, + "objc_name": "initWithTraceId:spanId:parentId:operation:spanDescription:sampled:", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryTransactionContext", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryTransactionContext", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)SentrySpanContext", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "Sentry.SpanContext", + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "User", + "printedName": "User", + "children": [ + { + "kind": "Var", + "name": "userId", + "printedName": "userId", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryUser(py)userId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "userId", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)userId", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "userId", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)setUserId:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setUserId:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "email", + "printedName": "email", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryUser(py)email", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "email", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)email", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "email", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)setEmail:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setEmail:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "username", + "printedName": "username", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryUser(py)username", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "username", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)username", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "username", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)setUsername:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setUsername:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "ipAddress", + "printedName": "ipAddress", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryUser(py)ipAddress", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "ipAddress", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)ipAddress", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "ipAddress", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)setIpAddress:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setIpAddress:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "name", + "printedName": "name", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryUser(py)name", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "name", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)name", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "name", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)setName:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setName:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "geo", + "printedName": "geo", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Geo?", + "children": [ + { + "kind": "TypeNominal", + "name": "Geo", + "printedName": "Sentry.Geo", + "usr": "c:objc(cs)SentryGeo" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryUser(py)geo", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "geo", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Geo?", + "children": [ + { + "kind": "TypeNominal", + "name": "Geo", + "printedName": "Sentry.Geo", + "usr": "c:objc(cs)SentryGeo" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)geo", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "geo", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.Geo?", + "children": [ + { + "kind": "TypeNominal", + "name": "Geo", + "printedName": "Sentry.Geo", + "usr": "c:objc(cs)SentryGeo" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)setGeo:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setGeo:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "data", + "printedName": "data", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:objc(cs)SentryUser(py)data", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "data", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)data", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "data", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:objc(cs)SentryUser(im)setData:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "setData:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(userId:)", + "children": [ + { + "kind": "TypeNominal", + "name": "User", + "printedName": "Sentry.User", + "usr": "c:objc(cs)SentryUser" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryUser(im)initWithUserId:", + "moduleName": "Sentry", + "objc_name": "initWithUserId:", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "User", + "printedName": "Sentry.User", + "usr": "c:objc(cs)SentryUser" + } + ], + "declKind": "Constructor", + "usr": "c:objc(cs)SentryUser(im)init", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "Override", + "ObjC", + "Dynamic" + ], + "init_kind": "Designated" + }, + { + "kind": "Function", + "name": "isEqual", + "printedName": "isEqual(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Any?", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryUser(im)isEqual:", + "moduleName": "Sentry", + "overriding": true, + "isOpen": true, + "objc_name": "isEqual:", + "declAttributes": [ + "DiscardableResult", + "Override", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "isEqual", + "printedName": "isEqual(to:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "User", + "printedName": "Sentry.User", + "usr": "c:objc(cs)SentryUser" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryUser(im)isEqualToUser:", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "isEqualToUser:", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "hash", + "printedName": "hash()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Func", + "usr": "c:objc(cs)SentryUser(im)hash", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "hash", + "declAttributes": [ + "DiscardableResult", + "ObjC", + "Dynamic" + ], + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)SentryUser", + "moduleName": "Sentry", + "isOpen": true, + "objc_name": "SentryUser", + "declAttributes": [ + "ObjC", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "NSCopying", + "printedName": "NSCopying", + "usr": "c:objc(pl)NSCopying" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeAlias", + "name": "__NSConstantString", + "printedName": "__NSConstantString", + "children": [ + { + "kind": "TypeNominal", + "name": "__NSConstantString_tag", + "printedName": "__ObjC.__NSConstantString_tag", + "usr": "c:@S@__NSConstantString_tag" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@__NSConstantString", + "moduleName": "__ObjC" + }, + { + "kind": "TypeAlias", + "name": "__builtin_ms_va_list", + "printedName": "__builtin_ms_va_list", + "children": [ + { + "kind": "TypeNominal", + "name": "UnsafeMutablePointer", + "printedName": "Swift.UnsafeMutablePointer", + "children": [ + { + "kind": "TypeNameAlias", + "name": "CChar", + "printedName": "Swift.CChar", + "children": [ + { + "kind": "TypeNominal", + "name": "Int8", + "printedName": "Swift.Int8", + "usr": "s:s4Int8V" + } + ] + } + ], + "usr": "s:Sp" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@__builtin_ms_va_list", + "moduleName": "__ObjC" + }, + { + "kind": "TypeAlias", + "name": "__builtin_va_list", + "printedName": "__builtin_va_list", + "children": [ + { + "kind": "TypeNominal", + "name": "UnsafeMutablePointer", + "printedName": "Swift.UnsafeMutablePointer", + "children": [ + { + "kind": "TypeNameAlias", + "name": "CChar", + "printedName": "Swift.CChar", + "children": [ + { + "kind": "TypeNominal", + "name": "Int8", + "printedName": "Swift.Int8", + "usr": "s:s4Int8V" + } + ] + } + ], + "usr": "s:Sp" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@__builtin_va_list", + "moduleName": "__ObjC" + }, + { + "kind": "TypeAlias", + "name": "char16_t", + "printedName": "char16_t", + "children": [ + { + "kind": "TypeNameAlias", + "name": "uint_least16_t", + "printedName": "_stdint.uint_least16_t", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt16", + "printedName": "Swift.UInt16", + "usr": "s:s6UInt16V" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@char16_t", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "char32_t", + "printedName": "char32_t", + "children": [ + { + "kind": "TypeNameAlias", + "name": "uint_least32_t", + "printedName": "_stdint.uint_least32_t", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt32", + "printedName": "Swift.UInt32", + "usr": "s:s6UInt32V" + } + ] + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@char32_t", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "char8_t", + "printedName": "char8_t", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt8", + "printedName": "Swift.UInt8", + "usr": "s:s5UInt8V" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@char8_t", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "defaultMaxBreadcrumbs", + "printedName": "defaultMaxBreadcrumbs", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "c:@defaultMaxBreadcrumbs", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentryFalseString", + "printedName": "kSentryFalseString", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentryFalseString", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameAborted", + "printedName": "kSentrySpanStatusNameAborted", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameAborted", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameAlreadyExists", + "printedName": "kSentrySpanStatusNameAlreadyExists", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameAlreadyExists", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameCancelled", + "printedName": "kSentrySpanStatusNameCancelled", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameCancelled", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameDataLoss", + "printedName": "kSentrySpanStatusNameDataLoss", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameDataLoss", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameDeadlineExceeded", + "printedName": "kSentrySpanStatusNameDeadlineExceeded", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameDeadlineExceeded", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameFailedPrecondition", + "printedName": "kSentrySpanStatusNameFailedPrecondition", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameFailedPrecondition", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameInternalError", + "printedName": "kSentrySpanStatusNameInternalError", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameInternalError", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameInvalidArgument", + "printedName": "kSentrySpanStatusNameInvalidArgument", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameInvalidArgument", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameNotFound", + "printedName": "kSentrySpanStatusNameNotFound", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameNotFound", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameOk", + "printedName": "kSentrySpanStatusNameOk", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameOk", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameOutOfRange", + "printedName": "kSentrySpanStatusNameOutOfRange", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameOutOfRange", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNamePermissionDenied", + "printedName": "kSentrySpanStatusNamePermissionDenied", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNamePermissionDenied", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameResourceExhausted", + "printedName": "kSentrySpanStatusNameResourceExhausted", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameResourceExhausted", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameUnauthenticated", + "printedName": "kSentrySpanStatusNameUnauthenticated", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameUnauthenticated", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameUnavailable", + "printedName": "kSentrySpanStatusNameUnavailable", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameUnavailable", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameUndefined", + "printedName": "kSentrySpanStatusNameUndefined", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameUndefined", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameUnimplemented", + "printedName": "kSentrySpanStatusNameUnimplemented", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameUnimplemented", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentrySpanStatusNameUnknownError", + "printedName": "kSentrySpanStatusNameUnknownError", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentrySpanStatusNameUnknownError", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Var", + "name": "kSentryTrueString", + "printedName": "kSentryTrueString", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@kSentryTrueString", + "moduleName": "Sentry", + "isLet": true, + "hasStorage": true + }, + { + "kind": "Function", + "name": "nameForSentrySpanStatus", + "printedName": "nameForSentrySpanStatus(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "SentrySpanStatus", + "printedName": "Sentry.SentrySpanStatus", + "usr": "c:@E@SentrySpanStatus" + } + ], + "declKind": "Func", + "usr": "c:@F@nameForSentrySpanStatus", + "moduleName": "Sentry", + "declAttributes": [ + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "TypeAlias", + "name": "swift_double2", + "printedName": "swift_double2", + "children": [ + { + "kind": "TypeNominal", + "name": "SIMD2", + "printedName": "Swift.SIMD2", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ], + "usr": "s:s5SIMD2V" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@swift_double2", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "swift_double3", + "printedName": "swift_double3", + "children": [ + { + "kind": "TypeNominal", + "name": "SIMD3", + "printedName": "Swift.SIMD3", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ], + "usr": "s:s5SIMD3V" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@swift_double3", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "swift_double4", + "printedName": "swift_double4", + "children": [ + { + "kind": "TypeNominal", + "name": "SIMD4", + "printedName": "Swift.SIMD4", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ], + "usr": "s:s5SIMD4V" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@swift_double4", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "swift_float2", + "printedName": "swift_float2", + "children": [ + { + "kind": "TypeNominal", + "name": "SIMD2", + "printedName": "Swift.SIMD2", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "usr": "s:s5SIMD2V" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@swift_float2", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "swift_float3", + "printedName": "swift_float3", + "children": [ + { + "kind": "TypeNominal", + "name": "SIMD3", + "printedName": "Swift.SIMD3", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "usr": "s:s5SIMD3V" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@swift_float3", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "swift_float4", + "printedName": "swift_float4", + "children": [ + { + "kind": "TypeNominal", + "name": "SIMD4", + "printedName": "Swift.SIMD4", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "usr": "s:s5SIMD4V" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@swift_float4", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "swift_int2", + "printedName": "swift_int2", + "children": [ + { + "kind": "TypeNominal", + "name": "SIMD2", + "printedName": "Swift.SIMD2", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "usr": "s:s5SIMD2V" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@swift_int2", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "swift_int3", + "printedName": "swift_int3", + "children": [ + { + "kind": "TypeNominal", + "name": "SIMD3", + "printedName": "Swift.SIMD3", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "usr": "s:s5SIMD3V" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@swift_int3", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "swift_int4", + "printedName": "swift_int4", + "children": [ + { + "kind": "TypeNominal", + "name": "SIMD4", + "printedName": "Swift.SIMD4", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "usr": "s:s5SIMD4V" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@swift_int4", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "swift_uint2", + "printedName": "swift_uint2", + "children": [ + { + "kind": "TypeNominal", + "name": "SIMD2", + "printedName": "Swift.SIMD2", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt32", + "printedName": "Swift.UInt32", + "usr": "s:s6UInt32V" + } + ], + "usr": "s:s5SIMD2V" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@swift_uint2", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "swift_uint3", + "printedName": "swift_uint3", + "children": [ + { + "kind": "TypeNominal", + "name": "SIMD3", + "printedName": "Swift.SIMD3", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt32", + "printedName": "Swift.UInt32", + "usr": "s:s6UInt32V" + } + ], + "usr": "s:s5SIMD3V" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@swift_uint3", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "swift_uint4", + "printedName": "swift_uint4", + "children": [ + { + "kind": "TypeNominal", + "name": "SIMD4", + "printedName": "Swift.SIMD4", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt32", + "printedName": "Swift.UInt32", + "usr": "s:s6UInt32V" + } + ], + "usr": "s:s5SIMD4V" + } + ], + "declKind": "TypeAlias", + "usr": "c:@T@swift_uint4", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "AVFoundation", + "printedName": "AVFoundation", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "CoreGraphics", + "printedName": "CoreGraphics", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "CoreMedia", + "printedName": "CoreMedia", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "Darwin", + "printedName": "Darwin", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "Foundation", + "printedName": "Foundation", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "MachO", + "printedName": "MachO", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "MetricKit", + "printedName": "MetricKit", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "ObjectiveC.NSObjCRuntime", + "printedName": "ObjectiveC.NSObjCRuntime", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "ObjectiveC", + "printedName": "ObjectiveC", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "PDFKit", + "printedName": "PDFKit", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "Sentry", + "printedName": "Sentry", + "declKind": "Import", + "moduleName": "Sentry", + "declAttributes": [ + "Exported" + ] + }, + { + "kind": "Import", + "name": "UIKit", + "printedName": "UIKit", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "WebKit", + "printedName": "WebKit", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "_Concurrency", + "printedName": "_Concurrency", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "_StringProcessing", + "printedName": "_StringProcessing", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "_SwiftConcurrencyShims", + "printedName": "_SwiftConcurrencyShims", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "Import", + "name": "ObjectiveC.runtime", + "printedName": "ObjectiveC.runtime", + "declKind": "Import", + "moduleName": "Sentry" + }, + { + "kind": "TypeDecl", + "name": "SentryViewScreenshotOptions", + "printedName": "SentryViewScreenshotOptions", + "children": [ + { + "kind": "TypeDecl", + "name": "DefaultValues", + "printedName": "DefaultValues", + "children": [ + { + "kind": "Var", + "name": "enableViewRendererV2", + "printedName": "enableViewRendererV2", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06enableB10RendererV2SbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "enableFastViewRendering", + "printedName": "enableFastViewRendering", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC010enableFastB9RenderingSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskAllText", + "printedName": "maskAllText", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC11maskAllTextSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskAllImages", + "printedName": "maskAllImages", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC13maskAllImagesSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskedViewClasses", + "printedName": "maskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC06maskedB7ClassesSayyXlXpGvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "unmaskedViewClasses", + "printedName": "unmaskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvpZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvgZ", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC08unmaskedB7ClassesSayyXlXpGvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + } + ], + "declKind": "Class", + "usr": "s:6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13DefaultValuesC", + "moduleName": "Sentry", + "hasMissingDesignatedInitializers": true, + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + } + ] + }, + { + "kind": "Var", + "name": "enableViewRendererV2", + "printedName": "enableViewRendererV2", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)enableViewRendererV2", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)enableViewRendererV2", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)setEnableViewRendererV2:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV2Sbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableFastViewRendering", + "printedName": "enableFastViewRendering", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)enableFastViewRendering", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC010enableFastB9RenderingSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)enableFastViewRendering", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC010enableFastB9RenderingSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)setEnableFastViewRendering:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC010enableFastB9RenderingSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "maskAllImages", + "printedName": "maskAllImages", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)maskAllImages", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13maskAllImagesSbvp", + "moduleName": "Sentry", + "objc_name": "maskAllImages", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)maskAllImages", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13maskAllImagesSbvg", + "moduleName": "Sentry", + "implicit": true, + "objc_name": "maskAllImages", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)setMaskAllImages:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC13maskAllImagesSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "maskAllText", + "printedName": "maskAllText", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)maskAllText", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11maskAllTextSbvp", + "moduleName": "Sentry", + "objc_name": "maskAllText", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)maskAllText", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11maskAllTextSbvg", + "moduleName": "Sentry", + "implicit": true, + "objc_name": "maskAllText", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)setMaskAllText:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11maskAllTextSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "maskedViewClasses", + "printedName": "maskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)maskedViewClasses", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06maskedB7ClassesSayyXlXpGvp", + "moduleName": "Sentry", + "objc_name": "maskedViewClasses", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)maskedViewClasses", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06maskedB7ClassesSayyXlXpGvg", + "moduleName": "Sentry", + "implicit": true, + "objc_name": "maskedViewClasses", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)setMaskedViewClasses:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06maskedB7ClassesSayyXlXpGvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "unmaskedViewClasses", + "printedName": "unmaskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)unmaskedViewClasses", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC08unmaskedB7ClassesSayyXlXpGvp", + "moduleName": "Sentry", + "objc_name": "unmaskedViewClasses", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)unmaskedViewClasses", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC08unmaskedB7ClassesSayyXlXpGvg", + "moduleName": "Sentry", + "implicit": true, + "objc_name": "unmaskedViewClasses", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)setUnmaskedViewClasses:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC08unmaskedB7ClassesSayyXlXpGvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryViewScreenshotOptions", + "printedName": "Sentry.SentryViewScreenshotOptions", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)init", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Convenience" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(enableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryViewScreenshotOptions", + "printedName": "Sentry.SentryViewScreenshotOptions", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "hasDefaultArg": true, + "usr": "s:Sa" + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "hasDefaultArg": true, + "usr": "s:Sa" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)initWithEnableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC06enableB10RendererV20e4FastB9Rendering11maskAllText0jK6Images06maskedB7Classes08unmaskedbO0ACSb_S3bSayyXlXpGAJtcfc", + "moduleName": "Sentry", + "objc_name": "initWithEnableViewRendererV2:enableFastViewRendering:maskAllText:maskAllImages:maskedViewClasses:unmaskedViewClasses:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "description", + "printedName": "description", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(py)description", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11descriptionSSvp", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "description", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions(im)description", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC11descriptionSSvg", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "description", + "declAttributes": [ + "Dynamic", + "ObjC", + "Override" + ], + "accessorKind": "get" + } + ] + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryViewScreenshotOptions", + "mangledName": "$s6Sentry0A21ViewScreenshotOptionsC", + "moduleName": "Sentry", + "declAttributes": [ + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "SentryRedactOptions", + "printedName": "SentryRedactOptions", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions", + "mangledName": "$s6Sentry0A13RedactOptionsP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryFeedback", + "printedName": "SentryFeedback", + "children": [ + { + "kind": "TypeDecl", + "name": "SentryFeedbackSource", + "printedName": "SentryFeedbackSource", + "children": [ + { + "kind": "Var", + "name": "serialize", + "printedName": "serialize", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO9serializeSSvp", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO9serializeSSvp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO9serializeSSvg", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO9serializeSSvg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "widget", + "printedName": "widget", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryFeedback.SentryFeedbackSource.Type) -> Sentry.SentryFeedback.SentryFeedbackSource", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO6widgetyA2EmF", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO6widgetyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "custom", + "printedName": "custom", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryFeedback.SentryFeedbackSource.Type) -> Sentry.SentryFeedback.SentryFeedbackSource", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO6customyA2EmF", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO6customyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO8rawValueAESgSi_tcfc", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO8rawValueAESgSi_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO8RawValuea", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO8RawValuea", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO8rawValueSivp", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO8rawValueSivp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO8rawValueSivg", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO8rawValueSivg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + } + ], + "declKind": "Enum", + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO", + "mangledName": "$s6Sentry0A8FeedbackC0aB6SourceO", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(message:name:email:source:associatedEventId:attachments:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedback", + "printedName": "Sentry.SentryFeedback", + "usr": "c:@M@Sentry@objc(cs)SentryFeedback" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "SentryFeedbackSource", + "printedName": "Sentry.SentryFeedback.SentryFeedbackSource", + "hasDefaultArg": true, + "usr": "s:6Sentry0A8FeedbackC0aB6SourceO" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryId?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "hasDefaultArg": true, + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Foundation.Data]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Foundation.Data]", + "children": [ + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + } + ], + "usr": "s:Sa" + } + ], + "hasDefaultArg": true, + "usr": "s:Sq" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryFeedback(im)initWithMessage:name:email:source:associatedEventId:attachments:", + "mangledName": "$s6Sentry0A8FeedbackC7message4name5email6source17associatedEventId11attachmentsACSS_SSSgAjC0aB6SourceOAA0aI0CSgSay10Foundation4DataVGSgtcfc", + "moduleName": "Sentry", + "objc_name": "initWithMessage:name:email:source:associatedEventId:attachments:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryFeedback", + "mangledName": "$s6Sentry0A8FeedbackC", + "moduleName": "Sentry", + "declAttributes": [ + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryLogMessage", + "printedName": "SentryLogMessage", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(stringLiteral:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A10LogMessageV13stringLiteralACSS_tcfc", + "mangledName": "$s6Sentry0A10LogMessageV13stringLiteralACSS_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(stringInterpolation:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "StringInterpolation", + "printedName": "Sentry.SentryLogMessage.StringInterpolation", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A10LogMessageV19stringInterpolationA2C06StringE0V_tcfc", + "mangledName": "$s6Sentry0A10LogMessageV19stringInterpolationA2C06StringE0V_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeDecl", + "name": "StringInterpolation", + "printedName": "StringInterpolation", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(literalCapacity:interpolationCount:)", + "children": [ + { + "kind": "TypeNominal", + "name": "StringInterpolation", + "printedName": "Sentry.SentryLogMessage.StringInterpolation", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV15literalCapacity18interpolationCountAESi_Sitcfc", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV15literalCapacity18interpolationCountAESi_Sitcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "Function", + "name": "appendLiteral", + "printedName": "appendLiteral(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV13appendLiteralyySSF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV13appendLiteralyySSF", + "moduleName": "Sentry", + "funcSelfKind": "Mutating" + }, + { + "kind": "Function", + "name": "appendInterpolation", + "printedName": "appendInterpolation(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.String", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySSyXAF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySSyXAF", + "moduleName": "Sentry", + "funcSelfKind": "Mutating" + }, + { + "kind": "Function", + "name": "appendInterpolation", + "printedName": "appendInterpolation(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Bool", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySbyXAF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySbyXAF", + "moduleName": "Sentry", + "funcSelfKind": "Mutating" + }, + { + "kind": "Function", + "name": "appendInterpolation", + "printedName": "appendInterpolation(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Int", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySiyXAF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySiyXAF", + "moduleName": "Sentry", + "funcSelfKind": "Mutating" + }, + { + "kind": "Function", + "name": "appendInterpolation", + "printedName": "appendInterpolation(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Double", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySdyXAF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySdyXAF", + "moduleName": "Sentry", + "funcSelfKind": "Mutating" + }, + { + "kind": "Function", + "name": "appendInterpolation", + "printedName": "appendInterpolation(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Float", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySfyXAF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV06appendE0yySfyXAF", + "moduleName": "Sentry", + "funcSelfKind": "Mutating" + }, + { + "kind": "Function", + "name": "appendInterpolation", + "printedName": "appendInterpolation(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> T", + "children": [ + { + "kind": "TypeNominal", + "name": "GenericTypeParam", + "printedName": "T" + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV06appendE0yyxyXAs06CustomD11ConvertibleRzlF", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV06appendE0yyxyXAs06CustomD11ConvertibleRzlF", + "moduleName": "Sentry", + "genericSig": "", + "funcSelfKind": "Mutating" + }, + { + "kind": "TypeAlias", + "name": "StringLiteralType", + "printedName": "StringLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV0D11LiteralTypea", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV0D11LiteralTypea", + "moduleName": "Sentry" + } + ], + "declKind": "Struct", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV", + "mangledName": "$s6Sentry0A10LogMessageV19StringInterpolationV", + "moduleName": "Sentry", + "conformances": [ + { + "kind": "Conformance", + "name": "StringInterpolationProtocol", + "printedName": "StringInterpolationProtocol", + "children": [ + { + "kind": "TypeWitness", + "name": "StringLiteralType", + "printedName": "StringLiteralType", + "children": [ + { + "kind": "TypeNameAlias", + "name": "StringLiteralType", + "printedName": "Sentry.SentryLogMessage.StringInterpolation.StringLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ] + } + ] + } + ], + "usr": "s:s27StringInterpolationProtocolP", + "mangledName": "$ss27StringInterpolationProtocolP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + } + ] + }, + { + "kind": "TypeAlias", + "name": "ExtendedGraphemeClusterLiteralType", + "printedName": "ExtendedGraphemeClusterLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A10LogMessageV34ExtendedGraphemeClusterLiteralTypea", + "mangledName": "$s6Sentry0A10LogMessageV34ExtendedGraphemeClusterLiteralTypea", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "StringLiteralType", + "printedName": "StringLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A10LogMessageV17StringLiteralTypea", + "mangledName": "$s6Sentry0A10LogMessageV17StringLiteralTypea", + "moduleName": "Sentry" + }, + { + "kind": "TypeAlias", + "name": "UnicodeScalarLiteralType", + "printedName": "UnicodeScalarLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A10LogMessageV24UnicodeScalarLiteralTypea", + "mangledName": "$s6Sentry0A10LogMessageV24UnicodeScalarLiteralTypea", + "moduleName": "Sentry" + } + ], + "declKind": "Struct", + "usr": "s:6Sentry0A10LogMessageV", + "mangledName": "$s6Sentry0A10LogMessageV", + "moduleName": "Sentry", + "conformances": [ + { + "kind": "Conformance", + "name": "ExpressibleByStringInterpolation", + "printedName": "ExpressibleByStringInterpolation", + "children": [ + { + "kind": "TypeWitness", + "name": "StringInterpolation", + "printedName": "StringInterpolation", + "children": [ + { + "kind": "TypeNominal", + "name": "StringInterpolation", + "printedName": "Sentry.SentryLogMessage.StringInterpolation", + "usr": "s:6Sentry0A10LogMessageV19StringInterpolationV" + } + ] + } + ], + "usr": "s:s32ExpressibleByStringInterpolationP", + "mangledName": "$ss32ExpressibleByStringInterpolationP" + }, + { + "kind": "Conformance", + "name": "ExpressibleByStringLiteral", + "printedName": "ExpressibleByStringLiteral", + "children": [ + { + "kind": "TypeWitness", + "name": "StringLiteralType", + "printedName": "StringLiteralType", + "children": [ + { + "kind": "TypeNameAlias", + "name": "StringLiteralType", + "printedName": "Sentry.SentryLogMessage.StringLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ] + } + ] + } + ], + "usr": "s:s26ExpressibleByStringLiteralP", + "mangledName": "$ss26ExpressibleByStringLiteralP" + }, + { + "kind": "Conformance", + "name": "ExpressibleByExtendedGraphemeClusterLiteral", + "printedName": "ExpressibleByExtendedGraphemeClusterLiteral", + "children": [ + { + "kind": "TypeWitness", + "name": "ExtendedGraphemeClusterLiteralType", + "printedName": "ExtendedGraphemeClusterLiteralType", + "children": [ + { + "kind": "TypeNameAlias", + "name": "ExtendedGraphemeClusterLiteralType", + "printedName": "Sentry.SentryLogMessage.ExtendedGraphemeClusterLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ] + } + ] + } + ], + "usr": "s:s43ExpressibleByExtendedGraphemeClusterLiteralP", + "mangledName": "$ss43ExpressibleByExtendedGraphemeClusterLiteralP" + }, + { + "kind": "Conformance", + "name": "ExpressibleByUnicodeScalarLiteral", + "printedName": "ExpressibleByUnicodeScalarLiteral", + "children": [ + { + "kind": "TypeWitness", + "name": "UnicodeScalarLiteralType", + "printedName": "UnicodeScalarLiteralType", + "children": [ + { + "kind": "TypeNameAlias", + "name": "UnicodeScalarLiteralType", + "printedName": "Sentry.SentryLogMessage.UnicodeScalarLiteralType", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ] + } + ] + } + ], + "usr": "s:s33ExpressibleByUnicodeScalarLiteralP", + "mangledName": "$ss33ExpressibleByUnicodeScalarLiteralP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryLog", + "printedName": "SentryLog", + "children": [ + { + "kind": "Var", + "name": "timestamp", + "printedName": "timestamp", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryLog(py)timestamp", + "mangledName": "$s6Sentry0A3LogC9timestamp10Foundation4DateVvp", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)timestamp", + "mangledName": "$s6Sentry0A3LogC9timestamp10Foundation4DateVvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Date", + "printedName": "Foundation.Date", + "usr": "s:10Foundation4DateV" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)setTimestamp:", + "mangledName": "$s6Sentry0A3LogC9timestamp10Foundation4DateVvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "traceId", + "printedName": "traceId", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryLog(py)traceId", + "mangledName": "$s6Sentry0A3LogC7traceIdAA0aD0Cvp", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)traceId", + "mangledName": "$s6Sentry0A3LogC7traceIdAA0aD0Cvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)setTraceId:", + "mangledName": "$s6Sentry0A3LogC7traceIdAA0aD0Cvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "level", + "printedName": "level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryLog(py)level", + "mangledName": "$s6Sentry0A3LogC5levelAC5LevelOvp", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)level", + "mangledName": "$s6Sentry0A3LogC5levelAC5LevelOvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)setLevel:", + "mangledName": "$s6Sentry0A3LogC5levelAC5LevelOvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "body", + "printedName": "body", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryLog(py)body", + "mangledName": "$s6Sentry0A3LogC4bodySSvp", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)body", + "mangledName": "$s6Sentry0A3LogC4bodySSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)setBody:", + "mangledName": "$s6Sentry0A3LogC4bodySSvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "attributes", + "printedName": "attributes", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Sentry.SentryLog.Attribute]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryLog(py)attributes", + "mangledName": "$s6Sentry0A3LogC10attributesSDySSAC9AttributeCGvp", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Sentry.SentryLog.Attribute]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)attributes", + "mangledName": "$s6Sentry0A3LogC10attributesSDySSAC9AttributeCGvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Sentry.SentryLog.Attribute]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)setAttributes:", + "mangledName": "$s6Sentry0A3LogC10attributesSDySSAC9AttributeCGvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "severityNumber", + "printedName": "severityNumber", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryLog(py)severityNumber", + "mangledName": "$s6Sentry0A3LogC14severityNumberSo8NSNumberCSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "Final", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)severityNumber", + "mangledName": "$s6Sentry0A3LogC14severityNumberSo8NSNumberCSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.NSNumber?", + "children": [ + { + "kind": "TypeNominal", + "name": "NSNumber", + "printedName": "Foundation.NSNumber", + "usr": "c:objc(cs)NSNumber" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryLog(im)setSeverityNumber:", + "mangledName": "$s6Sentry0A3LogC14severityNumberSo8NSNumberCSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "TypeDecl", + "name": "Level", + "printedName": "Level", + "children": [ + { + "kind": "Var", + "name": "trace", + "printedName": "trace", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog.Level.Type) -> Sentry.SentryLog.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLog.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A3LogC5LevelO5traceyA2EmF", + "mangledName": "$s6Sentry0A3LogC5LevelO5traceyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "debug", + "printedName": "debug", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog.Level.Type) -> Sentry.SentryLog.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLog.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A3LogC5LevelO5debugyA2EmF", + "mangledName": "$s6Sentry0A3LogC5LevelO5debugyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "info", + "printedName": "info", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog.Level.Type) -> Sentry.SentryLog.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLog.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A3LogC5LevelO4infoyA2EmF", + "mangledName": "$s6Sentry0A3LogC5LevelO4infoyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "warn", + "printedName": "warn", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog.Level.Type) -> Sentry.SentryLog.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLog.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A3LogC5LevelO4warnyA2EmF", + "mangledName": "$s6Sentry0A3LogC5LevelO4warnyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "error", + "printedName": "error", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog.Level.Type) -> Sentry.SentryLog.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLog.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A3LogC5LevelO5erroryA2EmF", + "mangledName": "$s6Sentry0A3LogC5LevelO5erroryA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "fatal", + "printedName": "fatal", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLog.Level.Type) -> Sentry.SentryLog.Level", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLog.Level.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A3LogC5LevelO5fatalyA2EmF", + "mangledName": "$s6Sentry0A3LogC5LevelO5fatalyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(value:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A3LogC5LevelO5valueAESS_tKcfc", + "mangledName": "$s6Sentry0A3LogC5LevelO5valueAESS_tKcfc", + "moduleName": "Sentry", + "throwing": true, + "init_kind": "Designated" + }, + { + "kind": "Var", + "name": "value", + "printedName": "value", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A3LogC5LevelO5valueSSvp", + "mangledName": "$s6Sentry0A3LogC5LevelO5valueSSvp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A3LogC5LevelO5valueSSvg", + "mangledName": "$s6Sentry0A3LogC5LevelO5valueSSvg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + }, + { + "kind": "Function", + "name": "toSeverityNumber", + "printedName": "toSeverityNumber()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A3LogC5LevelO16toSeverityNumberSiyF", + "mangledName": "$s6Sentry0A3LogC5LevelO16toSeverityNumberSiyF", + "moduleName": "Sentry", + "funcSelfKind": "NonMutating" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryLog.Level?", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "Sentry.SentryLog.Level", + "usr": "s:6Sentry0A3LogC5LevelO" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A3LogC5LevelO8rawValueAESgSi_tcfc", + "mangledName": "$s6Sentry0A3LogC5LevelO8rawValueAESgSi_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A3LogC5LevelO8RawValuea", + "mangledName": "$s6Sentry0A3LogC5LevelO8RawValuea", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A3LogC5LevelO8rawValueSivp", + "mangledName": "$s6Sentry0A3LogC5LevelO8rawValueSivp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A3LogC5LevelO8rawValueSivg", + "mangledName": "$s6Sentry0A3LogC5LevelO8rawValueSivg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + } + ], + "declKind": "Enum", + "usr": "s:6Sentry0A3LogC5LevelO", + "mangledName": "$s6Sentry0A3LogC5LevelO", + "moduleName": "Sentry", + "objc_name": "SentryStructuredLogLevel", + "declAttributes": [ + "ObjC" + ], + "isFromExtension": true, + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryLog.Level.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, + { + "kind": "TypeDecl", + "name": "Attribute", + "printedName": "Attribute", + "children": [ + { + "kind": "Var", + "name": "type", + "printedName": "type", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A3LogC9AttributeC4typeSSvp", + "mangledName": "$s6Sentry0A3LogC9AttributeC4typeSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A3LogC9AttributeC4typeSSvg", + "mangledName": "$s6Sentry0A3LogC9AttributeC4typeSSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "value", + "printedName": "value", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A3LogC9AttributeC5valueypvp", + "mangledName": "$s6Sentry0A3LogC9AttributeC5valueypvp", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A3LogC9AttributeC5valueypvg", + "mangledName": "$s6Sentry0A3LogC9AttributeC5valueypvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(string:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A3LogC9AttributeC6stringAESS_tcfc", + "mangledName": "$s6Sentry0A3LogC9AttributeC6stringAESS_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithString:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(boolean:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A3LogC9AttributeC7booleanAESb_tcfc", + "mangledName": "$s6Sentry0A3LogC9AttributeC7booleanAESb_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithBoolean:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(integer:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A3LogC9AttributeC7integerAESi_tcfc", + "mangledName": "$s6Sentry0A3LogC9AttributeC7integerAESi_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithInteger:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(double:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" + }, + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A3LogC9AttributeC6doubleAESd_tcfc", + "mangledName": "$s6Sentry0A3LogC9AttributeC6doubleAESd_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithDouble:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(float:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Attribute", + "printedName": "Sentry.SentryLog.Attribute", + "usr": "s:6Sentry0A3LogC9AttributeC" + }, + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A3LogC9AttributeC5floatAESf_tcfc", + "mangledName": "$s6Sentry0A3LogC9AttributeC5floatAESf_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithFloat:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "s:6Sentry0A3LogC9AttributeC", + "mangledName": "$s6Sentry0A3LogC9AttributeC", + "moduleName": "Sentry", + "objc_name": "SentryStructuredLogAttribute", + "declAttributes": [ + "Final", + "ObjCMembers", + "ObjC" + ], + "isFromExtension": true, + "superclassUsr": "c:objc(cs)NSObject", + "hasMissingDesignatedInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryLog", + "mangledName": "$s6Sentry0A3LogC", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "hasMissingDesignatedInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryLogger", + "printedName": "SentryLogger", + "children": [ + { + "kind": "Function", + "name": "trace", + "printedName": "trace(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "hasDefaultArg": true, + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A6LoggerC5trace_10attributesyAA0A10LogMessageV_SDySSypGtF", + "mangledName": "$s6Sentry0A6LoggerC5trace_10attributesyAA0A10LogMessageV_SDySSypGtF", + "moduleName": "Sentry", + "declAttributes": [ + "Final" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "trace", + "printedName": "trace(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)trace:", + "mangledName": "$s6Sentry0A6LoggerC5traceyySSF", + "moduleName": "Sentry", + "objc_name": "trace:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "trace", + "printedName": "trace(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)trace:attributes:", + "mangledName": "$s6Sentry0A6LoggerC5trace_10attributesySS_SDySSypGtF", + "moduleName": "Sentry", + "objc_name": "trace:attributes:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "debug", + "printedName": "debug(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "hasDefaultArg": true, + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A6LoggerC5debug_10attributesyAA0A10LogMessageV_SDySSypGtF", + "mangledName": "$s6Sentry0A6LoggerC5debug_10attributesyAA0A10LogMessageV_SDySSypGtF", + "moduleName": "Sentry", + "declAttributes": [ + "Final" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "debug", + "printedName": "debug(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)debug:", + "mangledName": "$s6Sentry0A6LoggerC5debugyySSF", + "moduleName": "Sentry", + "objc_name": "debug:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "debug", + "printedName": "debug(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)debug:attributes:", + "mangledName": "$s6Sentry0A6LoggerC5debug_10attributesySS_SDySSypGtF", + "moduleName": "Sentry", + "objc_name": "debug:attributes:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "info", + "printedName": "info(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "hasDefaultArg": true, + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A6LoggerC4info_10attributesyAA0A10LogMessageV_SDySSypGtF", + "mangledName": "$s6Sentry0A6LoggerC4info_10attributesyAA0A10LogMessageV_SDySSypGtF", + "moduleName": "Sentry", + "declAttributes": [ + "Final" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "info", + "printedName": "info(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)info:", + "mangledName": "$s6Sentry0A6LoggerC4infoyySSF", + "moduleName": "Sentry", + "objc_name": "info:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "info", + "printedName": "info(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)info:attributes:", + "mangledName": "$s6Sentry0A6LoggerC4info_10attributesySS_SDySSypGtF", + "moduleName": "Sentry", + "objc_name": "info:attributes:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "warn", + "printedName": "warn(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "hasDefaultArg": true, + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A6LoggerC4warn_10attributesyAA0A10LogMessageV_SDySSypGtF", + "mangledName": "$s6Sentry0A6LoggerC4warn_10attributesyAA0A10LogMessageV_SDySSypGtF", + "moduleName": "Sentry", + "declAttributes": [ + "Final" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "warn", + "printedName": "warn(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)warn:", + "mangledName": "$s6Sentry0A6LoggerC4warnyySSF", + "moduleName": "Sentry", + "objc_name": "warn:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "warn", + "printedName": "warn(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)warn:attributes:", + "mangledName": "$s6Sentry0A6LoggerC4warn_10attributesySS_SDySSypGtF", + "moduleName": "Sentry", + "objc_name": "warn:attributes:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "error", + "printedName": "error(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "hasDefaultArg": true, + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A6LoggerC5error_10attributesyAA0A10LogMessageV_SDySSypGtF", + "mangledName": "$s6Sentry0A6LoggerC5error_10attributesyAA0A10LogMessageV_SDySSypGtF", + "moduleName": "Sentry", + "declAttributes": [ + "Final" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "error", + "printedName": "error(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)error:", + "mangledName": "$s6Sentry0A6LoggerC5erroryySSF", + "moduleName": "Sentry", + "objc_name": "error:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "error", + "printedName": "error(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)error:attributes:", + "mangledName": "$s6Sentry0A6LoggerC5error_10attributesySS_SDySSypGtF", + "moduleName": "Sentry", + "objc_name": "error:attributes:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "fatal", + "printedName": "fatal(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryLogMessage", + "printedName": "Sentry.SentryLogMessage", + "usr": "s:6Sentry0A10LogMessageV" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "hasDefaultArg": true, + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "s:6Sentry0A6LoggerC5fatal_10attributesyAA0A10LogMessageV_SDySSypGtF", + "mangledName": "$s6Sentry0A6LoggerC5fatal_10attributesyAA0A10LogMessageV_SDySSypGtF", + "moduleName": "Sentry", + "declAttributes": [ + "Final" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "fatal", + "printedName": "fatal(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)fatal:", + "mangledName": "$s6Sentry0A6LoggerC5fatalyySSF", + "moduleName": "Sentry", + "objc_name": "fatal:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "fatal", + "printedName": "fatal(_:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryLogger(im)fatal:attributes:", + "mangledName": "$s6Sentry0A6LoggerC5fatal_10attributesySS_SDySSypGtF", + "moduleName": "Sentry", + "objc_name": "fatal:attributes:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryLogger", + "mangledName": "$s6Sentry0A6LoggerC", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryReplayOptions", + "printedName": "SentryReplayOptions", + "children": [ + { + "kind": "TypeDecl", + "name": "DefaultValues", + "printedName": "DefaultValues", + "children": [ + { + "kind": "Var", + "name": "sessionSampleRate", + "printedName": "sessionSampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17sessionSampleRateSfvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17sessionSampleRateSfvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17sessionSampleRateSfvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17sessionSampleRateSfvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "onErrorSampleRate", + "printedName": "onErrorSampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17onErrorSampleRateSfvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17onErrorSampleRateSfvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17onErrorSampleRateSfvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17onErrorSampleRateSfvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskAllText", + "printedName": "maskAllText", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC11maskAllTextSbvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC11maskAllTextSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC11maskAllTextSbvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC11maskAllTextSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskAllImages", + "printedName": "maskAllImages", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC13maskAllImagesSbvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC13maskAllImagesSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC13maskAllImagesSbvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC13maskAllImagesSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "enableViewRendererV2", + "printedName": "enableViewRendererV2", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC20enableViewRendererV2SbvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC20enableViewRendererV2SbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC20enableViewRendererV2SbvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC20enableViewRendererV2SbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "enableFastViewRendering", + "printedName": "enableFastViewRendering", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC23enableFastViewRenderingSbvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC23enableFastViewRenderingSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC23enableFastViewRenderingSbvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC23enableFastViewRenderingSbvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "quality", + "printedName": "quality", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC7qualityAC0aB7QualityOvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC7qualityAC0aB7QualityOvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC7qualityAC0aB7QualityOvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC7qualityAC0aB7QualityOvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskedViewClasses", + "printedName": "maskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17maskedViewClassesSayyXlXpGvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17maskedViewClassesSayyXlXpGvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC17maskedViewClassesSayyXlXpGvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC17maskedViewClassesSayyXlXpGvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "unmaskedViewClasses", + "printedName": "unmaskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC19unmaskedViewClassesSayyXlXpGvpZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC19unmaskedViewClassesSayyXlXpGvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC19unmaskedViewClassesSayyXlXpGvgZ", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC19unmaskedViewClassesSayyXlXpGvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final" + ], + "accessorKind": "get" + } + ] + } + ], + "declKind": "Class", + "usr": "s:6Sentry0A13ReplayOptionsC13DefaultValuesC", + "mangledName": "$s6Sentry0A13ReplayOptionsC13DefaultValuesC", + "moduleName": "Sentry", + "hasMissingDesignatedInitializers": true, + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryReplayQuality", + "printedName": "SentryReplayQuality", + "children": [ + { + "kind": "Var", + "name": "low", + "printedName": "low", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryReplayOptions.SentryReplayQuality.Type) -> Sentry.SentryReplayOptions.SentryReplayQuality", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO3lowyA2EmF", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO3lowyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "medium", + "printedName": "medium", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryReplayOptions.SentryReplayQuality.Type) -> Sentry.SentryReplayOptions.SentryReplayQuality", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO6mediumyA2EmF", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO6mediumyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "high", + "printedName": "high", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryReplayOptions.SentryReplayQuality.Type) -> Sentry.SentryReplayOptions.SentryReplayQuality", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO4highyA2EmF", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO4highyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "description", + "printedName": "description", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO11descriptionSSvp", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO11descriptionSSvp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO11descriptionSSvg", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO11descriptionSSvg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueAESgSi_tcfc", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueAESgSi_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO8RawValuea", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO8RawValuea", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueSivp", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueSivp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueSivg", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO8rawValueSivg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + } + ], + "declKind": "Enum", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO", + "mangledName": "$s6Sentry0A13ReplayOptionsC0aB7QualityO", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, + { + "kind": "Var", + "name": "sessionSampleRate", + "printedName": "sessionSampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)sessionSampleRate", + "mangledName": "$s6Sentry0A13ReplayOptionsC17sessionSampleRateSfvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)sessionSampleRate", + "mangledName": "$s6Sentry0A13ReplayOptionsC17sessionSampleRateSfvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setSessionSampleRate:", + "mangledName": "$s6Sentry0A13ReplayOptionsC17sessionSampleRateSfvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "onErrorSampleRate", + "printedName": "onErrorSampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)onErrorSampleRate", + "mangledName": "$s6Sentry0A13ReplayOptionsC17onErrorSampleRateSfvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)onErrorSampleRate", + "mangledName": "$s6Sentry0A13ReplayOptionsC17onErrorSampleRateSfvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setOnErrorSampleRate:", + "mangledName": "$s6Sentry0A13ReplayOptionsC17onErrorSampleRateSfvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "maskAllText", + "printedName": "maskAllText", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)maskAllText", + "mangledName": "$s6Sentry0A13ReplayOptionsC11maskAllTextSbvp", + "moduleName": "Sentry", + "objc_name": "maskAllText", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)maskAllText", + "mangledName": "$s6Sentry0A13ReplayOptionsC11maskAllTextSbvg", + "moduleName": "Sentry", + "implicit": true, + "objc_name": "maskAllText", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setMaskAllText:", + "mangledName": "$s6Sentry0A13ReplayOptionsC11maskAllTextSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "maskAllImages", + "printedName": "maskAllImages", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)maskAllImages", + "mangledName": "$s6Sentry0A13ReplayOptionsC13maskAllImagesSbvp", + "moduleName": "Sentry", + "objc_name": "maskAllImages", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)maskAllImages", + "mangledName": "$s6Sentry0A13ReplayOptionsC13maskAllImagesSbvg", + "moduleName": "Sentry", + "implicit": true, + "objc_name": "maskAllImages", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setMaskAllImages:", + "mangledName": "$s6Sentry0A13ReplayOptionsC13maskAllImagesSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "quality", + "printedName": "quality", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)quality", + "mangledName": "$s6Sentry0A13ReplayOptionsC7qualityAC0aB7QualityOvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)quality", + "mangledName": "$s6Sentry0A13ReplayOptionsC7qualityAC0aB7QualityOvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryReplayQuality", + "printedName": "Sentry.SentryReplayOptions.SentryReplayQuality", + "usr": "s:6Sentry0A13ReplayOptionsC0aB7QualityO" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setQuality:", + "mangledName": "$s6Sentry0A13ReplayOptionsC7qualityAC0aB7QualityOvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "maskedViewClasses", + "printedName": "maskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)maskedViewClasses", + "mangledName": "$s6Sentry0A13ReplayOptionsC17maskedViewClassesSayyXlXpGvp", + "moduleName": "Sentry", + "objc_name": "maskedViewClasses", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)maskedViewClasses", + "mangledName": "$s6Sentry0A13ReplayOptionsC17maskedViewClassesSayyXlXpGvg", + "moduleName": "Sentry", + "implicit": true, + "objc_name": "maskedViewClasses", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setMaskedViewClasses:", + "mangledName": "$s6Sentry0A13ReplayOptionsC17maskedViewClassesSayyXlXpGvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "unmaskedViewClasses", + "printedName": "unmaskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)unmaskedViewClasses", + "mangledName": "$s6Sentry0A13ReplayOptionsC19unmaskedViewClassesSayyXlXpGvp", + "moduleName": "Sentry", + "objc_name": "unmaskedViewClasses", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)unmaskedViewClasses", + "mangledName": "$s6Sentry0A13ReplayOptionsC19unmaskedViewClassesSayyXlXpGvg", + "moduleName": "Sentry", + "implicit": true, + "objc_name": "unmaskedViewClasses", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setUnmaskedViewClasses:", + "mangledName": "$s6Sentry0A13ReplayOptionsC19unmaskedViewClassesSayyXlXpGvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableExperimentalViewRenderer", + "printedName": "enableExperimentalViewRenderer", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)enableExperimentalViewRenderer", + "mangledName": "$s6Sentry0A13ReplayOptionsC30enableExperimentalViewRendererSbvp", + "moduleName": "Sentry", + "deprecated": true, + "declAttributes": [ + "Available", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)enableExperimentalViewRenderer", + "mangledName": "$s6Sentry0A13ReplayOptionsC30enableExperimentalViewRendererSbvg", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setEnableExperimentalViewRenderer:", + "mangledName": "$s6Sentry0A13ReplayOptionsC30enableExperimentalViewRendererSbvs", + "moduleName": "Sentry", + "objc_name": "setEnableExperimentalViewRenderer:", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableViewRendererV2", + "printedName": "enableViewRendererV2", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)enableViewRendererV2", + "mangledName": "$s6Sentry0A13ReplayOptionsC20enableViewRendererV2Sbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)enableViewRendererV2", + "mangledName": "$s6Sentry0A13ReplayOptionsC20enableViewRendererV2Sbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setEnableViewRendererV2:", + "mangledName": "$s6Sentry0A13ReplayOptionsC20enableViewRendererV2Sbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableFastViewRendering", + "printedName": "enableFastViewRendering", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(py)enableFastViewRendering", + "mangledName": "$s6Sentry0A13ReplayOptionsC23enableFastViewRenderingSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)enableFastViewRendering", + "mangledName": "$s6Sentry0A13ReplayOptionsC23enableFastViewRenderingSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)setEnableFastViewRendering:", + "mangledName": "$s6Sentry0A13ReplayOptionsC23enableFastViewRenderingSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayOptions", + "printedName": "Sentry.SentryReplayOptions", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)init", + "mangledName": "$s6Sentry0A13ReplayOptionsCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Convenience" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(sessionSampleRate:onErrorSampleRate:maskAllText:maskAllImages:enableViewRendererV2:enableFastViewRendering:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayOptions", + "printedName": "Sentry.SentryReplayOptions", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions" + }, + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "hasDefaultArg": true, + "usr": "s:Sf" + }, + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "hasDefaultArg": true, + "usr": "s:Sf" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "hasDefaultArg": true, + "usr": "s:Sb" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions(im)initWithSessionSampleRate:onErrorSampleRate:maskAllText:maskAllImages:enableViewRendererV2:enableFastViewRendering:", + "mangledName": "$s6Sentry0A13ReplayOptionsC17sessionSampleRate07onErroreF011maskAllText0iJ6Images20enableViewRendererV20m4FastN9RenderingACSf_SfS4btcfc", + "moduleName": "Sentry", + "objc_name": "initWithSessionSampleRate:onErrorSampleRate:maskAllText:maskAllImages:enableViewRendererV2:enableFastViewRendering:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Convenience" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryReplayOptions", + "mangledName": "$s6Sentry0A13ReplayOptionsC", + "moduleName": "Sentry", + "declAttributes": [ + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "hasMissingDesignatedInitializers": true, + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "SentryRedactOptions", + "printedName": "SentryRedactOptions", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions", + "mangledName": "$s6Sentry0A13RedactOptionsP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryEventDecoder", + "printedName": "SentryEventDecoder", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryEventDecoder", + "printedName": "Sentry.SentryEventDecoder", + "usr": "c:@M@Sentry@objc(cs)SentryEventDecoder" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryEventDecoder(im)init", + "mangledName": "$s6Sentry0A12EventDecoderCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryEventDecoder", + "mangledName": "$s6Sentry0A12EventDecoderC", + "moduleName": "Sentry", + "declAttributes": [ + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryUserFeedbackConfiguration", + "printedName": "SentryUserFeedbackConfiguration", + "children": [ + { + "kind": "Var", + "name": "animations", + "printedName": "animations", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)animations", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10animationsSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)animations", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10animationsSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setAnimations:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10animationsSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "configureWidget", + "printedName": "configureWidget", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackWidgetConfiguration", + "printedName": "Sentry.SentryUserFeedbackWidgetConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)configureWidget", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15configureWidgetyAA0abcfD0CcSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackWidgetConfiguration", + "printedName": "Sentry.SentryUserFeedbackWidgetConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)configureWidget", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15configureWidgetyAA0abcfD0CcSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackWidgetConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackWidgetConfiguration", + "printedName": "Sentry.SentryUserFeedbackWidgetConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setConfigureWidget:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15configureWidgetyAA0abcfD0CcSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "useShakeGesture", + "printedName": "useShakeGesture", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)useShakeGesture", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15useShakeGestureSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)useShakeGesture", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15useShakeGestureSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setUseShakeGesture:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15useShakeGestureSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "showFormForScreenshots", + "printedName": "showFormForScreenshots", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)showFormForScreenshots", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC22showFormForScreenshotsSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)showFormForScreenshots", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC22showFormForScreenshotsSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setShowFormForScreenshots:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC22showFormForScreenshotsSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "customButton", + "printedName": "customButton", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "UIKit.UIButton?", + "children": [ + { + "kind": "TypeNominal", + "name": "UIButton", + "printedName": "UIKit.UIButton", + "usr": "c:objc(cs)UIButton" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)customButton", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC12customButtonSo8UIButtonCSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "UIKit.UIButton?", + "children": [ + { + "kind": "TypeNominal", + "name": "UIButton", + "printedName": "UIKit.UIButton", + "usr": "c:objc(cs)UIButton" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)customButton", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC12customButtonSo8UIButtonCSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "UIKit.UIButton?", + "children": [ + { + "kind": "TypeNominal", + "name": "UIButton", + "printedName": "UIKit.UIButton", + "usr": "c:objc(cs)UIButton" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setCustomButton:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC12customButtonSo8UIButtonCSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "configureForm", + "printedName": "configureForm", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackFormConfiguration", + "printedName": "Sentry.SentryUserFeedbackFormConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)configureForm", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13configureFormyAA0abcfD0CcSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackFormConfiguration", + "printedName": "Sentry.SentryUserFeedbackFormConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)configureForm", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13configureFormyAA0abcfD0CcSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackFormConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackFormConfiguration", + "printedName": "Sentry.SentryUserFeedbackFormConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setConfigureForm:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13configureFormyAA0abcfD0CcSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "tags", + "printedName": "tags", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)tags", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC4tagsSDySSypGSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)tags", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC4tagsSDySSypGSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Swift.String : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setTags:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC4tagsSDySSypGSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "onFormOpen", + "printedName": "onFormOpen", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(() -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)onFormOpen", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10onFormOpenyycSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(() -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)onFormOpen", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10onFormOpenyycSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(() -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setOnFormOpen:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC10onFormOpenyycSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "onFormClose", + "printedName": "onFormClose", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(() -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)onFormClose", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC11onFormCloseyycSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(() -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)onFormClose", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC11onFormCloseyycSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(() -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "() -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setOnFormClose:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC11onFormCloseyycSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "onSubmitSuccess", + "printedName": "onSubmitSuccess", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(([Swift.String : Any]) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "([Swift.String : Any]) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)onSubmitSuccess", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15onSubmitSuccessySDySSypGcSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(([Swift.String : Any]) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "([Swift.String : Any]) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)onSubmitSuccess", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15onSubmitSuccessySDySSypGcSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(([Swift.String : Any]) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "([Swift.String : Any]) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setOnSubmitSuccess:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC15onSubmitSuccessySDySSypGcSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "onSubmitError", + "printedName": "onSubmitError", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((any Swift.Error) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(any Swift.Error) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)onSubmitError", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13onSubmitErrorys0G0_pcSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((any Swift.Error) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(any Swift.Error) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)onSubmitError", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13onSubmitErrorys0G0_pcSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((any Swift.Error) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(any Swift.Error) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setOnSubmitError:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC13onSubmitErrorys0G0_pcSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "configureTheme", + "printedName": "configureTheme", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)configureTheme", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC14configureThemeyAA0abcfD0CcSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)configureTheme", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC14configureThemeyAA0abcfD0CcSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setConfigureTheme:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC14configureThemeyAA0abcfD0CcSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "configureDarkTheme", + "printedName": "configureDarkTheme", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(py)configureDarkTheme", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC18configureDarkThemeyAA0abcgD0CcSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasInitialValue", + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)configureDarkTheme", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC18configureDarkThemeyAA0abcgD0CcSgvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "((Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void)?", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryUserFeedbackThemeConfiguration) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + } + ] + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)setConfigureDarkTheme:", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC18configureDarkThemeyAA0abcgD0CcSgvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackConfiguration", + "printedName": "Sentry.SentryUserFeedbackConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration(im)init", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackConfiguration", + "mangledName": "$s6Sentry0A25UserFeedbackConfigurationC", + "moduleName": "Sentry", + "intro_iOS": "13.0", + "declAttributes": [ + "Available", + "ObjCMembers", + "Available", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryProfileOptions", + "printedName": "SentryProfileOptions", + "children": [ + { + "kind": "TypeDecl", + "name": "SentryProfileLifecycle", + "printedName": "SentryProfileLifecycle", + "children": [ + { + "kind": "Var", + "name": "manual", + "printedName": "manual", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryProfileOptions.SentryProfileLifecycle.Type) -> Sentry.SentryProfileOptions.SentryProfileLifecycle", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO6manualyA2EmF", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO6manualyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "trace", + "printedName": "trace", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryProfileOptions.SentryProfileLifecycle.Type) -> Sentry.SentryProfileOptions.SentryProfileLifecycle", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO5traceyA2EmF", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO5traceyA2EmF", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueAESgSi_tcfc", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueAESgSi_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO8RawValuea", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO8RawValuea", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueSivp", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueSivp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueSivg", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO8rawValueSivg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + } + ], + "declKind": "Enum", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO", + "mangledName": "$s6Sentry0A14ProfileOptionsC0aB9LifecycleO", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, + { + "kind": "Var", + "name": "lifecycle", + "printedName": "lifecycle", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(py)lifecycle", + "mangledName": "$s6Sentry0A14ProfileOptionsC9lifecycleAC0aB9LifecycleOvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)lifecycle", + "mangledName": "$s6Sentry0A14ProfileOptionsC9lifecycleAC0aB9LifecycleOvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryProfileLifecycle", + "printedName": "Sentry.SentryProfileOptions.SentryProfileLifecycle", + "usr": "s:6Sentry0A14ProfileOptionsC0aB9LifecycleO" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)setLifecycle:", + "mangledName": "$s6Sentry0A14ProfileOptionsC9lifecycleAC0aB9LifecycleOvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "sessionSampleRate", + "printedName": "sessionSampleRate", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(py)sessionSampleRate", + "mangledName": "$s6Sentry0A14ProfileOptionsC17sessionSampleRateSfvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)sessionSampleRate", + "mangledName": "$s6Sentry0A14ProfileOptionsC17sessionSampleRateSfvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Float", + "printedName": "Swift.Float", + "usr": "s:Sf" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)setSessionSampleRate:", + "mangledName": "$s6Sentry0A14ProfileOptionsC17sessionSampleRateSfvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "profileAppStarts", + "printedName": "profileAppStarts", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(py)profileAppStarts", + "mangledName": "$s6Sentry0A14ProfileOptionsC16profileAppStartsSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)profileAppStarts", + "mangledName": "$s6Sentry0A14ProfileOptionsC16profileAppStartsSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)setProfileAppStarts:", + "mangledName": "$s6Sentry0A14ProfileOptionsC16profileAppStartsSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryProfileOptions", + "printedName": "Sentry.SentryProfileOptions", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions(im)init", + "mangledName": "$s6Sentry0A14ProfileOptionsCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryProfileOptions", + "mangledName": "$s6Sentry0A14ProfileOptionsC", + "moduleName": "Sentry", + "declAttributes": [ + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryId", + "printedName": "SentryId", + "children": [ + { + "kind": "Var", + "name": "empty", + "printedName": "empty", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryId(cpy)empty", + "mangledName": "$s6Sentry0A2IdC5emptyACvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryId(cm)empty", + "mangledName": "$s6Sentry0A2IdC5emptyACvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "sentryIdString", + "printedName": "sentryIdString", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryId(py)sentryIdString", + "mangledName": "$s6Sentry0A2IdC06sentryB6StringSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)sentryIdString", + "mangledName": "$s6Sentry0A2IdC06sentryB6StringSSvg", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)init", + "mangledName": "$s6Sentry0A2IdCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(uuid:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "UUID", + "printedName": "Foundation.UUID", + "usr": "s:10Foundation4UUIDV" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)initWithUuid:", + "mangledName": "$s6Sentry0A2IdC4uuidAC10Foundation4UUIDV_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithUuid:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(uuidString:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)initWithUUIDString:", + "mangledName": "$s6Sentry0A2IdC10uuidStringACSS_tcfc", + "moduleName": "Sentry", + "objc_name": "initWithUUIDString:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + }, + { + "kind": "Function", + "name": "isEqual", + "printedName": "isEqual(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Any?", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)isEqual:", + "mangledName": "$s6Sentry0A2IdC7isEqualySbypSgF", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "isEqual:", + "declAttributes": [ + "ObjC", + "Final", + "Override" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Var", + "name": "description", + "printedName": "description", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryId(py)description", + "mangledName": "$s6Sentry0A2IdC11descriptionSSvp", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "description", + "declAttributes": [ + "ObjC", + "Final", + "Override" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)description", + "mangledName": "$s6Sentry0A2IdC11descriptionSSvg", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "description", + "declAttributes": [ + "Final", + "ObjC", + "Override" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "hash", + "printedName": "hash", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryId(py)hash", + "mangledName": "$s6Sentry0A2IdC4hashSivp", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "hash", + "declAttributes": [ + "ObjC", + "Final", + "Override" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryId(im)hash", + "mangledName": "$s6Sentry0A2IdC4hashSivg", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "hash", + "declAttributes": [ + "Final", + "ObjC", + "Override" + ], + "accessorKind": "get" + } + ] + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryId", + "mangledName": "$s6Sentry0A2IdC", + "moduleName": "Sentry", + "declAttributes": [ + "Final", + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentrySDK", + "printedName": "SentrySDK", + "children": [ + { + "kind": "Var", + "name": "span", + "printedName": "span", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)span", + "mangledName": "$s6Sentry0A3SDKC4spanSo0A4Span_pSgvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "(any Sentry.Span)?", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)span", + "mangledName": "$s6Sentry0A3SDKC4spanSo0A4Span_pSgvgZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "isEnabled", + "printedName": "isEnabled", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)isEnabled", + "mangledName": "$s6Sentry0A3SDKC9isEnabledSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)isEnabled", + "mangledName": "$s6Sentry0A3SDKC9isEnabledSbvgZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "replay", + "printedName": "replay", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayApi", + "printedName": "Sentry.SentryReplayApi", + "usr": "c:objc(cs)SentryReplayApi" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)replay", + "mangledName": "$s6Sentry0A3SDKC6replaySo0A9ReplayApiCvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryReplayApi", + "printedName": "Sentry.SentryReplayApi", + "usr": "c:objc(cs)SentryReplayApi" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)replay", + "mangledName": "$s6Sentry0A3SDKC6replaySo0A9ReplayApiCvgZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "logger", + "printedName": "logger", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLogger", + "printedName": "Sentry.SentryLogger", + "usr": "c:@M@Sentry@objc(cs)SentryLogger" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)logger", + "mangledName": "$s6Sentry0A3SDKC6loggerAA0A6LoggerCvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLogger", + "printedName": "Sentry.SentryLogger", + "usr": "c:@M@Sentry@objc(cs)SentryLogger" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)logger", + "mangledName": "$s6Sentry0A3SDKC6loggerAA0A6LoggerCvgZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Function", + "name": "start", + "printedName": "start(options:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Options", + "printedName": "Sentry.Options", + "usr": "c:objc(cs)SentryOptions" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startWithOptions:", + "mangledName": "$s6Sentry0A3SDKC5start7optionsySo0A7OptionsC_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startWithOptions:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "start", + "printedName": "start(configureOptions:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Options) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Options", + "printedName": "Sentry.Options", + "usr": "c:objc(cs)SentryOptions" + } + ] + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startWithConfigureOptions:", + "mangledName": "$s6Sentry0A3SDKC5start16configureOptionsyySo0aE0Cc_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startWithConfigureOptions:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(event:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureEvent:", + "mangledName": "$s6Sentry0A3SDKC7capture5eventAA0A2IdCSo0A5EventC_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureEvent:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(event:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureEvent:withScope:", + "mangledName": "$s6Sentry0A3SDKC7capture5event5scopeAA0A2IdCSo0A5EventC_So0A5ScopeCtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureEvent:withScope:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(event:block:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Event", + "printedName": "Sentry.Event", + "usr": "c:objc(cs)SentryEvent" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ] + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureEvent:withScopeBlock:", + "mangledName": "$s6Sentry0A3SDKC7capture5event5blockAA0A2IdCSo0A5EventC_ySo0A5ScopeCctFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureEvent:withScopeBlock:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(name:operation:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startTransactionWithName:operation:", + "mangledName": "$s6Sentry0A3SDKC16startTransaction4name9operationSo0A4Span_pSS_SStFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startTransactionWithName:operation:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(name:operation:bindToScope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startTransactionWithName:operation:bindToScope:", + "mangledName": "$s6Sentry0A3SDKC16startTransaction4name9operation11bindToScopeSo0A4Span_pSS_SSSbtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startTransactionWithName:operation:bindToScope:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(transactionContext:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startTransactionWithContext:", + "mangledName": "$s6Sentry0A3SDKC16startTransaction18transactionContextSo0A4Span_pSo0adF0C_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startTransactionWithContext:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(transactionContext:bindToScope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startTransactionWithContext:bindToScope:", + "mangledName": "$s6Sentry0A3SDKC16startTransaction18transactionContext11bindToScopeSo0A4Span_pSo0adF0C_SbtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startTransactionWithContext:bindToScope:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(transactionContext:bindToScope:customSamplingContext:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startTransactionWithContext:bindToScope:customSamplingContext:", + "mangledName": "$s6Sentry0A3SDKC16startTransaction18transactionContext11bindToScope014customSamplingF0So0A4Span_pSo0adF0C_SbSDySSypGtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startTransactionWithContext:bindToScope:customSamplingContext:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startTransaction", + "printedName": "startTransaction(transactionContext:customSamplingContext:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Span", + "printedName": "any Sentry.Span", + "usr": "c:objc(pl)SentrySpan" + }, + { + "kind": "TypeNominal", + "name": "TransactionContext", + "printedName": "Sentry.TransactionContext", + "usr": "c:objc(cs)SentryTransactionContext" + }, + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Swift.String : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startTransactionWithContext:customSamplingContext:", + "mangledName": "$s6Sentry0A3SDKC16startTransaction18transactionContext014customSamplingF0So0A4Span_pSo0adF0C_SDySSypGtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "startTransactionWithContext:customSamplingContext:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(error:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureError:", + "mangledName": "$s6Sentry0A3SDKC7capture5errorAA0A2IdCs5Error_p_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureError:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(error:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureError:withScope:", + "mangledName": "$s6Sentry0A3SDKC7capture5error5scopeAA0A2IdCs5Error_p_So0A5ScopeCtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureError:withScope:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(error:block:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "Error", + "printedName": "any Swift.Error", + "usr": "s:s5ErrorP" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ] + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureError:withScopeBlock:", + "mangledName": "$s6Sentry0A3SDKC7capture5error5blockAA0A2IdCs5Error_p_ySo0A5ScopeCctFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureError:withScopeBlock:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(exception:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "NSException", + "printedName": "Foundation.NSException", + "usr": "c:objc(cs)NSException" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureException:", + "mangledName": "$s6Sentry0A3SDKC7capture9exceptionAA0A2IdCSo11NSExceptionC_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureException:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(exception:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "NSException", + "printedName": "Foundation.NSException", + "usr": "c:objc(cs)NSException" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureException:withScope:", + "mangledName": "$s6Sentry0A3SDKC7capture9exception5scopeAA0A2IdCSo11NSExceptionC_So0A5ScopeCtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureException:withScope:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(exception:block:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "NSException", + "printedName": "Foundation.NSException", + "usr": "c:objc(cs)NSException" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ] + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureException:withScopeBlock:", + "mangledName": "$s6Sentry0A3SDKC7capture9exception5blockAA0A2IdCSo11NSExceptionC_ySo0A5ScopeCctFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureException:withScopeBlock:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(message:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureMessage:", + "mangledName": "$s6Sentry0A3SDKC7capture7messageAA0A2IdCSS_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureMessage:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(message:scope:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureMessage:withScope:", + "mangledName": "$s6Sentry0A3SDKC7capture7message5scopeAA0A2IdCSS_So0A5ScopeCtFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureMessage:withScope:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(message:block:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryId", + "printedName": "Sentry.SentryId", + "usr": "c:@M@Sentry@objc(cs)SentryId" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ] + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureMessage:withScopeBlock:", + "mangledName": "$s6Sentry0A3SDKC7capture7message5blockAA0A2IdCSS_ySo0A5ScopeCctFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureMessage:withScopeBlock:", + "declAttributes": [ + "Final", + "ObjC", + "DiscardableResult" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "capture", + "printedName": "capture(feedback:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryFeedback", + "printedName": "Sentry.SentryFeedback", + "usr": "c:@M@Sentry@objc(cs)SentryFeedback" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)captureFeedback:", + "mangledName": "$s6Sentry0A3SDKC7capture8feedbackyAA0A8FeedbackC_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "captureFeedback:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Var", + "name": "feedback", + "printedName": "feedback", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackAPI", + "printedName": "Sentry.SentryFeedbackAPI", + "usr": "c:objc(cs)SentryFeedbackAPI" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)feedback", + "mangledName": "$s6Sentry0A3SDKC8feedbackSo0A11FeedbackAPICvpZ", + "moduleName": "Sentry", + "static": true, + "intro_iOS": "13.0", + "declAttributes": [ + "Final", + "ObjC", + "Available", + "HasStorage" + ], + "isLet": true, + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFeedbackAPI", + "printedName": "Sentry.SentryFeedbackAPI", + "usr": "c:objc(cs)SentryFeedbackAPI" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)feedback", + "mangledName": "$s6Sentry0A3SDKC8feedbackSo0A11FeedbackAPICvgZ", + "moduleName": "Sentry", + "static": true, + "implicit": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Function", + "name": "addBreadcrumb", + "printedName": "addBreadcrumb(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Breadcrumb", + "printedName": "Sentry.Breadcrumb", + "usr": "c:objc(cs)SentryBreadcrumb" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)addBreadcrumb:", + "mangledName": "$s6Sentry0A3SDKC13addBreadcrumbyySo0aD0CFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "addBreadcrumb:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "configureScope", + "printedName": "configureScope(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.Scope) -> Swift.Void", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + }, + { + "kind": "TypeNominal", + "name": "Scope", + "printedName": "Sentry.Scope", + "usr": "c:objc(cs)SentryScope" + } + ] + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)configureScope:", + "mangledName": "$s6Sentry0A3SDKC14configureScopeyyySo0aD0CcFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "configureScope:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Var", + "name": "crashedLastRun", + "printedName": "crashedLastRun", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)crashedLastRun", + "mangledName": "$s6Sentry0A3SDKC14crashedLastRunSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)crashedLastRun", + "mangledName": "$s6Sentry0A3SDKC14crashedLastRunSbvgZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "detectedStartUpCrash", + "printedName": "detectedStartUpCrash", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cpy)detectedStartUpCrash", + "mangledName": "$s6Sentry0A3SDKC20detectedStartUpCrashSbvpZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)detectedStartUpCrash", + "mangledName": "$s6Sentry0A3SDKC20detectedStartUpCrashSbvgZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Function", + "name": "setUser", + "printedName": "setUser(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.User?", + "children": [ + { + "kind": "TypeNominal", + "name": "User", + "printedName": "Sentry.User", + "usr": "c:objc(cs)SentryUser" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)setUser:", + "mangledName": "$s6Sentry0A3SDKC7setUseryySo0aD0CSgFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startSession", + "printedName": "startSession()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startSession", + "mangledName": "$s6Sentry0A3SDKC12startSessionyyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "endSession", + "printedName": "endSession()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)endSession", + "mangledName": "$s6Sentry0A3SDKC10endSessionyyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "crash", + "printedName": "crash()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)crash", + "mangledName": "$s6Sentry0A3SDKC5crashyyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "reportFullyDisplayed", + "printedName": "reportFullyDisplayed()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)reportFullyDisplayed", + "mangledName": "$s6Sentry0A3SDKC20reportFullyDisplayedyyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "pauseAppHangTracking", + "printedName": "pauseAppHangTracking()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)pauseAppHangTracking", + "mangledName": "$s6Sentry0A3SDKC20pauseAppHangTrackingyyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "resumeAppHangTracking", + "printedName": "resumeAppHangTracking()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)resumeAppHangTracking", + "mangledName": "$s6Sentry0A3SDKC21resumeAppHangTrackingyyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "flush", + "printedName": "flush(timeout:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNameAlias", + "name": "TimeInterval", + "printedName": "Foundation.TimeInterval", + "children": [ + { + "kind": "TypeNominal", + "name": "Double", + "printedName": "Swift.Double", + "usr": "s:Sd" + } + ] + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)flush:", + "mangledName": "$s6Sentry0A3SDKC5flush7timeoutySd_tFZ", + "moduleName": "Sentry", + "static": true, + "objc_name": "flush:", + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "close", + "printedName": "close()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)close", + "mangledName": "$s6Sentry0A3SDKC5closeyyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "startProfiler", + "printedName": "startProfiler()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)startProfiler", + "mangledName": "$s6Sentry0A3SDKC13startProfileryyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "stopProfiler", + "printedName": "stopProfiler()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(cm)stopProfiler", + "mangledName": "$s6Sentry0A3SDKC12stopProfileryyFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentrySDK", + "printedName": "Sentry.SentrySDK", + "usr": "c:@M@Sentry@objc(cs)SentrySDK" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentrySDK(im)init", + "mangledName": "$s6Sentry0A3SDKCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentrySDK", + "mangledName": "$s6Sentry0A3SDKC", + "moduleName": "Sentry", + "isOpen": true, + "declAttributes": [ + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryRedactViewHelper", + "printedName": "SentryRedactViewHelper", + "children": [ + { + "kind": "Function", + "name": "clipOutView", + "printedName": "clipOutView(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UIView", + "printedName": "UIKit.UIView", + "usr": "c:objc(cs)UIView" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryRedactViewHelper(cm)clipOutView:", + "mangledName": "$s6Sentry0A16RedactViewHelperC07clipOutC0yySo6UIViewCFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "maskSwiftUI", + "printedName": "maskSwiftUI(_:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UIView", + "printedName": "UIKit.UIView", + "usr": "c:objc(cs)UIView" + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@objc(cs)SentryRedactViewHelper(cm)maskSwiftUI:", + "mangledName": "$s6Sentry0A16RedactViewHelperC11maskSwiftUIyySo6UIViewCFZ", + "moduleName": "Sentry", + "static": true, + "declAttributes": [ + "Final", + "ObjC" + ], + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryRedactViewHelper", + "mangledName": "$s6Sentry0A16RedactViewHelperC", + "moduleName": "Sentry", + "declAttributes": [ + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "hasMissingDesignatedInitializers": true, + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryTransactionNameSource", + "printedName": "SentryTransactionNameSource", + "children": [ + { + "kind": "Var", + "name": "custom", + "printedName": "custom", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryTransactionNameSource.Type) -> Sentry.SentryTransactionNameSource", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryTransactionNameSource.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource@kSentryTransactionNameSourceCustom", + "mangledName": "$s6Sentry0A21TransactionNameSourceO6customyA2CmF", + "moduleName": "Sentry", + "objc_name": "kSentryTransactionNameSourceCustom", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "url", + "printedName": "url", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryTransactionNameSource.Type) -> Sentry.SentryTransactionNameSource", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryTransactionNameSource.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource@kSentryTransactionNameSourceUrl", + "mangledName": "$s6Sentry0A21TransactionNameSourceO3urlyA2CmF", + "moduleName": "Sentry", + "objc_name": "kSentryTransactionNameSourceUrl", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "route", + "printedName": "route", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryTransactionNameSource.Type) -> Sentry.SentryTransactionNameSource", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryTransactionNameSource.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource@kSentryTransactionNameSourceRoute", + "mangledName": "$s6Sentry0A21TransactionNameSourceO5routeyA2CmF", + "moduleName": "Sentry", + "objc_name": "kSentryTransactionNameSourceRoute", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "view", + "printedName": "view", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryTransactionNameSource.Type) -> Sentry.SentryTransactionNameSource", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryTransactionNameSource.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource@kSentryTransactionNameSourceView", + "mangledName": "$s6Sentry0A21TransactionNameSourceO4viewyA2CmF", + "moduleName": "Sentry", + "objc_name": "kSentryTransactionNameSourceView", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "component", + "printedName": "component", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryTransactionNameSource.Type) -> Sentry.SentryTransactionNameSource", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryTransactionNameSource.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource@kSentryTransactionNameSourceComponent", + "mangledName": "$s6Sentry0A21TransactionNameSourceO9componentyA2CmF", + "moduleName": "Sentry", + "objc_name": "kSentryTransactionNameSourceComponent", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "sourceTask", + "printedName": "sourceTask", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryTransactionNameSource.Type) -> Sentry.SentryTransactionNameSource", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryTransactionNameSource.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource@kSentryTransactionNameSourceTask", + "mangledName": "$s6Sentry0A21TransactionNameSourceO10sourceTaskyA2CmF", + "moduleName": "Sentry", + "objc_name": "kSentryTransactionNameSourceTask", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryTransactionNameSource?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryTransactionNameSource", + "printedName": "Sentry.SentryTransactionNameSource", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A21TransactionNameSourceO8rawValueACSgSi_tcfc", + "mangledName": "$s6Sentry0A21TransactionNameSourceO8rawValueACSgSi_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A21TransactionNameSourceO8RawValuea", + "mangledName": "$s6Sentry0A21TransactionNameSourceO8RawValuea", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A21TransactionNameSourceO8rawValueSivp", + "mangledName": "$s6Sentry0A21TransactionNameSourceO8rawValueSivp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A21TransactionNameSourceO8rawValueSivg", + "mangledName": "$s6Sentry0A21TransactionNameSourceO8rawValueSivg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentryTransactionNameSource", + "mangledName": "$s6Sentry0A21TransactionNameSourceO", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "enumRawTypeName": "Int", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryTransactionNameSource.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryRedactOptions", + "printedName": "SentryRedactOptions", + "children": [ + { + "kind": "Var", + "name": "maskAllText", + "printedName": "maskAllText", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions(py)maskAllText", + "mangledName": "$s6Sentry0A13RedactOptionsP11maskAllTextSbvp", + "moduleName": "Sentry", + "protocolReq": true, + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions(im)maskAllText", + "mangledName": "$s6Sentry0A13RedactOptionsP11maskAllTextSbvg", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "declAttributes": [ + "ObjC" + ], + "reqNewWitnessTableEntry": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskAllImages", + "printedName": "maskAllImages", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions(py)maskAllImages", + "mangledName": "$s6Sentry0A13RedactOptionsP13maskAllImagesSbvp", + "moduleName": "Sentry", + "protocolReq": true, + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions(im)maskAllImages", + "mangledName": "$s6Sentry0A13RedactOptionsP13maskAllImagesSbvg", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "declAttributes": [ + "ObjC" + ], + "reqNewWitnessTableEntry": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "maskedViewClasses", + "printedName": "maskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions(py)maskedViewClasses", + "mangledName": "$s6Sentry0A13RedactOptionsP17maskedViewClassesSayyXlXpGvp", + "moduleName": "Sentry", + "protocolReq": true, + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions(im)maskedViewClasses", + "mangledName": "$s6Sentry0A13RedactOptionsP17maskedViewClassesSayyXlXpGvg", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "declAttributes": [ + "ObjC" + ], + "reqNewWitnessTableEntry": true, + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "unmaskedViewClasses", + "printedName": "unmaskedViewClasses", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions(py)unmaskedViewClasses", + "mangledName": "$s6Sentry0A13RedactOptionsP19unmaskedViewClassesSayyXlXpGvp", + "moduleName": "Sentry", + "protocolReq": true, + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Array", + "printedName": "[Swift.AnyClass]", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyClass", + "printedName": "Swift.AnyClass", + "children": [ + { + "kind": "TypeNominal", + "name": "ExistentialMetatype", + "printedName": "any Swift.AnyObject.Type", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Swift.AnyObject", + "children": [ + { + "kind": "TypeNameAlias", + "name": "AnyObject", + "printedName": "Builtin.AnyObject", + "children": [ + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "AnyObject" + } + ] + } + ] + } + ] + } + ] + } + ], + "usr": "s:Sa" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions(im)unmaskedViewClasses", + "mangledName": "$s6Sentry0A13RedactOptionsP19unmaskedViewClassesSayyXlXpGvg", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "declAttributes": [ + "ObjC" + ], + "reqNewWitnessTableEntry": true, + "accessorKind": "get" + } + ] + } + ], + "declKind": "Protocol", + "usr": "c:@M@Sentry@objc(pl)SentryRedactOptions", + "mangledName": "$s6Sentry0A13RedactOptionsP", + "moduleName": "Sentry", + "genericSig": "", + "declAttributes": [ + "ObjC" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryLevel", + "printedName": "SentryLevel", + "children": [ + { + "kind": "Var", + "name": "none", + "printedName": "none", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLevel.Type) -> Sentry.SentryLevel", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLevel.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryLevel@kSentryLevelNone", + "mangledName": "$s6Sentry0A5LevelO4noneyA2CmF", + "moduleName": "Sentry", + "objc_name": "kSentryLevelNone", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "debug", + "printedName": "debug", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLevel.Type) -> Sentry.SentryLevel", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLevel.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryLevel@kSentryLevelDebug", + "mangledName": "$s6Sentry0A5LevelO5debugyA2CmF", + "moduleName": "Sentry", + "objc_name": "kSentryLevelDebug", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "info", + "printedName": "info", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLevel.Type) -> Sentry.SentryLevel", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLevel.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryLevel@kSentryLevelInfo", + "mangledName": "$s6Sentry0A5LevelO4infoyA2CmF", + "moduleName": "Sentry", + "objc_name": "kSentryLevelInfo", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "warning", + "printedName": "warning", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLevel.Type) -> Sentry.SentryLevel", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLevel.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryLevel@kSentryLevelWarning", + "mangledName": "$s6Sentry0A5LevelO7warningyA2CmF", + "moduleName": "Sentry", + "objc_name": "kSentryLevelWarning", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "error", + "printedName": "error", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLevel.Type) -> Sentry.SentryLevel", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLevel.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryLevel@kSentryLevelError", + "mangledName": "$s6Sentry0A5LevelO5erroryA2CmF", + "moduleName": "Sentry", + "objc_name": "kSentryLevelError", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Var", + "name": "fatal", + "printedName": "fatal", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryLevel.Type) -> Sentry.SentryLevel", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryLevel.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "c:@M@Sentry@E@SentryLevel@kSentryLevelFatal", + "mangledName": "$s6Sentry0A5LevelO5fatalyA2CmF", + "moduleName": "Sentry", + "objc_name": "kSentryLevelFatal", + "declAttributes": [ + "ObjC" + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryLevel?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryLevel", + "printedName": "Sentry.SentryLevel", + "usr": "c:@M@Sentry@E@SentryLevel" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A5LevelO8rawValueACSgSu_tcfc", + "mangledName": "$s6Sentry0A5LevelO8rawValueACSgSu_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A5LevelO8RawValuea", + "mangledName": "$s6Sentry0A5LevelO8RawValuea", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A5LevelO8rawValueSuvp", + "mangledName": "$s6Sentry0A5LevelO8rawValueSuvp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A5LevelO8rawValueSuvg", + "mangledName": "$s6Sentry0A5LevelO8rawValueSuvg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "description", + "printedName": "description", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A5LevelO11descriptionSSvp", + "mangledName": "$s6Sentry0A5LevelO11descriptionSSvp", + "moduleName": "Sentry", + "isFromExtension": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A5LevelO11descriptionSSvg", + "mangledName": "$s6Sentry0A5LevelO11descriptionSSvg", + "moduleName": "Sentry", + "isFromExtension": true, + "accessorKind": "get" + } + ] + } + ], + "declKind": "Enum", + "usr": "c:@M@Sentry@E@SentryLevel", + "mangledName": "$s6Sentry0A5LevelO", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "enumRawTypeName": "UInt", + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryLevel.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt", + "printedName": "Swift.UInt", + "usr": "s:Su" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryUIViewControllerDescriptor", + "printedName": "SentryUIViewControllerDescriptor", + "children": [ + { + "kind": "Var", + "name": "sentryName", + "printedName": "sentryName", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(pl)SentryUIViewControllerDescriptor(py)sentryName", + "mangledName": "$s6Sentry0A26UIViewControllerDescriptorP10sentryNameSSvp", + "moduleName": "Sentry", + "protocolReq": true, + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(pl)SentryUIViewControllerDescriptor(im)sentryName", + "mangledName": "$s6Sentry0A26UIViewControllerDescriptorP10sentryNameSSvg", + "moduleName": "Sentry", + "genericSig": "", + "protocolReq": true, + "declAttributes": [ + "ObjC" + ], + "reqNewWitnessTableEntry": true, + "accessorKind": "get" + } + ] + } + ], + "declKind": "Protocol", + "usr": "c:@M@Sentry@objc(pl)SentryUIViewControllerDescriptor", + "mangledName": "$s6Sentry0A26UIViewControllerDescriptorP", + "moduleName": "Sentry", + "genericSig": "", + "declAttributes": [ + "ObjC" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryExperimentalOptions", + "printedName": "SentryExperimentalOptions", + "children": [ + { + "kind": "Var", + "name": "enableDataSwizzling", + "printedName": "enableDataSwizzling", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(py)enableDataSwizzling", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC19enableDataSwizzlingSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)enableDataSwizzling", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC19enableDataSwizzlingSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)setEnableDataSwizzling:", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC19enableDataSwizzlingSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableFileManagerSwizzling", + "printedName": "enableFileManagerSwizzling", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(py)enableFileManagerSwizzling", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC26enableFileManagerSwizzlingSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)enableFileManagerSwizzling", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC26enableFileManagerSwizzlingSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)setEnableFileManagerSwizzling:", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC26enableFileManagerSwizzlingSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableUnhandledCPPExceptionsV2", + "printedName": "enableUnhandledCPPExceptionsV2", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(py)enableUnhandledCPPExceptionsV2", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC30enableUnhandledCPPExceptionsV2Sbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)enableUnhandledCPPExceptionsV2", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC30enableUnhandledCPPExceptionsV2Sbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)setEnableUnhandledCPPExceptionsV2:", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC30enableUnhandledCPPExceptionsV2Sbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "enableLogs", + "printedName": "enableLogs", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(py)enableLogs", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC10enableLogsSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)enableLogs", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC10enableLogsSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)setEnableLogs:", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC10enableLogsSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryExperimentalOptions", + "printedName": "Sentry.SentryExperimentalOptions", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions(im)init", + "mangledName": "$s6Sentry0A19ExperimentalOptionsCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryExperimentalOptions", + "mangledName": "$s6Sentry0A19ExperimentalOptionsC", + "moduleName": "Sentry", + "declAttributes": [ + "ObjCMembers", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "SentryUserFeedbackThemeConfiguration", + "children": [ + { + "kind": "Var", + "name": "fontFamily", + "printedName": "fontFamily", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(py)fontFamily", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC10fontFamilySSSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)fontFamily", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC10fontFamilySSSgvg", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)setFontFamily:", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC10fontFamilySSSgvs", + "moduleName": "Sentry", + "objc_name": "setFontFamily:", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "foreground", + "printedName": "foreground", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(py)foreground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC10foregroundSo7UIColorCvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)foreground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC10foregroundSo7UIColorCvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)setForeground:", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC10foregroundSo7UIColorCvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "background", + "printedName": "background", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(py)background", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC10backgroundSo7UIColorCvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)background", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC10backgroundSo7UIColorCvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)setBackground:", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC10backgroundSo7UIColorCvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "submitForeground", + "printedName": "submitForeground", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(py)submitForeground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC16submitForegroundSo7UIColorCvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)submitForeground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC16submitForegroundSo7UIColorCvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)setSubmitForeground:", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC16submitForegroundSo7UIColorCvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "submitBackground", + "printedName": "submitBackground", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(py)submitBackground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC16submitBackgroundSo7UIColorCvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)submitBackground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC16submitBackgroundSo7UIColorCvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)setSubmitBackground:", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC16submitBackgroundSo7UIColorCvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "buttonForeground", + "printedName": "buttonForeground", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(py)buttonForeground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC16buttonForegroundSo7UIColorCvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)buttonForeground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC16buttonForegroundSo7UIColorCvg", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)setButtonForeground:", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC16buttonForegroundSo7UIColorCvs", + "moduleName": "Sentry", + "objc_name": "setButtonForeground:", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "buttonBackground", + "printedName": "buttonBackground", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(py)buttonBackground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC16buttonBackgroundSo7UIColorCvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)buttonBackground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC16buttonBackgroundSo7UIColorCvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)setButtonBackground:", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC16buttonBackgroundSo7UIColorCvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "errorColor", + "printedName": "errorColor", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(py)errorColor", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC10errorColorSo7UIColorCvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)errorColor", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC10errorColorSo7UIColorCvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)setErrorColor:", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC10errorColorSo7UIColorCvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryFormElementOutlineStyle", + "printedName": "SentryFormElementOutlineStyle", + "children": [ + { + "kind": "Var", + "name": "color", + "printedName": "color", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC5colorSo7UIColorCvp", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC5colorSo7UIColorCvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC5colorSo7UIColorCvg", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC5colorSo7UIColorCvg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC5colorSo7UIColorCvs", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC5colorSo7UIColorCvs", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "cornerRadius", + "printedName": "cornerRadius", + "children": [ + { + "kind": "TypeNominal", + "name": "CGFloat", + "printedName": "CoreGraphics.CGFloat", + "usr": "s:14CoreFoundation7CGFloatV" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC12cornerRadius14CoreFoundation7CGFloatVvp", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC12cornerRadius12CoreGraphics7CGFloatVvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "CGFloat", + "printedName": "CoreGraphics.CGFloat", + "usr": "s:14CoreFoundation7CGFloatV" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC12cornerRadius14CoreFoundation7CGFloatVvg", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC12cornerRadius12CoreGraphics7CGFloatVvg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "CGFloat", + "printedName": "CoreGraphics.CGFloat", + "usr": "s:14CoreFoundation7CGFloatV" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC12cornerRadius14CoreFoundation7CGFloatVvs", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC12cornerRadius12CoreGraphics7CGFloatVvs", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "outlineWidth", + "printedName": "outlineWidth", + "children": [ + { + "kind": "TypeNominal", + "name": "CGFloat", + "printedName": "CoreGraphics.CGFloat", + "usr": "s:14CoreFoundation7CGFloatV" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC12outlineWidth14CoreFoundation7CGFloatVvp", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC12outlineWidth12CoreGraphics7CGFloatVvp", + "moduleName": "Sentry", + "declAttributes": [ + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "CGFloat", + "printedName": "CoreGraphics.CGFloat", + "usr": "s:14CoreFoundation7CGFloatV" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC12outlineWidth14CoreFoundation7CGFloatVvg", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC12outlineWidth12CoreGraphics7CGFloatVvg", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "CGFloat", + "printedName": "CoreGraphics.CGFloat", + "usr": "s:14CoreFoundation7CGFloatV" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC12outlineWidth14CoreFoundation7CGFloatVvs", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC12outlineWidth12CoreGraphics7CGFloatVvs", + "moduleName": "Sentry", + "implicit": true, + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(color:cornerRadius:outlineWidth:)", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFormElementOutlineStyle", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration.SentryFormElementOutlineStyle", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC" + }, + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "hasDefaultArg": true, + "usr": "c:objc(cs)UIColor" + }, + { + "kind": "TypeNominal", + "name": "CGFloat", + "printedName": "CoreGraphics.CGFloat", + "hasDefaultArg": true, + "usr": "s:14CoreFoundation7CGFloatV" + }, + { + "kind": "TypeNominal", + "name": "CGFloat", + "printedName": "CoreGraphics.CGFloat", + "hasDefaultArg": true, + "usr": "s:14CoreFoundation7CGFloatV" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC5color12cornerRadius12outlineWidthAESo7UIColorC_14CoreFoundation7CGFloatVAMtcfc", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC5color12cornerRadius12outlineWidthAESo7UIColorC_12CoreGraphics7CGFloatVAMtcfc", + "moduleName": "Sentry", + "objc_name": "initWithColor:cornerRadius:outlineWidth:", + "declAttributes": [ + "ObjC" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "Var", + "name": "outlineStyle", + "printedName": "outlineStyle", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFormElementOutlineStyle", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration.SentryFormElementOutlineStyle", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(py)outlineStyle", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC12outlineStyleAC0a18FormElementOutlineG0Cvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryFormElementOutlineStyle", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration.SentryFormElementOutlineStyle", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)outlineStyle", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC12outlineStyleAC0a18FormElementOutlineG0Cvg", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "SentryFormElementOutlineStyle", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration.SentryFormElementOutlineStyle", + "usr": "s:6Sentry0A30UserFeedbackThemeConfigurationC0A23FormElementOutlineStyleC" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)setOutlineStyle:", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC12outlineStyleAC0a18FormElementOutlineG0Cvs", + "moduleName": "Sentry", + "objc_name": "setOutlineStyle:", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "inputBackground", + "printedName": "inputBackground", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(py)inputBackground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC15inputBackgroundSo7UIColorCvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)inputBackground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC15inputBackgroundSo7UIColorCvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)setInputBackground:", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC15inputBackgroundSo7UIColorCvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "inputForeground", + "printedName": "inputForeground", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(py)inputForeground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC15inputForegroundSo7UIColorCvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)inputForeground", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC15inputForegroundSo7UIColorCvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UIColor", + "printedName": "UIKit.UIColor", + "usr": "c:objc(cs)UIColor" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)setInputForeground:", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC15inputForegroundSo7UIColorCvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackThemeConfiguration", + "printedName": "Sentry.SentryUserFeedbackThemeConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration(im)init", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackThemeConfiguration", + "mangledName": "$s6Sentry0A30UserFeedbackThemeConfigurationC", + "moduleName": "Sentry", + "intro_iOS": "13.0", + "declAttributes": [ + "Available", + "ObjCMembers", + "Available", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryUserFeedbackWidgetConfiguration", + "printedName": "SentryUserFeedbackWidgetConfiguration", + "children": [ + { + "kind": "Var", + "name": "autoInject", + "printedName": "autoInject", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(py)autoInject", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC10autoInjectSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)autoInject", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC10autoInjectSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)setAutoInject:", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC10autoInjectSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "labelText", + "printedName": "labelText", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(py)labelText", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC9labelTextSSSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)labelText", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC9labelTextSSSgvg", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)setLabelText:", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC9labelTextSSSgvs", + "moduleName": "Sentry", + "objc_name": "setLabelText:", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "showIcon", + "printedName": "showIcon", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(py)showIcon", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC8showIconSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)showIcon", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC8showIconSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)setShowIcon:", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC8showIconSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "widgetAccessibilityLabel", + "printedName": "widgetAccessibilityLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(py)widgetAccessibilityLabel", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC24widgetAccessibilityLabelSSSgvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)widgetAccessibilityLabel", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC24widgetAccessibilityLabelSSSgvg", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Swift.String?", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "usr": "s:Sq" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)setWidgetAccessibilityLabel:", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC24widgetAccessibilityLabelSSSgvs", + "moduleName": "Sentry", + "objc_name": "setWidgetAccessibilityLabel:", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "windowLevel", + "printedName": "windowLevel", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "UIKit.UIWindow.Level", + "usr": "c:@T@UIWindowLevel" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(py)windowLevel", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC11windowLevelSo08UIWindowG0avp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "UIKit.UIWindow.Level", + "usr": "c:@T@UIWindowLevel" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)windowLevel", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC11windowLevelSo08UIWindowG0avg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Level", + "printedName": "UIKit.UIWindow.Level", + "usr": "c:@T@UIWindowLevel" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)setWindowLevel:", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC11windowLevelSo08UIWindowG0avs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "location", + "printedName": "location", + "children": [ + { + "kind": "TypeNominal", + "name": "NSDirectionalRectEdge", + "printedName": "UIKit.NSDirectionalRectEdge", + "usr": "c:@E@NSDirectionalRectEdge" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(py)location", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC8locationSo21NSDirectionalRectEdgeVvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "NSDirectionalRectEdge", + "printedName": "UIKit.NSDirectionalRectEdge", + "usr": "c:@E@NSDirectionalRectEdge" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)location", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC8locationSo21NSDirectionalRectEdgeVvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "NSDirectionalRectEdge", + "printedName": "UIKit.NSDirectionalRectEdge", + "usr": "c:@E@NSDirectionalRectEdge" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)setLocation:", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC8locationSo21NSDirectionalRectEdgeVvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "layoutUIOffset", + "printedName": "layoutUIOffset", + "children": [ + { + "kind": "TypeNominal", + "name": "UIOffset", + "printedName": "UIKit.UIOffset", + "usr": "c:@S@UIOffset" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(py)layoutUIOffset", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC14layoutUIOffsetSo0G0Vvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "UIOffset", + "printedName": "UIKit.UIOffset", + "usr": "c:@S@UIOffset" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)layoutUIOffset", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC14layoutUIOffsetSo0G0Vvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "UIOffset", + "printedName": "UIKit.UIOffset", + "usr": "c:@S@UIOffset" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)setLayoutUIOffset:", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC14layoutUIOffsetSo0G0Vvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackWidgetConfiguration", + "printedName": "Sentry.SentryUserFeedbackWidgetConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration(im)init", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackWidgetConfiguration", + "mangledName": "$s6Sentry0A31UserFeedbackWidgetConfigurationC", + "moduleName": "Sentry", + "intro_iOS": "13.0", + "declAttributes": [ + "Available", + "ObjCMembers", + "Available", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryRedactRegionType", + "printedName": "SentryRedactRegionType", + "children": [ + { + "kind": "Var", + "name": "redact", + "printedName": "redact", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryRedactRegionType.Type) -> Sentry.SentryRedactRegionType", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRedactRegionType", + "printedName": "Sentry.SentryRedactRegionType", + "usr": "s:6Sentry0A16RedactRegionTypeO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryRedactRegionType.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRedactRegionType", + "printedName": "Sentry.SentryRedactRegionType", + "usr": "s:6Sentry0A16RedactRegionTypeO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A16RedactRegionTypeO6redactyA2CmF", + "mangledName": "$s6Sentry0A16RedactRegionTypeO6redactyA2CmF", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "clipOut", + "printedName": "clipOut", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryRedactRegionType.Type) -> Sentry.SentryRedactRegionType", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRedactRegionType", + "printedName": "Sentry.SentryRedactRegionType", + "usr": "s:6Sentry0A16RedactRegionTypeO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryRedactRegionType.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRedactRegionType", + "printedName": "Sentry.SentryRedactRegionType", + "usr": "s:6Sentry0A16RedactRegionTypeO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A16RedactRegionTypeO7clipOutyA2CmF", + "mangledName": "$s6Sentry0A16RedactRegionTypeO7clipOutyA2CmF", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "clipBegin", + "printedName": "clipBegin", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryRedactRegionType.Type) -> Sentry.SentryRedactRegionType", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRedactRegionType", + "printedName": "Sentry.SentryRedactRegionType", + "usr": "s:6Sentry0A16RedactRegionTypeO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryRedactRegionType.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRedactRegionType", + "printedName": "Sentry.SentryRedactRegionType", + "usr": "s:6Sentry0A16RedactRegionTypeO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A16RedactRegionTypeO9clipBeginyA2CmF", + "mangledName": "$s6Sentry0A16RedactRegionTypeO9clipBeginyA2CmF", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "clipEnd", + "printedName": "clipEnd", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryRedactRegionType.Type) -> Sentry.SentryRedactRegionType", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRedactRegionType", + "printedName": "Sentry.SentryRedactRegionType", + "usr": "s:6Sentry0A16RedactRegionTypeO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryRedactRegionType.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRedactRegionType", + "printedName": "Sentry.SentryRedactRegionType", + "usr": "s:6Sentry0A16RedactRegionTypeO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A16RedactRegionTypeO7clipEndyA2CmF", + "mangledName": "$s6Sentry0A16RedactRegionTypeO7clipEndyA2CmF", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "redactSwiftUI", + "printedName": "redactSwiftUI", + "children": [ + { + "kind": "TypeFunc", + "name": "Function", + "printedName": "(Sentry.SentryRedactRegionType.Type) -> Sentry.SentryRedactRegionType", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRedactRegionType", + "printedName": "Sentry.SentryRedactRegionType", + "usr": "s:6Sentry0A16RedactRegionTypeO" + }, + { + "kind": "TypeNominal", + "name": "Metatype", + "printedName": "Sentry.SentryRedactRegionType.Type", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRedactRegionType", + "printedName": "Sentry.SentryRedactRegionType", + "usr": "s:6Sentry0A16RedactRegionTypeO" + } + ] + } + ] + } + ], + "declKind": "EnumElement", + "usr": "s:6Sentry0A16RedactRegionTypeO13redactSwiftUIyA2CmF", + "mangledName": "$s6Sentry0A16RedactRegionTypeO13redactSwiftUIyA2CmF", + "moduleName": "Sentry" + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init(rawValue:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Sentry.SentryRedactRegionType?", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryRedactRegionType", + "printedName": "Sentry.SentryRedactRegionType", + "usr": "s:6Sentry0A16RedactRegionTypeO" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Constructor", + "usr": "s:6Sentry0A16RedactRegionTypeO8rawValueACSgSS_tcfc", + "mangledName": "$s6Sentry0A16RedactRegionTypeO8rawValueACSgSS_tcfc", + "moduleName": "Sentry", + "init_kind": "Designated" + }, + { + "kind": "TypeAlias", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "TypeAlias", + "usr": "s:6Sentry0A16RedactRegionTypeO8RawValuea", + "mangledName": "$s6Sentry0A16RedactRegionTypeO8RawValuea", + "moduleName": "Sentry" + }, + { + "kind": "Var", + "name": "rawValue", + "printedName": "rawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "s:6Sentry0A16RedactRegionTypeO8rawValueSSvp", + "mangledName": "$s6Sentry0A16RedactRegionTypeO8rawValueSSvp", + "moduleName": "Sentry", + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "s:6Sentry0A16RedactRegionTypeO8rawValueSSvg", + "mangledName": "$s6Sentry0A16RedactRegionTypeO8rawValueSSvg", + "moduleName": "Sentry", + "accessorKind": "get" + } + ] + } + ], + "declKind": "Enum", + "usr": "s:6Sentry0A16RedactRegionTypeO", + "mangledName": "$s6Sentry0A16RedactRegionTypeO", + "moduleName": "Sentry", + "enumRawTypeName": "String", + "conformances": [ + { + "kind": "Conformance", + "name": "Decodable", + "printedName": "Decodable", + "usr": "s:Se", + "mangledName": "$sSe" + }, + { + "kind": "Conformance", + "name": "Encodable", + "printedName": "Encodable", + "usr": "s:SE", + "mangledName": "$sSE" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RawRepresentable", + "printedName": "RawRepresentable", + "children": [ + { + "kind": "TypeWitness", + "name": "RawValue", + "printedName": "RawValue", + "children": [ + { + "kind": "TypeNameAlias", + "name": "RawValue", + "printedName": "Sentry.SentryRedactRegionType.RawValue", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ] + } + ] + } + ], + "usr": "s:SY", + "mangledName": "$sSY" + } + ] + }, + { + "kind": "TypeDecl", + "name": "SentryUserFeedbackFormConfiguration", + "printedName": "SentryUserFeedbackFormConfiguration", + "children": [ + { + "kind": "Var", + "name": "useSentryUser", + "printedName": "useSentryUser", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)useSentryUser", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC03useaB0Sbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)useSentryUser", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC03useaB0Sbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setUseSentryUser:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC03useaB0Sbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "showBranding", + "printedName": "showBranding", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)showBranding", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC12showBrandingSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)showBranding", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC12showBrandingSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setShowBranding:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC12showBrandingSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "formTitle", + "printedName": "formTitle", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)formTitle", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC9formTitleSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)formTitle", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC9formTitleSSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setFormTitle:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC9formTitleSSvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "messageLabel", + "printedName": "messageLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)messageLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC12messageLabelSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)messageLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC12messageLabelSSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setMessageLabel:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC12messageLabelSSvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "messagePlaceholder", + "printedName": "messagePlaceholder", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)messagePlaceholder", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC18messagePlaceholderSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)messagePlaceholder", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC18messagePlaceholderSSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setMessagePlaceholder:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC18messagePlaceholderSSvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "messageTextViewAccessibilityLabel", + "printedName": "messageTextViewAccessibilityLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)messageTextViewAccessibilityLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC33messageTextViewAccessibilityLabelSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)messageTextViewAccessibilityLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC33messageTextViewAccessibilityLabelSSvg", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setMessageTextViewAccessibilityLabel:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC33messageTextViewAccessibilityLabelSSvs", + "moduleName": "Sentry", + "objc_name": "setMessageTextViewAccessibilityLabel:", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "isRequiredLabel", + "printedName": "isRequiredLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)isRequiredLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC15isRequiredLabelSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)isRequiredLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC15isRequiredLabelSSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setIsRequiredLabel:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC15isRequiredLabelSSvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "removeScreenshotButtonLabel", + "printedName": "removeScreenshotButtonLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)removeScreenshotButtonLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC27removeScreenshotButtonLabelSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)removeScreenshotButtonLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC27removeScreenshotButtonLabelSSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setRemoveScreenshotButtonLabel:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC27removeScreenshotButtonLabelSSvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "removeScreenshotButtonAccessibilityLabel", + "printedName": "removeScreenshotButtonAccessibilityLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)removeScreenshotButtonAccessibilityLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC40removeScreenshotButtonAccessibilityLabelSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)removeScreenshotButtonAccessibilityLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC40removeScreenshotButtonAccessibilityLabelSSvg", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setRemoveScreenshotButtonAccessibilityLabel:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC40removeScreenshotButtonAccessibilityLabelSSvs", + "moduleName": "Sentry", + "objc_name": "setRemoveScreenshotButtonAccessibilityLabel:", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "isNameRequired", + "printedName": "isNameRequired", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)isNameRequired", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC14isNameRequiredSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)isNameRequired", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC14isNameRequiredSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setIsNameRequired:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC14isNameRequiredSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "showName", + "printedName": "showName", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)showName", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC8showNameSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)showName", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC8showNameSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setShowName:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC8showNameSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "nameLabel", + "printedName": "nameLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)nameLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC9nameLabelSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)nameLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC9nameLabelSSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setNameLabel:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC9nameLabelSSvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "namePlaceholder", + "printedName": "namePlaceholder", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)namePlaceholder", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC15namePlaceholderSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)namePlaceholder", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC15namePlaceholderSSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setNamePlaceholder:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC15namePlaceholderSSvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "nameTextFieldAccessibilityLabel", + "printedName": "nameTextFieldAccessibilityLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)nameTextFieldAccessibilityLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC31nameTextFieldAccessibilityLabelSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)nameTextFieldAccessibilityLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC31nameTextFieldAccessibilityLabelSSvg", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setNameTextFieldAccessibilityLabel:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC31nameTextFieldAccessibilityLabelSSvs", + "moduleName": "Sentry", + "objc_name": "setNameTextFieldAccessibilityLabel:", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "isEmailRequired", + "printedName": "isEmailRequired", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)isEmailRequired", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC15isEmailRequiredSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)isEmailRequired", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC15isEmailRequiredSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setIsEmailRequired:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC15isEmailRequiredSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "showEmail", + "printedName": "showEmail", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)showEmail", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC9showEmailSbvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)showEmail", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC9showEmailSbvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setShowEmail:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC9showEmailSbvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "emailLabel", + "printedName": "emailLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)emailLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC10emailLabelSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)emailLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC10emailLabelSSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setEmailLabel:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC10emailLabelSSvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "emailPlaceholder", + "printedName": "emailPlaceholder", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)emailPlaceholder", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC16emailPlaceholderSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)emailPlaceholder", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC16emailPlaceholderSSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setEmailPlaceholder:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC16emailPlaceholderSSvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "emailTextFieldAccessibilityLabel", + "printedName": "emailTextFieldAccessibilityLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)emailTextFieldAccessibilityLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC32emailTextFieldAccessibilityLabelSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)emailTextFieldAccessibilityLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC32emailTextFieldAccessibilityLabelSSvg", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setEmailTextFieldAccessibilityLabel:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC32emailTextFieldAccessibilityLabelSSvs", + "moduleName": "Sentry", + "objc_name": "setEmailTextFieldAccessibilityLabel:", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "submitButtonLabel", + "printedName": "submitButtonLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)submitButtonLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC17submitButtonLabelSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)submitButtonLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC17submitButtonLabelSSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setSubmitButtonLabel:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC17submitButtonLabelSSvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "submitButtonAccessibilityLabel", + "printedName": "submitButtonAccessibilityLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)submitButtonAccessibilityLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC30submitButtonAccessibilityLabelSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)submitButtonAccessibilityLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC30submitButtonAccessibilityLabelSSvg", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setSubmitButtonAccessibilityLabel:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC30submitButtonAccessibilityLabelSSvs", + "moduleName": "Sentry", + "objc_name": "setSubmitButtonAccessibilityLabel:", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "cancelButtonLabel", + "printedName": "cancelButtonLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)cancelButtonLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC17cancelButtonLabelSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC", + "HasStorage" + ], + "hasStorage": true, + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)cancelButtonLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC17cancelButtonLabelSSvg", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setCancelButtonLabel:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC17cancelButtonLabelSSvs", + "moduleName": "Sentry", + "implicit": true, + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Var", + "name": "cancelButtonAccessibilityLabel", + "printedName": "cancelButtonAccessibilityLabel", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Var", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(py)cancelButtonAccessibilityLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC30cancelButtonAccessibilityLabelSSvp", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)cancelButtonAccessibilityLabel", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC30cancelButtonAccessibilityLabelSSvg", + "moduleName": "Sentry", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "get" + }, + { + "kind": "Accessor", + "name": "Set", + "printedName": "Set()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Accessor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)setCancelButtonAccessibilityLabel:", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC30cancelButtonAccessibilityLabelSSvs", + "moduleName": "Sentry", + "objc_name": "setCancelButtonAccessibilityLabel:", + "declAttributes": [ + "ObjC" + ], + "accessorKind": "set" + } + ] + }, + { + "kind": "Constructor", + "name": "init", + "printedName": "init()", + "children": [ + { + "kind": "TypeNominal", + "name": "SentryUserFeedbackFormConfiguration", + "printedName": "Sentry.SentryUserFeedbackFormConfiguration", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration" + } + ], + "declKind": "Constructor", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration(im)init", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationCACycfc", + "moduleName": "Sentry", + "overriding": true, + "objc_name": "init", + "declAttributes": [ + "ObjC", + "Dynamic", + "Override" + ], + "init_kind": "Designated" + } + ], + "declKind": "Class", + "usr": "c:@M@Sentry@objc(cs)SentryUserFeedbackFormConfiguration", + "mangledName": "$s6Sentry0A29UserFeedbackFormConfigurationC", + "moduleName": "Sentry", + "intro_iOS": "13.0", + "declAttributes": [ + "Available", + "ObjCMembers", + "Available", + "ObjC" + ], + "superclassUsr": "c:objc(cs)NSObject", + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "Var", + "name": "SENTRY_HAS_METRIC_KIT", + "printedName": "SENTRY_HAS_METRIC_KIT", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Var", + "usr": "c:@macro@SENTRY_HAS_METRIC_KIT", + "moduleName": "Sentry", + "declAttributes": [ + "Nonisolated" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Accessor", + "usr": "s:SC21SENTRY_HAS_METRIC_KITs5Int32Vvg", + "mangledName": "$sSC21SENTRY_HAS_METRIC_KITs5Int32Vvg", + "moduleName": "Sentry", + "declAttributes": [ + "Transparent" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "SENTRY_HAS_REACHABILITY", + "printedName": "SENTRY_HAS_REACHABILITY", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Var", + "usr": "c:@macro@SENTRY_HAS_REACHABILITY", + "moduleName": "Sentry", + "declAttributes": [ + "Nonisolated" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Accessor", + "usr": "s:SC23SENTRY_HAS_REACHABILITYs5Int32Vvg", + "mangledName": "$sSC23SENTRY_HAS_REACHABILITYs5Int32Vvg", + "moduleName": "Sentry", + "declAttributes": [ + "Transparent" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "SENTRY_HAS_UIKIT", + "printedName": "SENTRY_HAS_UIKIT", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Var", + "usr": "c:@macro@SENTRY_HAS_UIKIT", + "moduleName": "Sentry", + "declAttributes": [ + "Nonisolated" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Accessor", + "usr": "s:SC16SENTRY_HAS_UIKITs5Int32Vvg", + "mangledName": "$sSC16SENTRY_HAS_UIKITs5Int32Vvg", + "moduleName": "Sentry", + "declAttributes": [ + "Transparent" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "SENTRY_TARGET_MACOS", + "printedName": "SENTRY_TARGET_MACOS", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Var", + "usr": "c:@macro@SENTRY_TARGET_MACOS", + "moduleName": "Sentry", + "declAttributes": [ + "Nonisolated" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Accessor", + "usr": "s:SC19SENTRY_TARGET_MACOSs5Int32Vvg", + "mangledName": "$sSC19SENTRY_TARGET_MACOSs5Int32Vvg", + "moduleName": "Sentry", + "declAttributes": [ + "Transparent" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "SENTRY_TARGET_MACOS_HAS_UI", + "printedName": "SENTRY_TARGET_MACOS_HAS_UI", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Var", + "usr": "c:@macro@SENTRY_TARGET_MACOS_HAS_UI", + "moduleName": "Sentry", + "declAttributes": [ + "Nonisolated" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Accessor", + "usr": "s:SC26SENTRY_TARGET_MACOS_HAS_UIs5Int32Vvg", + "mangledName": "$sSC26SENTRY_TARGET_MACOS_HAS_UIs5Int32Vvg", + "moduleName": "Sentry", + "declAttributes": [ + "Transparent" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "SENTRY_TARGET_PROFILING_SUPPORTED", + "printedName": "SENTRY_TARGET_PROFILING_SUPPORTED", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Var", + "usr": "c:@macro@SENTRY_TARGET_PROFILING_SUPPORTED", + "moduleName": "Sentry", + "declAttributes": [ + "Nonisolated" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Accessor", + "usr": "s:SC33SENTRY_TARGET_PROFILING_SUPPORTEDs5Int32Vvg", + "mangledName": "$sSC33SENTRY_TARGET_PROFILING_SUPPORTEDs5Int32Vvg", + "moduleName": "Sentry", + "declAttributes": [ + "Transparent" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "SENTRY_TARGET_REPLAY_SUPPORTED", + "printedName": "SENTRY_TARGET_REPLAY_SUPPORTED", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Var", + "usr": "c:@macro@SENTRY_TARGET_REPLAY_SUPPORTED", + "moduleName": "Sentry", + "declAttributes": [ + "Nonisolated" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Accessor", + "usr": "s:SC30SENTRY_TARGET_REPLAY_SUPPORTEDs5Int32Vvg", + "mangledName": "$sSC30SENTRY_TARGET_REPLAY_SUPPORTEDs5Int32Vvg", + "moduleName": "Sentry", + "declAttributes": [ + "Transparent" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "SENTRY_UIKIT_AVAILABLE", + "printedName": "SENTRY_UIKIT_AVAILABLE", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Var", + "usr": "c:@macro@SENTRY_UIKIT_AVAILABLE", + "moduleName": "Sentry", + "declAttributes": [ + "Nonisolated" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Accessor", + "usr": "s:SC22SENTRY_UIKIT_AVAILABLEs5Int32Vvg", + "mangledName": "$sSC22SENTRY_UIKIT_AVAILABLEs5Int32Vvg", + "moduleName": "Sentry", + "declAttributes": [ + "Transparent" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "Var", + "name": "SWIFT_TYPEDEFS", + "printedName": "SWIFT_TYPEDEFS", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Var", + "usr": "c:@macro@SWIFT_TYPEDEFS", + "moduleName": "Sentry", + "declAttributes": [ + "Nonisolated" + ], + "accessors": [ + { + "kind": "Accessor", + "name": "Get", + "printedName": "Get()", + "children": [ + { + "kind": "TypeNominal", + "name": "Int32", + "printedName": "Swift.Int32", + "usr": "s:s5Int32V" + } + ], + "declKind": "Accessor", + "usr": "s:SC14SWIFT_TYPEDEFSs5Int32Vvg", + "mangledName": "$sSC14SWIFT_TYPEDEFSs5Int32Vvg", + "moduleName": "Sentry", + "declAttributes": [ + "Transparent" + ], + "accessorKind": "get" + } + ] + }, + { + "kind": "TypeDecl", + "name": "FileManager", + "printedName": "FileManager", + "children": [ + { + "kind": "Function", + "name": "createFileWithSentryTracing", + "printedName": "createFileWithSentryTracing(atPath:contents:attributes:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Bool", + "printedName": "Swift.Bool", + "usr": "s:Sb" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "Foundation.Data?", + "children": [ + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + } + ], + "usr": "s:Sq" + }, + { + "kind": "TypeNominal", + "name": "Optional", + "printedName": "[Foundation.FileAttributeKey : Any]?", + "children": [ + { + "kind": "TypeNominal", + "name": "Dictionary", + "printedName": "[Foundation.FileAttributeKey : Any]", + "children": [ + { + "kind": "TypeNominal", + "name": "FileAttributeKey", + "printedName": "Foundation.FileAttributeKey", + "usr": "c:@T@NSFileAttributeKey" + }, + { + "kind": "TypeNominal", + "name": "ProtocolComposition", + "printedName": "Any" + } + ], + "usr": "s:SD" + } + ], + "hasDefaultArg": true, + "usr": "s:Sq" + } + ], + "declKind": "Func", + "usr": "s:So13NSFileManagerC6SentryE014createFileWithC7Tracing6atPath8contents10attributesSbSS_10Foundation4DataVSgSDySo0A12AttributeKeyaypGSgtF", + "mangledName": "$sSo13NSFileManagerC6SentryE014createFileWithC7Tracing6atPath8contents10attributesSbSS_10Foundation4DataVSgSDySo0A12AttributeKeyaypGSgtF", + "moduleName": "Sentry", + "isFromExtension": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "removeItemWithSentryTracing", + "printedName": "removeItemWithSentryTracing(at:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "URL", + "printedName": "Foundation.URL", + "usr": "s:10Foundation3URLV" + } + ], + "declKind": "Func", + "usr": "s:So13NSFileManagerC6SentryE014removeItemWithC7Tracing2aty10Foundation3URLV_tKF", + "mangledName": "$sSo13NSFileManagerC6SentryE014removeItemWithC7Tracing2aty10Foundation3URLV_tKF", + "moduleName": "Sentry", + "isFromExtension": true, + "throwing": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "removeItemWithSentryTracing", + "printedName": "removeItemWithSentryTracing(atPath:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "s:So13NSFileManagerC6SentryE014removeItemWithC7Tracing6atPathySS_tKF", + "mangledName": "$sSo13NSFileManagerC6SentryE014removeItemWithC7Tracing6atPathySS_tKF", + "moduleName": "Sentry", + "isFromExtension": true, + "throwing": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "copyItemWithSentryTracing", + "printedName": "copyItemWithSentryTracing(at:to:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "URL", + "printedName": "Foundation.URL", + "usr": "s:10Foundation3URLV" + }, + { + "kind": "TypeNominal", + "name": "URL", + "printedName": "Foundation.URL", + "usr": "s:10Foundation3URLV" + } + ], + "declKind": "Func", + "usr": "s:So13NSFileManagerC6SentryE012copyItemWithC7Tracing2at2toy10Foundation3URLV_AItKF", + "mangledName": "$sSo13NSFileManagerC6SentryE012copyItemWithC7Tracing2at2toy10Foundation3URLV_AItKF", + "moduleName": "Sentry", + "isFromExtension": true, + "throwing": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "copyItemWithSentryTracing", + "printedName": "copyItemWithSentryTracing(atPath:toPath:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "s:So13NSFileManagerC6SentryE012copyItemWithC7Tracing6atPath02toI0ySS_SStKF", + "mangledName": "$sSo13NSFileManagerC6SentryE012copyItemWithC7Tracing6atPath02toI0ySS_SStKF", + "moduleName": "Sentry", + "isFromExtension": true, + "throwing": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "moveItemWithSentryTracing", + "printedName": "moveItemWithSentryTracing(at:to:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "URL", + "printedName": "Foundation.URL", + "usr": "s:10Foundation3URLV" + }, + { + "kind": "TypeNominal", + "name": "URL", + "printedName": "Foundation.URL", + "usr": "s:10Foundation3URLV" + } + ], + "declKind": "Func", + "usr": "s:So13NSFileManagerC6SentryE012moveItemWithC7Tracing2at2toy10Foundation3URLV_AItKF", + "mangledName": "$sSo13NSFileManagerC6SentryE012moveItemWithC7Tracing2at2toy10Foundation3URLV_AItKF", + "moduleName": "Sentry", + "isFromExtension": true, + "throwing": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "moveItemWithSentryTracing", + "printedName": "moveItemWithSentryTracing(atPath:toPath:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + }, + { + "kind": "TypeNominal", + "name": "String", + "printedName": "Swift.String", + "usr": "s:SS" + } + ], + "declKind": "Func", + "usr": "s:So13NSFileManagerC6SentryE012moveItemWithC7Tracing6atPath02toI0ySS_SStKF", + "mangledName": "$sSo13NSFileManagerC6SentryE012moveItemWithC7Tracing6atPath02toI0ySS_SStKF", + "moduleName": "Sentry", + "isFromExtension": true, + "throwing": true, + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)NSFileManager", + "moduleName": "Foundation", + "isOpen": true, + "objc_name": "NSFileManager", + "declAttributes": [ + "ObjC", + "NonSendable", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)NSObject", + "isExternal": true, + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + } + ] + }, + { + "kind": "TypeDecl", + "name": "UIView", + "printedName": "UIView", + "children": [ + { + "kind": "Function", + "name": "sentryReplayMask", + "printedName": "sentryReplayMask()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "s:So6UIViewC6SentryE16sentryReplayMaskyyF", + "mangledName": "$sSo6UIViewC6SentryE16sentryReplayMaskyyF", + "moduleName": "Sentry", + "declAttributes": [ + "Preconcurrency", + "Custom" + ], + "isFromExtension": true, + "funcSelfKind": "NonMutating" + }, + { + "kind": "Function", + "name": "sentryReplayUnmask", + "printedName": "sentryReplayUnmask()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "s:So6UIViewC6SentryE18sentryReplayUnmaskyyF", + "mangledName": "$sSo6UIViewC6SentryE18sentryReplayUnmaskyyF", + "moduleName": "Sentry", + "declAttributes": [ + "Preconcurrency", + "Custom" + ], + "isFromExtension": true, + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Class", + "usr": "c:objc(cs)UIView", + "moduleName": "UIKit", + "isOpen": true, + "intro_iOS": "2.0", + "objc_name": "UIView", + "declAttributes": [ + "Available", + "ObjC", + "NonSendable", + "Custom", + "Dynamic" + ], + "superclassUsr": "c:objc(cs)UIResponder", + "isExternal": true, + "inheritsConvenienceInitializers": true, + "superclassNames": [ + "UIKit.UIResponder", + "ObjectiveC.NSObject" + ], + "conformances": [ + { + "kind": "Conformance", + "name": "NSCoding", + "printedName": "NSCoding", + "usr": "c:objc(pl)NSCoding" + }, + { + "kind": "Conformance", + "name": "UIAppearance", + "printedName": "UIAppearance", + "usr": "c:objc(pl)UIAppearance" + }, + { + "kind": "Conformance", + "name": "UIAppearanceContainer", + "printedName": "UIAppearanceContainer", + "usr": "c:objc(pl)UIAppearanceContainer" + }, + { + "kind": "Conformance", + "name": "UIDynamicItem", + "printedName": "UIDynamicItem", + "usr": "c:objc(pl)UIDynamicItem" + }, + { + "kind": "Conformance", + "name": "UITraitEnvironment", + "printedName": "UITraitEnvironment", + "usr": "c:objc(pl)UITraitEnvironment" + }, + { + "kind": "Conformance", + "name": "UICoordinateSpace", + "printedName": "UICoordinateSpace", + "usr": "c:objc(pl)UICoordinateSpace" + }, + { + "kind": "Conformance", + "name": "UIFocusItem", + "printedName": "UIFocusItem", + "usr": "c:objc(pl)UIFocusItem" + }, + { + "kind": "Conformance", + "name": "UIFocusEnvironment", + "printedName": "UIFocusEnvironment", + "usr": "c:objc(pl)UIFocusEnvironment" + }, + { + "kind": "Conformance", + "name": "UIFocusItemContainer", + "printedName": "UIFocusItemContainer", + "usr": "c:objc(pl)UIFocusItemContainer" + }, + { + "kind": "Conformance", + "name": "CALayerDelegate", + "printedName": "CALayerDelegate", + "usr": "c:objc(pl)CALayerDelegate" + }, + { + "kind": "Conformance", + "name": "UIResponderStandardEditActions", + "printedName": "UIResponderStandardEditActions", + "usr": "c:objc(pl)UIResponderStandardEditActions" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "NSObjectProtocol", + "printedName": "NSObjectProtocol", + "usr": "c:objc(pl)NSObject" + }, + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "CVarArg", + "printedName": "CVarArg", + "usr": "s:s7CVarArgP", + "mangledName": "$ss7CVarArgP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "UIActivityItemsConfigurationProviding", + "printedName": "UIActivityItemsConfigurationProviding", + "usr": "c:objc(pl)UIActivityItemsConfigurationProviding" + }, + { + "kind": "Conformance", + "name": "UIPasteConfigurationSupporting", + "printedName": "UIPasteConfigurationSupporting", + "usr": "c:objc(pl)UIPasteConfigurationSupporting" + }, + { + "kind": "Conformance", + "name": "UIUserActivityRestoring", + "printedName": "UIUserActivityRestoring", + "usr": "c:objc(pl)UIUserActivityRestoring" + }, + { + "kind": "Conformance", + "name": "UITraitChangeObservable", + "printedName": "UITraitChangeObservable", + "usr": "s:5UIKit23UITraitChangeObservableP", + "mangledName": "$s5UIKit23UITraitChangeObservableP" + }, + { + "kind": "Conformance", + "name": "UIPopoverPresentationControllerSourceItem", + "printedName": "UIPopoverPresentationControllerSourceItem", + "usr": "c:objc(pl)UIPopoverPresentationControllerSourceItem" + }, + { + "kind": "Conformance", + "name": "UILargeContentViewerItem", + "printedName": "UILargeContentViewerItem", + "usr": "c:objc(pl)UILargeContentViewerItem" + }, + { + "kind": "Conformance", + "name": "UIAccessibilityIdentification", + "printedName": "UIAccessibilityIdentification", + "usr": "c:objc(pl)UIAccessibilityIdentification" + } + ] + }, + { + "kind": "TypeDecl", + "name": "Data", + "printedName": "Data", + "children": [ + { + "kind": "Constructor", + "name": "init", + "printedName": "init(contentsOfWithSentryTracing:options:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + }, + { + "kind": "TypeNominal", + "name": "URL", + "printedName": "Foundation.URL", + "usr": "s:10Foundation3URLV" + }, + { + "kind": "TypeNameAlias", + "name": "ReadingOptions", + "printedName": "Foundation.Data.ReadingOptions", + "children": [ + { + "kind": "TypeNominal", + "name": "ReadingOptions", + "printedName": "Foundation.NSData.ReadingOptions", + "usr": "c:@E@NSDataReadingOptions" + } + ], + "hasDefaultArg": true + } + ], + "declKind": "Constructor", + "usr": "s:10Foundation4DataV6SentryE014contentsOfWithC7Tracing7optionsAcA3URLV_So20NSDataReadingOptionsVtKcfc", + "mangledName": "$s10Foundation4DataV6SentryE014contentsOfWithC7Tracing7optionsAcA3URLV_So20NSDataReadingOptionsVtKcfc", + "moduleName": "Sentry", + "isFromExtension": true, + "throwing": true, + "init_kind": "Designated" + }, + { + "kind": "Function", + "name": "writeWithSentryTracing", + "printedName": "writeWithSentryTracing(to:options:)", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + }, + { + "kind": "TypeNominal", + "name": "URL", + "printedName": "Foundation.URL", + "usr": "s:10Foundation3URLV" + }, + { + "kind": "TypeNameAlias", + "name": "WritingOptions", + "printedName": "Foundation.Data.WritingOptions", + "children": [ + { + "kind": "TypeNominal", + "name": "WritingOptions", + "printedName": "Foundation.NSData.WritingOptions", + "usr": "c:@E@NSDataWritingOptions" + } + ], + "hasDefaultArg": true + } + ], + "declKind": "Func", + "usr": "s:10Foundation4DataV6SentryE09writeWithC7Tracing2to7optionsyAA3URLV_So20NSDataWritingOptionsVtKF", + "mangledName": "$s10Foundation4DataV6SentryE09writeWithC7Tracing2to7optionsyAA3URLV_So20NSDataWritingOptionsVtKF", + "moduleName": "Sentry", + "isFromExtension": true, + "throwing": true, + "funcSelfKind": "NonMutating" + } + ], + "declKind": "Struct", + "usr": "s:10Foundation4DataV", + "mangledName": "$s10Foundation4DataV", + "moduleName": "Foundation", + "intro_Macosx": "10.10", + "intro_iOS": "8.0", + "intro_tvOS": "9.0", + "intro_watchOS": "2.0", + "declAttributes": [ + "Frozen", + "Available", + "Available", + "Available", + "Available" + ], + "isExternal": true, + "conformances": [ + { + "kind": "Conformance", + "name": "Equatable", + "printedName": "Equatable", + "usr": "s:SQ", + "mangledName": "$sSQ" + }, + { + "kind": "Conformance", + "name": "Hashable", + "printedName": "Hashable", + "usr": "s:SH", + "mangledName": "$sSH" + }, + { + "kind": "Conformance", + "name": "RandomAccessCollection", + "printedName": "RandomAccessCollection", + "children": [ + { + "kind": "TypeWitness", + "name": "Element", + "printedName": "Element", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Element", + "printedName": "Foundation.Data.Element", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt8", + "printedName": "Swift.UInt8", + "usr": "s:s5UInt8V" + } + ] + } + ] + }, + { + "kind": "TypeWitness", + "name": "Index", + "printedName": "Index", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Index", + "printedName": "Foundation.Data.Index", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + }, + { + "kind": "TypeWitness", + "name": "SubSequence", + "printedName": "SubSequence", + "children": [ + { + "kind": "TypeNameAlias", + "name": "SubSequence", + "printedName": "Foundation.Data.SubSequence", + "children": [ + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + } + ] + } + ] + }, + { + "kind": "TypeWitness", + "name": "Indices", + "printedName": "Indices", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Indices", + "printedName": "Foundation.Data.Indices", + "children": [ + { + "kind": "TypeNominal", + "name": "Range", + "printedName": "Swift.Range", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "usr": "s:Sn" + } + ] + } + ] + } + ], + "usr": "s:Sk", + "mangledName": "$sSk" + }, + { + "kind": "Conformance", + "name": "MutableCollection", + "printedName": "MutableCollection", + "children": [ + { + "kind": "TypeWitness", + "name": "Element", + "printedName": "Element", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Element", + "printedName": "Foundation.Data.Element", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt8", + "printedName": "Swift.UInt8", + "usr": "s:s5UInt8V" + } + ] + } + ] + }, + { + "kind": "TypeWitness", + "name": "Index", + "printedName": "Index", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Index", + "printedName": "Foundation.Data.Index", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + }, + { + "kind": "TypeWitness", + "name": "SubSequence", + "printedName": "SubSequence", + "children": [ + { + "kind": "TypeNameAlias", + "name": "SubSequence", + "printedName": "Foundation.Data.SubSequence", + "children": [ + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + } + ] + } + ] + } + ], + "usr": "s:SM", + "mangledName": "$sSM" + }, + { + "kind": "Conformance", + "name": "RangeReplaceableCollection", + "printedName": "RangeReplaceableCollection", + "children": [ + { + "kind": "TypeWitness", + "name": "SubSequence", + "printedName": "SubSequence", + "children": [ + { + "kind": "TypeNameAlias", + "name": "SubSequence", + "printedName": "Foundation.Data.SubSequence", + "children": [ + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + } + ] + } + ] + } + ], + "usr": "s:Sm", + "mangledName": "$sSm" + }, + { + "kind": "Conformance", + "name": "MutableDataProtocol", + "printedName": "MutableDataProtocol", + "usr": "s:10Foundation19MutableDataProtocolP", + "mangledName": "$s10Foundation19MutableDataProtocolP" + }, + { + "kind": "Conformance", + "name": "ContiguousBytes", + "printedName": "ContiguousBytes", + "usr": "s:10Foundation15ContiguousBytesP", + "mangledName": "$s10Foundation15ContiguousBytesP" + }, + { + "kind": "Conformance", + "name": "Sendable", + "printedName": "Sendable", + "usr": "s:s8SendableP", + "mangledName": "$ss8SendableP" + }, + { + "kind": "Conformance", + "name": "BidirectionalCollection", + "printedName": "BidirectionalCollection", + "children": [ + { + "kind": "TypeWitness", + "name": "Element", + "printedName": "Element", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Element", + "printedName": "Foundation.Data.Element", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt8", + "printedName": "Swift.UInt8", + "usr": "s:s5UInt8V" + } + ] + } + ] + }, + { + "kind": "TypeWitness", + "name": "Index", + "printedName": "Index", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Index", + "printedName": "Foundation.Data.Index", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + }, + { + "kind": "TypeWitness", + "name": "SubSequence", + "printedName": "SubSequence", + "children": [ + { + "kind": "TypeNameAlias", + "name": "SubSequence", + "printedName": "Foundation.Data.SubSequence", + "children": [ + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + } + ] + } + ] + }, + { + "kind": "TypeWitness", + "name": "Indices", + "printedName": "Indices", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Indices", + "printedName": "Foundation.Data.Indices", + "children": [ + { + "kind": "TypeNominal", + "name": "Range", + "printedName": "Swift.Range", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "usr": "s:Sn" + } + ] + } + ] + } + ], + "usr": "s:SK", + "mangledName": "$sSK" + }, + { + "kind": "Conformance", + "name": "Collection", + "printedName": "Collection", + "children": [ + { + "kind": "TypeWitness", + "name": "Element", + "printedName": "Element", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Element", + "printedName": "Foundation.Data.Element", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt8", + "printedName": "Swift.UInt8", + "usr": "s:s5UInt8V" + } + ] + } + ] + }, + { + "kind": "TypeWitness", + "name": "Index", + "printedName": "Index", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Index", + "printedName": "Foundation.Data.Index", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ] + } + ] + }, + { + "kind": "TypeWitness", + "name": "Iterator", + "printedName": "Iterator", + "children": [ + { + "kind": "TypeNominal", + "name": "Iterator", + "printedName": "Foundation.Data.Iterator", + "usr": "s:10Foundation4DataV8IteratorV" + } + ] + }, + { + "kind": "TypeWitness", + "name": "SubSequence", + "printedName": "SubSequence", + "children": [ + { + "kind": "TypeNameAlias", + "name": "SubSequence", + "printedName": "Foundation.Data.SubSequence", + "children": [ + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + } + ] + } + ] + }, + { + "kind": "TypeWitness", + "name": "Indices", + "printedName": "Indices", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Indices", + "printedName": "Foundation.Data.Indices", + "children": [ + { + "kind": "TypeNominal", + "name": "Range", + "printedName": "Swift.Range", + "children": [ + { + "kind": "TypeNominal", + "name": "Int", + "printedName": "Swift.Int", + "usr": "s:Si" + } + ], + "usr": "s:Sn" + } + ] + } + ] + } + ], + "usr": "s:Sl", + "mangledName": "$sSl" + }, + { + "kind": "Conformance", + "name": "DataProtocol", + "printedName": "DataProtocol", + "children": [ + { + "kind": "TypeWitness", + "name": "Regions", + "printedName": "Regions", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Regions", + "printedName": "Foundation.Data.Regions", + "children": [ + { + "kind": "TypeNominal", + "name": "CollectionOfOne", + "printedName": "Swift.CollectionOfOne", + "children": [ + { + "kind": "TypeNominal", + "name": "Data", + "printedName": "Foundation.Data", + "usr": "s:10Foundation4DataV" + } + ], + "usr": "s:s15CollectionOfOneV" + } + ] + } + ] + } + ], + "usr": "s:10Foundation12DataProtocolP", + "mangledName": "$s10Foundation12DataProtocolP" + }, + { + "kind": "Conformance", + "name": "Sequence", + "printedName": "Sequence", + "children": [ + { + "kind": "TypeWitness", + "name": "Element", + "printedName": "Element", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Element", + "printedName": "Foundation.Data.Element", + "children": [ + { + "kind": "TypeNominal", + "name": "UInt8", + "printedName": "Swift.UInt8", + "usr": "s:s5UInt8V" + } + ] + } + ] + }, + { + "kind": "TypeWitness", + "name": "Iterator", + "printedName": "Iterator", + "children": [ + { + "kind": "TypeNominal", + "name": "Iterator", + "printedName": "Foundation.Data.Iterator", + "usr": "s:10Foundation4DataV8IteratorV" + } + ] + } + ], + "usr": "s:ST", + "mangledName": "$sST" + }, + { + "kind": "Conformance", + "name": "Copyable", + "printedName": "Copyable", + "usr": "s:s8CopyableP", + "mangledName": "$ss8CopyableP" + }, + { + "kind": "Conformance", + "name": "Escapable", + "printedName": "Escapable", + "usr": "s:s9EscapableP", + "mangledName": "$ss9EscapableP" + }, + { + "kind": "Conformance", + "name": "CustomStringConvertible", + "printedName": "CustomStringConvertible", + "usr": "s:s23CustomStringConvertibleP", + "mangledName": "$ss23CustomStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomDebugStringConvertible", + "printedName": "CustomDebugStringConvertible", + "usr": "s:s28CustomDebugStringConvertibleP", + "mangledName": "$ss28CustomDebugStringConvertibleP" + }, + { + "kind": "Conformance", + "name": "CustomReflectable", + "printedName": "CustomReflectable", + "usr": "s:s17CustomReflectableP", + "mangledName": "$ss17CustomReflectableP" + }, + { + "kind": "Conformance", + "name": "Decodable", + "printedName": "Decodable", + "usr": "s:Se", + "mangledName": "$sSe" + }, + { + "kind": "Conformance", + "name": "Encodable", + "printedName": "Encodable", + "usr": "s:SE", + "mangledName": "$sSE" + }, + { + "kind": "Conformance", + "name": "ReferenceConvertible", + "printedName": "ReferenceConvertible", + "children": [ + { + "kind": "TypeWitness", + "name": "ReferenceType", + "printedName": "ReferenceType", + "children": [ + { + "kind": "TypeNameAlias", + "name": "ReferenceType", + "printedName": "Foundation.Data.ReferenceType", + "children": [ + { + "kind": "TypeNominal", + "name": "NSData", + "printedName": "Foundation.NSData", + "usr": "c:objc(cs)NSData" + } + ] + } + ] + } + ], + "usr": "s:10Foundation20ReferenceConvertibleP", + "mangledName": "$s10Foundation20ReferenceConvertibleP" + } + ] + } + ], + "json_format_version": 8 + } +} \ No newline at end of file