Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,14 @@ jobs:
device: "Apple TV"
scheme: "Sentry"

# visionOS 26
- name: visionOS 26 Sentry
runs-on: macos-26
xcode: "26.1.1"
test-destination-os: "26.1"
platform: "visionOS"
scheme: "Sentry"

# 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.
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- Change default attributes of Logs to only include user attributes when `options.sendDefaultPii = true` (#7055)
- Rename log attribute `sentry.trace.parent_span_id` to `span_id` (#7055)
- Fixes stacktraces for MetricKit events (#6908)
- Fix compilation for visionOS (#7081)

## 9.1.0

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
#import "SentryDefines.h"

#if TARGET_OS_IOS || TARGET_OS_TV
# define SENTRY_UIKIT_AVAILABLE 1
#else
# define SENTRY_UIKIT_AVAILABLE 0
#endif

#if SENTRY_HAS_UIKIT
# import "SentryAppStartTracker.h"
# import "SentryDefaultUIViewControllerPerformanceTracker.h"
Expand Down
8 changes: 6 additions & 2 deletions SentryTestUtils/Sources/TestDisplayLinkWrapper.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation
@_spi(Private) @testable import Sentry

#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst)
#if os(iOS) || os(tvOS) || os(visionOS) || targetEnvironment(macCatalyst)

public enum GPUFrame {
case normal
Expand All @@ -18,7 +18,7 @@ public enum FrameRate: UInt64 {
}
}

@_spi(Private) public class TestDisplayLinkWrapper: SentryDisplayLinkWrapper, SentryReplayDisplayLinkWrapper {
@_spi(Private) public class TestDisplayLinkWrapper: SentryDisplayLinkWrapper {
public var target: AnyObject!
public var selector: Selector!
public var currentFrameRate: FrameRate = .low
Expand Down Expand Up @@ -146,3 +146,7 @@ public enum FrameRate: UInt64 {
}

#endif

#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst)
extension TestDisplayLinkWrapper: SentryReplayDisplayLinkWrapper {}
#endif
2 changes: 1 addition & 1 deletion Sources/Sentry/SentryBuildAppStartSpans.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#import "SentryTracer.h"
#import <SentryBuildAppStartSpans.h>

#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION

SentrySpan *
sentryBuildAppStartSpan(
Expand Down
6 changes: 3 additions & 3 deletions Sources/Sentry/SentrySpan.m
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ @implementation SentrySpan {
}

- (instancetype)initWithContext:(SentrySpanContext *)context
#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION
framesTracker:(nullable SentryFramesTracker *)framesTracker;
#endif // SENTRY_HAS_UIKIT
{
Expand All @@ -65,7 +65,7 @@ - (instancetype)initWithContext:(SentrySpanContext *)context
getThreadName:currentThread];
}

#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION
_framesTracker = framesTracker;
if (_framesTracker.isRunning) {
SentryScreenFrames *currentFrames = _framesTracker.currentFrames;
Expand Down Expand Up @@ -137,7 +137,7 @@ - (void)stopObservingContinuousProfiling

- (instancetype)initWithTracer:(SentryTracer *)tracer
context:(SentrySpanContext *)context
#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION
framesTracker:(nullable SentryFramesTracker *)framesTracker
{
if (self = [self initWithContext:context framesTracker:framesTracker]) {
Expand Down
20 changes: 10 additions & 10 deletions Sources/Sentry/SentryTracer.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
# import "SentryProfiledTracerConcurrency.h"
#endif // SENTRY_TARGET_PROFILING_SUPPORTED

#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION
# import "SentryAppStartMeasurement.h"
# import "SentryBuildAppStartSpans.h"
#endif // SENTRY_HAS_UIKIT
Expand All @@ -39,7 +39,7 @@

static const void *spanTimestampObserver = &spanTimestampObserver;

#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION
/**
* The maximum amount of seconds the app start measurement end time and the start time of the
* transaction are allowed to be apart.
Expand Down Expand Up @@ -114,7 +114,7 @@ - (instancetype)initWithTransactionContext:(SentryTransactionContext *)transacti
configuration:(SentryTracerConfiguration *)configuration;
{
if (!(self = [super initWithContext:transactionContext
#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION
framesTracker:SentryDependencyContainer.sharedInstance.framesTracker
#endif // SENTRY_HAS_UIKIT
])) {
Expand Down Expand Up @@ -390,7 +390,7 @@ - (BOOL)isAutoGeneratedTransaction
SentrySpan *child =
[[SentrySpan alloc] initWithTracer:self
context:context
#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION
framesTracker:SentryDependencyContainer.sharedInstance.framesTracker
#endif // SENTRY_HAS_UIKIT
];
Expand Down Expand Up @@ -615,13 +615,13 @@ - (BOOL)finishTracer:(SentrySpanStatus)unfinishedSpansFinishStatus shouldCleanUp
}
[super finishWithStatus:_finishStatus];
}
#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION
appStartMeasurement = [self getAppStartMeasurement];

if (appStartMeasurement != nil) {
[self updateStartTime:appStartMeasurement.appStartTimestamp];
}
#endif // SENTRY_HAS_UIKIT
#endif // SENTRY_HAS_UIKIT && !TARGET_OS_VISION

if (shouldCleanUp) {
[self.delegate tracerDidFinish:self];
Expand Down Expand Up @@ -721,7 +721,7 @@ - (SentryTransaction *)toTransaction
{

NSUInteger capacity;
#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION
[self addFrameStatistics];

NSArray<id<SentrySpan>> *appStartSpans = sentryBuildAppStartSpans(self, appStartMeasurement);
Expand All @@ -736,7 +736,7 @@ - (SentryTransaction *)toTransaction
[spans addObjectsFromArray:_children];
}

#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION
[spans addObjectsFromArray:appStartSpans];
#endif // SENTRY_HAS_UIKIT

Expand All @@ -763,7 +763,7 @@ - (SentryTransaction *)toTransaction
[debugImageProvider getDebugImagesFromCacheForFrames:framesOfAllSpans];
}

#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION
[self addAppStartMeasurements:transaction];

if ([viewNames count] > 0) {
Expand All @@ -774,7 +774,7 @@ - (SentryTransaction *)toTransaction
return transaction;
}

#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION

- (nullable SentryAppStartMeasurement *)getAppStartMeasurement SENTRY_DISABLE_THREAD_SANITIZER(
"double-checked lock produce false alarms")
Expand Down
4 changes: 2 additions & 2 deletions Sources/Sentry/include/SentrySpan.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ SENTRY_NO_INIT
*/
- (instancetype)initWithTracer:(SentryTracer *)transaction
context:(SentrySpanContext *)context
#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION
framesTracker:(nullable SentryFramesTracker *)framesTracker;
#endif // SENTRY_HAS_UIKIT
;
Expand All @@ -106,7 +106,7 @@ SENTRY_NO_INIT
* @param context This span context information.
*/
- (instancetype)initWithContext:(SentrySpanContext *)context
#if SENTRY_HAS_UIKIT
#if SENTRY_HAS_UIKIT && !TARGET_OS_VISION
framesTracker:(nullable SentryFramesTracker *)framesTracker;
#endif // SENTRY_HAS_UIKIT
;
Expand Down
2 changes: 1 addition & 1 deletion Sources/Swift/SentryCrash/SentryCrashWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ public final class SentryCrashWrapper: NSObject {

if self.processInfoWrapper.isMacCatalystApp {
runtimeContext["name"] = "Mac Catalyst App"
runtimeContext["raw_description"] = "raw_description"
runtimeContext["raw_description"] = "mac-catalyst-app"
}
}

Expand Down
18 changes: 18 additions & 0 deletions Tests/SentryTests/Helper/SentryDeviceTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,18 @@ - (void)testCPUArchitecture
// TODO: create a watch UI test target to test this branch as it cannot run on the watch
// simulator
SENTRY_ASSERT_CONTAINS(arch, @"arm"); // Real Watches
#elif TARGET_OS_VISION
# if TARGET_OS_SIMULATOR
# if TARGET_CPU_ARM64
SENTRY_ASSERT_CONTAINS(arch, @"arm"); // Vision Pro simulator on M1 macs
# elif TARGET_CPU_X86_64
SENTRY_ASSERT_CONTAINS(arch, @"x86"); // Vision Pro simulator on Intel macs
# else
XCTFail(@"Unexpected CPU type on test host.");
# endif // TARGET_CPU_ARM64
# else
SENTRY_ASSERT_CONTAINS(arch, @"arm"); // Real Vision Pro devices
# endif
#else
XCTFail(@"Unexpected device OS");
#endif
Expand Down Expand Up @@ -127,6 +139,8 @@ - (void)testOSName
#elif TARGET_OS_WATCH
// TODO: create a watch UI test target to test this branch
SENTRY_ASSERT_EQUAL(osName, @"watchOS");
#elif TARGET_OS_VISION
SENTRY_ASSERT_EQUAL(osName, @"visionOS");
#else
XCTFail(@"Unexpected device OS");
#endif
Expand Down Expand Up @@ -161,6 +175,8 @@ - (void)testDeviceModel
// TODO: create a watch UI test target to test this branch as it cannot run on the watch
// simulator
SENTRY_ASSERT_CONTAINS(modelName, @"Watch");
#elif TARGET_OS_VISION
SENTRY_ASSERT_CONTAINS(modelName, @"RealityDevice");
#else
XCTFail(@"Unexpected target OS");
#endif
Expand Down Expand Up @@ -205,6 +221,8 @@ - (void)testSimulatedDeviceModel
// TODO: create a watch UI test target to test this branch as it cannot run on the watch
// simulator
SENTRY_ASSERT_CONTAINS(modelName, @"Watch");
# elif TARGET_OS_VISION
SENTRY_ASSERT_CONTAINS(modelName, @"RealityDevice");
# else
XCTFail(@"Unexpected device OS");
# endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ class SentryANRTrackingIntegrationTests: SentrySDKIntegrationTestsBase {

let tracker = try XCTUnwrap(Dynamic(sut).tracker.asAnyObject as? SentryANRTracker)

#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst)
#if os(iOS) || os(tvOS) || os(visionOS) || targetEnvironment(macCatalyst)
XCTAssertTrue(tracker.helper is SentryANRTrackerV2, "Expected SentryANRTrackerV2, but got \(type(of: tracker))")
#else
XCTAssertTrue(tracker.helper is SentryANRTrackerV1, "Expected SentryANRTrackerV1 on macOS, but got \(type(of: tracker))")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
@_spi(Private) import SentryTestUtils
import XCTest

#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst)

class TestDelayedWrapper: SentryDelayedFramesTracker {}

Check failure on line 6 in Tests/SentryTests/Integrations/Performance/UIViewController/SentryTimeToDisplayTrackerTest.swift

View workflow job for this annotation

GitHub Actions / Unit macOS 26 Sentry / Unit macOS 26 Sentry

cannot find type 'SentryDelayedFramesTracker' in scope

Check failure on line 6 in Tests/SentryTests/Integrations/Performance/UIViewController/SentryTimeToDisplayTrackerTest.swift

View workflow job for this annotation

GitHub Actions / Unit with Test Server macOS 15

cannot find type 'SentryDelayedFramesTracker' in scope

Check failure on line 6 in Tests/SentryTests/Integrations/Performance/UIViewController/SentryTimeToDisplayTrackerTest.swift

View workflow job for this annotation

GitHub Actions / Unit macOS 14 Sentry / Unit macOS 14 Sentry

cannot find type 'SentryDelayedFramesTracker' in scope

Check failure on line 6 in Tests/SentryTests/Integrations/Performance/UIViewController/SentryTimeToDisplayTrackerTest.swift

View workflow job for this annotation

GitHub Actions / Unit macOS 15 Sentry / Unit macOS 15 Sentry

cannot find type 'SentryDelayedFramesTracker' in scope

#if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst)
class SentryTimeToDisplayTrackerTest: XCTestCase {

private class Fixture {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class SentrySessionTrackerTests: XCTestCase {
let client: TestClient!
let sentryCrash: TestSentryCrashWrapper

#if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS)
#if (os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT
let _application: TestSentryUIApplication
#else
let _application: TestSentryNSApplication
Expand All @@ -38,7 +38,7 @@ class SentrySessionTrackerTests: XCTestCase {

sentryCrash = TestSentryCrashWrapper(processInfoWrapper: ProcessInfo.processInfo)

#if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS)
#if (os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT
_application = TestSentryUIApplication()
_application.unsafeApplicationState = .inactive
#else
Expand Down Expand Up @@ -537,7 +537,7 @@ class SentrySessionTrackerTests: XCTestCase {
// MARK: - Helpers

private func startSutInAppDelegate() {
#if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS)
#if (os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT
// The Sentry SDK should be initialized in the `UIAppDelegate.didFinishLaunchingWithOptions`
// At this point the application state is `inactive`, because the app just launched but did not
// become the active app yet.
Expand Down Expand Up @@ -565,7 +565,7 @@ class SentrySessionTrackerTests: XCTestCase {
// We remove the observers, to ensure future notifications are not handled.
sut.removeObservers()

#if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS)
#if (os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT
// When the app stops, the app state is `inactive`.
// This can be observed by viewing the application state in `UIAppDelegate.applicationDidEnterBackground`.
fixture._application.unsafeApplicationState = .inactive
Expand All @@ -580,7 +580,7 @@ class SentrySessionTrackerTests: XCTestCase {

private func crashSut() {
sut.removeObservers()
#if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS)
#if (os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT
// When the app stops, the app state is `inactive`.
//
// This can be observed by viewing the application state in `UIAppDelegate.applicationDidEnterBackground`.
Expand All @@ -600,7 +600,7 @@ class SentrySessionTrackerTests: XCTestCase {
}

private func goToForeground() {
#if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS)
#if (os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT
// When the app becomes active, the app state is `active`.
// This can be observed by viewing the application state in `UIAppDelegate.applicationDidBecomeActive`.
fixture._application.unsafeApplicationState = .active
Expand All @@ -622,7 +622,7 @@ class SentrySessionTrackerTests: XCTestCase {
private func goToBackground() {
// Before an app goes to background, it is still active and will resign from being active.
willResignActive()
#if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS)
#if (os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT
// It is expected that the app state is background when the didEnterBackground is called
fixture._application.unsafeApplicationState = .background
fixture.notificationCenter
Expand All @@ -642,7 +642,7 @@ class SentrySessionTrackerTests: XCTestCase {
}

private func willResignActive() {
#if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS)
#if (os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT
// 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`.
Expand All @@ -665,7 +665,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)
#if (os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT
fixture._application.unsafeApplicationState = .active
#else
fixture._application.setIsActive(true)
Expand All @@ -687,7 +687,7 @@ class SentrySessionTrackerTests: XCTestCase {
}

private func willTerminate() {
#if os(iOS) || targetEnvironment(macCatalyst) || os(tvOS)
#if (os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT
// 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`.
Expand Down Expand Up @@ -876,7 +876,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)
#if (os(iOS) || targetEnvironment(macCatalyst) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT
fixture._application.unsafeApplicationState = .active
#else
fixture._application.setIsActive(true)
Expand Down
Loading
Loading