diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 9bd9533a9db..bbac89f866a 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -85,7 +85,7 @@ 623FD9062D3FA9C800803EDA /* NSNumberDecodableWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 623FD9052D3FA9BA00803EDA /* NSNumberDecodableWrapperTests.swift */; }; 626E2D4C2BEA0C37005596FE /* SentryEnabledFeaturesBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 626E2D4B2BEA0C37005596FE /* SentryEnabledFeaturesBuilderTests.swift */; }; 6271ADF32BA06D9B0098D2E9 /* SentryInternalSerializable.h in Headers */ = {isa = PBXBuildFile; fileRef = 6271ADF22BA06D9B0098D2E9 /* SentryInternalSerializable.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 6273513F2CBD14970021D100 /* SentryDebugImageProviderInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6273513E2CBD14970021D100 /* SentryDebugImageProviderInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 6273513F2CBD14970021D100 /* SentryDebugImageProviderInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 6273513E2CBD14970021D100 /* SentryDebugImageProviderInternal.h */; }; 6276350C2D59FACC00F7CEF6 /* SentryEventDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6276350B2D59FACC00F7CEF6 /* SentryEventDecoder.swift */; }; 6276E68B2E7A779B002A4A8F /* SentryNetworkTrackerIntegrationTestServerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6276E68A2E7A779B002A4A8F /* SentryNetworkTrackerIntegrationTestServerTests.swift */; }; 627C77892D50B6840055E966 /* SentryBreadcrumbCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 627C77882D50B6840055E966 /* SentryBreadcrumbCodable.swift */; }; @@ -369,7 +369,6 @@ 7B3B473825D6CC7E00D01640 /* SentryNSError.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B3B473725D6CC7E00D01640 /* SentryNSError.m */; }; 7B3B473E25D6CEA500D01640 /* SentryNSErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3B473D25D6CEA500D01640 /* SentryNSErrorTests.swift */; }; 7B42C48027E08F33009B58C2 /* SentryDependencyContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B42C47F27E08F33009B58C2 /* SentryDependencyContainer.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 7B42C48227E08F4B009B58C2 /* SentryDependencyContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B42C48127E08F4B009B58C2 /* SentryDependencyContainer.m */; }; 7B4D308A26FC616B00C94DE9 /* SentryHttpTransportTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4D308926FC616B00C94DE9 /* SentryHttpTransportTests.swift */; }; 7B4E23B6251A07BD00060D68 /* SentryDispatchQueueWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4E23B5251A07BD00060D68 /* SentryDispatchQueueWrapperTests.swift */; }; 7B4E23BE251A2BD500060D68 /* SentryCrashIntegrationSessionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B4E23BD251A2BD500060D68 /* SentryCrashIntegrationSessionHandler.h */; }; @@ -507,7 +506,6 @@ 7BC9A20228F41350001E7C4C /* SentryMeasurementUnit.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BC9A20128F41350001E7C4C /* SentryMeasurementUnit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 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 */; }; 7BCFBD6D2681D0A900BC27D8 /* SentryCrashScopeObserver.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BCFBD6C2681D0A900BC27D8 /* SentryCrashScopeObserver.h */; }; 7BCFBD6F2681D0EE00BC27D8 /* SentryCrashScopeObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BCFBD6E2681D0EE00BC27D8 /* SentryCrashScopeObserver.m */; }; 7BD337E424A356180050DB6E /* SentryCrashIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BD337E324A356180050DB6E /* SentryCrashIntegrationTests.swift */; }; @@ -1110,15 +1108,20 @@ FAAB2F972E4D345800FE8B7E /* SentryUIDeviceWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB2F962E4D344F00FE8B7E /* SentryUIDeviceWrapper.swift */; }; FAAB30F32E4E8F2C00FE8B7E /* SentryInAppLogic.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB30F22E4E8F2C00FE8B7E /* SentryInAppLogic.swift */; }; FAAB95C02EA163590030A2DB /* SentryScopeObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB95BF2EA163590030A2DB /* SentryScopeObserver.swift */; }; + FAAB95CD2EA18B2E0030A2DB /* SentryDependencyContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB95CC2EA18B260030A2DB /* SentryDependencyContainer.swift */; }; FAAB95D82EA1E23F0030A2DB /* SentryExtraContextProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB95D22EA1E23A0030A2DB /* SentryExtraContextProvider.swift */; }; FAAB95DE2EA1EB470030A2DB /* SentryDeviceContextKeys.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAB95DD2EA1EB470030A2DB /* SentryDeviceContextKeys.h */; }; - FAAB96132EA31FA20030A2DB /* SentryDebugImageProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB96122EA31F9E0030A2DB /* SentryDebugImageProvider.swift */; }; - FAAB967B2EA6D82F0030A2DB /* SentryWatchdogTerminationScopeObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB96752EA6D8280030A2DB /* SentryWatchdogTerminationScopeObserver.swift */; }; - FAAB967E2EA6D9D80030A2DB /* SentryCrashScopeHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = FAAB967D2EA6D9D70030A2DB /* SentryCrashScopeHelper.m */; }; + FAAB95FF2EA301670030A2DB /* SentryWatchdogTerminationScopeObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB95FE2EA301600030A2DB /* SentryWatchdogTerminationScopeObserver.swift */; }; + FAAB96132EA31FA20030A2DB /* (null) in Sources */ = {isa = PBXBuildFile; }; + FAAB96482EA6843E0030A2DB /* SentryANRTrackerInternalDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAB96422EA684380030A2DB /* SentryANRTrackerInternalDelegate.h */; }; + FAAB964A2EA688D40030A2DB /* SentryANRStoppedResultInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = FAAB96492EA688CB0030A2DB /* SentryANRStoppedResultInternal.h */; }; + FAAB964C2EA688E50030A2DB /* SentryANRStoppedResultInternal.m in Sources */ = {isa = PBXBuildFile; fileRef = FAAB964B2EA688E40030A2DB /* SentryANRStoppedResultInternal.m */; }; + FAAB964E2EA698730030A2DB /* SentryDebugImageProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB964D2EA698730030A2DB /* SentryDebugImageProvider.swift */; }; + FAAB96502EA698910030A2DB /* SentryCrashSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAAB964F2EA698910030A2DB /* SentryCrashSwift.swift */; }; + FAAB96542EA6A72E0030A2DB /* SentryCrashScopeHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = FAAB96532EA6A72D0030A2DB /* SentryCrashScopeHelper.m */; }; FAB007362E9EF8D3001C806A /* SentryUIViewControllerPerformanceTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB007302E9EF8CB001C806A /* SentryUIViewControllerPerformanceTracker.swift */; }; FAB007432E9F47E8001C806A /* SessionTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB007422E9F47E4001C806A /* SessionTracker.swift */; }; FAB007522E9FE2FF001C806A /* SentrySwizzleWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB0074C2E9FE2FA001C806A /* SentrySwizzleWrapper.swift */; }; - FAB007812EA01B98001C806A /* SentryCrashSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAB0077B2EA01B95001C806A /* SentryCrashSwift.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 */; }; @@ -1143,6 +1146,7 @@ FAEEBFEA2E74517B00E79CA9 /* SentryFileManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAEEBFE92E74517800E79CA9 /* SentryFileManager.swift */; }; FAEEC0522E75E55F00E79CA9 /* SentrySerializationSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAEEC04C2E75E55A00E79CA9 /* SentrySerializationSwift.swift */; }; FAEFA12F2E4FAE1900C431D9 /* SentrySDKSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAEFA1292E4FAE1700C431D9 /* SentrySDKSettings.swift */; }; + FAF0F3D02EA7DD0D00E44E9B /* SentryANRTrackerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAF0F3CA2EA7DD0700E44E9B /* SentryANRTrackerTests.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 */ @@ -1662,7 +1666,6 @@ 7B3B473725D6CC7E00D01640 /* SentryNSError.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryNSError.m; sourceTree = ""; }; 7B3B473D25D6CEA500D01640 /* SentryNSErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSErrorTests.swift; sourceTree = ""; }; 7B42C47F27E08F33009B58C2 /* SentryDependencyContainer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDependencyContainer.h; path = include/HybridPublic/SentryDependencyContainer.h; sourceTree = ""; }; - 7B42C48127E08F4B009B58C2 /* SentryDependencyContainer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDependencyContainer.m; sourceTree = ""; }; 7B4C817124D1BC2B0076ACE4 /* SentryFileManager+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryFileManager+Test.h"; sourceTree = ""; }; 7B4D308926FC616B00C94DE9 /* SentryHttpTransportTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryHttpTransportTests.swift; sourceTree = ""; }; 7B4E23AE2519E13800060D68 /* SentryCrashIntegration+TestInit.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryCrashIntegration+TestInit.h"; sourceTree = ""; }; @@ -1818,7 +1821,6 @@ 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 = ""; }; 7BCFA71527D0BB50008C662C /* SentryANRTrackerV1.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryANRTrackerV1.m; sourceTree = ""; }; - 7BCFBD662681C95000BC27D8 /* SentryScopeObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryScopeObserver.h; path = include/SentryScopeObserver.h; sourceTree = ""; }; 7BCFBD6C2681D0A900BC27D8 /* SentryCrashScopeObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryCrashScopeObserver.h; path = include/SentryCrashScopeObserver.h; sourceTree = ""; }; 7BCFBD6E2681D0EE00BC27D8 /* SentryCrashScopeObserver.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashScopeObserver.m; sourceTree = ""; }; 7BD337E324A356180050DB6E /* SentryCrashIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashIntegrationTests.swift; sourceTree = ""; }; @@ -2490,16 +2492,20 @@ FAAB2F962E4D344F00FE8B7E /* SentryUIDeviceWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUIDeviceWrapper.swift; sourceTree = ""; }; FAAB30F22E4E8F2C00FE8B7E /* SentryInAppLogic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryInAppLogic.swift; sourceTree = ""; }; FAAB95BF2EA163590030A2DB /* SentryScopeObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryScopeObserver.swift; sourceTree = ""; }; + FAAB95CC2EA18B260030A2DB /* SentryDependencyContainer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryDependencyContainer.swift; sourceTree = ""; }; FAAB95D22EA1E23A0030A2DB /* SentryExtraContextProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryExtraContextProvider.swift; sourceTree = ""; }; FAAB95DD2EA1EB470030A2DB /* SentryDeviceContextKeys.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDeviceContextKeys.h; path = include/SentryDeviceContextKeys.h; sourceTree = ""; }; - FAAB96122EA31F9E0030A2DB /* SentryDebugImageProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryDebugImageProvider.swift; sourceTree = ""; }; - FAAB96752EA6D8280030A2DB /* SentryWatchdogTerminationScopeObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryWatchdogTerminationScopeObserver.swift; sourceTree = ""; }; - FAAB967C2EA6D9C00030A2DB /* SentryCrashScopeHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryCrashScopeHelper.h; sourceTree = ""; }; - FAAB967D2EA6D9D70030A2DB /* SentryCrashScopeHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashScopeHelper.m; sourceTree = ""; }; + FAAB95FE2EA301600030A2DB /* SentryWatchdogTerminationScopeObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryWatchdogTerminationScopeObserver.swift; sourceTree = ""; }; + FAAB96422EA684380030A2DB /* SentryANRTrackerInternalDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryANRTrackerInternalDelegate.h; path = include/SentryANRTrackerInternalDelegate.h; sourceTree = ""; }; + FAAB96492EA688CB0030A2DB /* SentryANRStoppedResultInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryANRStoppedResultInternal.h; path = include/SentryANRStoppedResultInternal.h; sourceTree = ""; }; + FAAB964B2EA688E40030A2DB /* SentryANRStoppedResultInternal.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryANRStoppedResultInternal.m; sourceTree = ""; }; + FAAB964D2EA698730030A2DB /* SentryDebugImageProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryDebugImageProvider.swift; sourceTree = ""; }; + FAAB964F2EA698910030A2DB /* SentryCrashSwift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashSwift.swift; sourceTree = ""; }; + FAAB96522EA6A6A30030A2DB /* SentryCrashScopeHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryCrashScopeHelper.h; sourceTree = ""; }; + FAAB96532EA6A72D0030A2DB /* SentryCrashScopeHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashScopeHelper.m; sourceTree = ""; }; FAB007302E9EF8CB001C806A /* SentryUIViewControllerPerformanceTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUIViewControllerPerformanceTracker.swift; sourceTree = ""; }; FAB007422E9F47E4001C806A /* SessionTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionTracker.swift; sourceTree = ""; }; FAB0074C2E9FE2FA001C806A /* SentrySwizzleWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySwizzleWrapper.swift; sourceTree = ""; }; - FAB0077B2EA01B95001C806A /* SentryCrashSwift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashSwift.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 = ""; }; @@ -2525,6 +2531,7 @@ FAEEBFE92E74517800E79CA9 /* SentryFileManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryFileManager.swift; sourceTree = ""; }; FAEEC04C2E75E55A00E79CA9 /* SentrySerializationSwift.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySerializationSwift.swift; sourceTree = ""; }; FAEFA1292E4FAE1700C431D9 /* SentrySDKSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySDKSettings.swift; sourceTree = ""; }; + FAF0F3CA2EA7DD0700E44E9B /* SentryANRTrackerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryANRTrackerTests.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 */ @@ -2888,8 +2895,8 @@ 7BA61CB3247BC3EB00C130A8 /* SentryCrashBinaryImageProvider.h */, 7BA61CB8247BC57B00C130A8 /* SentryCrashDefaultBinaryImageProvider.h */, 7BA61CBA247BC5D800C130A8 /* SentryCrashDefaultBinaryImageProvider.m */, - 6273513E2CBD14970021D100 /* SentryDebugImageProviderInternal.h */, 7BA61CAC247BAA0B00C130A8 /* SentryDebugImageProviderInternal.m */, + 6273513E2CBD14970021D100 /* SentryDebugImageProviderInternal.h */, 7BA61CBE247CEA8100C130A8 /* SentryFormatter.h */, 7BA61CC7247D125400C130A8 /* SentryDefaultThreadInspector.h */, 7BA61CC9247D128B00C130A8 /* SentryDefaultThreadInspector.m */, @@ -2916,7 +2923,6 @@ 7D65260B237F649E00113EA2 /* SentryScope.m */, 632331F7240506DF008D91D6 /* SentryScope+Private.h */, 928207C32E251B8F009285A4 /* SentryScope+PrivateSwift.h */, - 7BCFBD662681C95000BC27D8 /* SentryScopeObserver.h */, 15360CEF2433A16D00112302 /* SentryInstallation.h */, 15360CEC2433A15500112302 /* SentryInstallation.m */, D8C66A342A77B1F70015696A /* SentryPropagationContext.h */, @@ -2957,7 +2963,6 @@ 63AA769B1EB9C57A00D153DE /* SentryError.h */, 63AA769C1EB9C57A00D153DE /* SentryError.mm */, 7B42C47F27E08F33009B58C2 /* SentryDependencyContainer.h */, - 7B42C48127E08F4B009B58C2 /* SentryDependencyContainer.m */, 636085111ED47BE600E8599E /* SentryFileManagerHelper.h */, FA3734832E0F07A20091EF24 /* SentryDependencyContainerSwiftHelper.h */, FA3734852E0F092F0091EF24 /* SentryDependencyContainerSwiftHelper.m */, @@ -3398,6 +3403,9 @@ children = ( 7B127B0C27CF6F2300A71ED2 /* SentryANRTrackingIntegration.h */, 7B127B0E27CF6F4700A71ED2 /* SentryANRTrackingIntegration.m */, + FAAB96422EA684380030A2DB /* SentryANRTrackerInternalDelegate.h */, + FAAB96492EA688CB0030A2DB /* SentryANRStoppedResultInternal.h */, + FAAB964B2EA688E40030A2DB /* SentryANRStoppedResultInternal.m */, 7BCFA71427D0BAB7008C662C /* SentryANRTrackerV1.h */, 7BCFA71527D0BB50008C662C /* SentryANRTrackerV1.m */, 621AE74A2C626C230012E730 /* SentryANRTrackerV2.h */, @@ -3413,6 +3421,7 @@ 621D22002DBB7E09006F9C48 /* SentryANRTrackerV1IntegrationTests.swift */, 621AE74E2C626CF70012E730 /* SentryANRTrackerV2Tests.swift */, 7BFA69F527E0840400233199 /* SentryANRTrackingIntegrationTests.swift */, + FAF0F3CA2EA7DD0700E44E9B /* SentryANRTrackerTests.swift */, 623E16C22D6C57C000CF1625 /* SentryANRTypeTests.swift */, ); path = ANR; @@ -3815,9 +3824,9 @@ 7BE0DC3E272AE9DC004FA8B7 /* SentryCrash */ = { isa = PBXGroup; children = ( + FAAB96522EA6A6A30030A2DB /* SentryCrashScopeHelper.h */, + FAAB96532EA6A72D0030A2DB /* SentryCrashScopeHelper.m */, 7B965727268321CD00C66E25 /* SentryCrashScopeObserverTests.swift */, - FAAB967C2EA6D9C00030A2DB /* SentryCrashScopeHelper.h */, - FAAB967D2EA6D9D70030A2DB /* SentryCrashScopeHelper.m */, 7B6ADFCE26A02CAE0076C206 /* SentryCrashReportTests.swift */, 7BD337E324A356180050DB6E /* SentryCrashIntegrationTests.swift */, 7B4E23AE2519E13800060D68 /* SentryCrashIntegration+TestInit.h */, @@ -4272,6 +4281,7 @@ D452FCBC2DDB6FA800AFF56F /* WatchdogTerminations */ = { isa = PBXGroup; children = ( + FAAB95FE2EA301600030A2DB /* SentryWatchdogTerminationScopeObserver.swift */, D452FCBD2DDB6FC200AFF56F /* Processors */, ); path = WatchdogTerminations; @@ -4397,6 +4407,7 @@ D800942328F82E8D005D3943 /* Swift */ = { isa = PBXGroup; children = ( + FAAB95CC2EA18B260030A2DB /* SentryDependencyContainer.swift */, FAAB95B92EA1633E0030A2DB /* State */, FA560F5A2E8C876A00F2AF7F /* SentryAppStateManager.swift */, F429D37E2E8532A300DBF387 /* Networking */, @@ -4840,8 +4851,8 @@ F4FE9E062E6248BB0014FED5 /* SentryCrash */ = { isa = PBXGroup; children = ( - FAAB96122EA31F9E0030A2DB /* SentryDebugImageProvider.swift */, - FAB0077B2EA01B95001C806A /* SentryCrashSwift.swift */, + FAAB964F2EA698910030A2DB /* SentryCrashSwift.swift */, + FAAB964D2EA698730030A2DB /* SentryDebugImageProvider.swift */, FA8AFCE72E8434A0007A0E18 /* SentryThreadInspector.swift */, FAE579C62E7DE14400B710F9 /* SentryFrameRemover.swift */, F4FE9E072E6248E40014FED5 /* SentryCrashWrapper.swift */, @@ -5002,7 +5013,6 @@ FAB0073C2E9F47DE001C806A /* Session */ = { isa = PBXGroup; children = ( - FAAB96752EA6D8280030A2DB /* SentryWatchdogTerminationScopeObserver.swift */, FAB007422E9F47E4001C806A /* SessionTracker.swift */, ); path = Session; @@ -5048,7 +5058,6 @@ 63FE717720DA4C1100CDBAE8 /* SentryCrashReportWriter.h in Headers */, 84DEE86B2B686BD400A7BC17 /* SentrySamplerDecision.h in Headers */, 7B4E23BE251A2BD500060D68 /* SentryCrashIntegrationSessionHandler.h in Headers */, - 7BCFBD672681C95000BC27D8 /* SentryScopeObserver.h in Headers */, D81A346C291AECC7005A27A9 /* PrivateSentrySDKOnly.h in Headers */, D88817DA26D72AB800BF2251 /* SentryTraceContext.h in Headers */, 7B6C5F8126034354007F7DFF /* SentryWatchdogTerminationLogic.h in Headers */, @@ -5181,6 +5190,7 @@ FAF120182E70C08F006E1DA3 /* SentryEnvelopeHeaderHelper.h in Headers */, 62A456E12B03704A003F19A1 /* SentryUIEventTrackerMode.h in Headers */, 03F84D2327DD414C008FE43F /* SentryThreadHandle.hpp in Headers */, + FAAB964A2EA688D40030A2DB /* SentryANRStoppedResultInternal.h in Headers */, 84A305572BC9EF8C00D84283 /* SentryTraceProfiler.h in Headers */, FA034AC82DD3DB4900FE3107 /* SentryIntegrationProtocol.h in Headers */, 63FE715720DA4C1100CDBAE8 /* SentryCrashThread.h in Headers */, @@ -5284,6 +5294,7 @@ 7BA61CB9247BC57B00C130A8 /* SentryCrashDefaultBinaryImageProvider.h in Headers */, 8E4E7C7D25DAB287006AB9E2 /* SentryTracer.h in Headers */, 7BC8523724588115005A70F0 /* SentryDataCategory.h in Headers */, + FAAB96482EA6843E0030A2DB /* SentryANRTrackerInternalDelegate.h in Headers */, FA8A36182DEAA1EB0058D883 /* SentryThread+Private.h in Headers */, 62A456E32B0370AA003F19A1 /* SentryUIEventTrackerTransactionMode.h in Headers */, 63FE714B20DA4C1100CDBAE8 /* SentryCrashString.h in Headers */, @@ -5686,6 +5697,7 @@ D84D2CDF2C2BF9370011AF8A /* SentryReplayType.swift in Sources */, 63FE717B20DA4C1100CDBAE8 /* SentryCrashReport.c in Sources */, D8F67B222BEAB6CC00C9197B /* SentryRRWebEvent.swift in Sources */, + FAAB96502EA698910030A2DB /* SentryCrashSwift.swift in Sources */, 84A903712D39F66F00690CE4 /* SentryUserFeedbackFormViewModel.swift in Sources */, 7B3398652459C15200BD9C96 /* SentryEnvelopeRateLimit.m in Sources */, D81988C92BEC19200020E36C /* SentryRRWebBreadcrumbEvent.swift in Sources */, @@ -5714,6 +5726,7 @@ 8E564AE8267AF22600FE117D /* SentryNetworkTrackingIntegration.m in Sources */, 63AA75EF1EB8B3C400D153DE /* SentryClient.m in Sources */, D4B0DC7F2DA9257A00DE61B6 /* SentryRenderVideoResult.swift in Sources */, + FAAB964E2EA698730030A2DB /* SentryDebugImageProvider.swift in Sources */, 7B7D873624864C9D00D2ECFF /* SentryCrashDefaultMachineContextWrapper.m in Sources */, 63FE712F20DA4C1100CDBAE8 /* SentryCrashSysCtl.c in Sources */, 62212B872D520CB00062C2FA /* SentryEventCodable.swift in Sources */, @@ -5788,12 +5801,12 @@ 639FCFA91EBC80CC00778193 /* SentryFrame.m in Sources */, 8E564AEA267AF22600FE117D /* SentryNetworkTracker.m in Sources */, 15360CED2433A15500112302 /* SentryInstallation.m in Sources */, + FAAB95FF2EA301670030A2DB /* SentryWatchdogTerminationScopeObserver.swift in Sources */, D8370B6A273DF1E900F66E2D /* SentryNSURLSessionTaskSearch.m in Sources */, 63FE711D20DA4C1000CDBAE8 /* SentryCrashCPU_arm64.c in Sources */, 844EDC77294144DB00C86F34 /* SentrySystemWrapper.mm in Sources */, D451ED5F2D92ECDE00C9BEA8 /* SentryReplayFrame.swift in Sources */, FAE579CC2E7DE14900B710F9 /* SentryFrameRemover.swift in Sources */, - FAB007812EA01B98001C806A /* SentryCrashSwift.swift in Sources */, D49480D72DC23FE300A3B6E9 /* SentrySessionReplayDelegate.swift in Sources */, FA67DCC12DDBD4C800896B02 /* SentrySDKLog+Configure.swift in Sources */, 6281C5722D3E4F12009D0978 /* DecodeArbitraryData.swift in Sources */, @@ -5820,6 +5833,7 @@ 84A305582BC9EF8C00D84283 /* SentryTraceProfiler.mm in Sources */, 7D082B8323C628790029866B /* SentryMeta.m in Sources */, D8CAC02F2BA0663E00E38F34 /* SentryVideoInfo.swift in Sources */, + FAAB95CD2EA18B2E0030A2DB /* SentryDependencyContainer.swift in Sources */, 63FE710720DA4C1000CDBAE8 /* SentryCrashStackCursor_SelfThread.m in Sources */, 63FE711120DA4C1000CDBAE8 /* SentryCrashDebug.c in Sources */, 7B883F49253D714C00879E62 /* SentryCrashUUIDConversion.c in Sources */, @@ -5870,7 +5884,7 @@ 63295AF71EF3C7DB002D4490 /* SentryNSDictionarySanitize.m in Sources */, 7B8ECBFC26498958005FE2EF /* SentryDefaultAppStateManager.m in Sources */, FA67DCF52DDBD4EA00896B02 /* SentryCurrentDateProvider.swift in Sources */, - FAAB96132EA31FA20030A2DB /* SentryDebugImageProvider.swift in Sources */, + FAAB96132EA31FA20030A2DB /* (null) in Sources */, FA67DCF62DDBD4EA00896B02 /* SentryViewRenderer.swift in Sources */, FA67DCF72DDBD4EA00896B02 /* SentryDefaultMaskRenderer.swift in Sources */, FA67DCF82DDBD4EA00896B02 /* SentryProfileOptions.swift in Sources */, @@ -5972,7 +5986,6 @@ 84AF45A729A7FFA500FBB177 /* SentryProfiledTracerConcurrency.mm in Sources */, 7DC8310C2398283C0043DD9A /* SentryCrashIntegration.m in Sources */, D45CE9752E5F454E00BFEDB2 /* SentryScreenshotSource.swift in Sources */, - FAAB967B2EA6D82F0030A2DB /* SentryWatchdogTerminationScopeObserver.swift in Sources */, FAE579BA2E7DBE9900B710F9 /* SentryGlobalEventProcessor.swift in Sources */, 03F84D3227DD4191008FE43F /* SentryProfiler.mm in Sources */, 635B3F391EBC6E2500A6176D /* SentryAsynchronousOperation.m in Sources */, @@ -6021,7 +6034,6 @@ D43B26D82D70A550007747FD /* SentryTraceOrigin.m in Sources */, FAE57C082E83092E00B710F9 /* SentryDispatchFactory.swift in Sources */, D8A3649C2C91AA3300AC569B /* SentryReplayApi.m in Sources */, - 7B42C48227E08F4B009B58C2 /* SentryDependencyContainer.m in Sources */, 639FCFAD1EBC811400778193 /* SentryUser.m in Sources */, FA94E7242E6F339400576666 /* SentryEnvelopeItemType.swift in Sources */, F41362152E1C568400B84443 /* SentryScopePersistentStore+Context.swift in Sources */, @@ -6087,6 +6099,7 @@ 0A2D8D5B289815C0008720F6 /* SentryBaseIntegration.m in Sources */, 639FCF991EBC7B9700778193 /* SentryEvent.m in Sources */, D820CDB72BB1895F00BA339D /* SentrySessionReplayIntegration.m in Sources */, + FAAB964C2EA688E50030A2DB /* SentryANRStoppedResultInternal.m in Sources */, 632F43521F581D5400A18A36 /* SentryCrashExceptionApplication.m in Sources */, FAE579842E7CF21800B710F9 /* SentryMigrateSessionInit.swift in Sources */, 620379DD2AFE1432005AC0C1 /* SentryBuildAppStartSpans.m in Sources */, @@ -6150,6 +6163,7 @@ FA65551A2E3018A3009917BC /* SentrySDKTests.swift in Sources */, 0A283E79291A67E000EF4126 /* SentryUIDeviceWrapperTests.swift in Sources */, 63FE720D20DA66EC00CDBAE8 /* SentryCrashNSErrorUtilTests.m in Sources */, + FAAB96542EA6A72E0030A2DB /* SentryCrashScopeHelper.m in Sources */, 69BEE6F72620729E006DF9DF /* UrlSessionDelegateSpy.swift in Sources */, A8AFFCD42907E0CA00967CD7 /* SentryRequestTests.swift in Sources */, 7BD4BD4D27EB31820071F4FF /* SentryClientReportTests.swift in Sources */, @@ -6214,6 +6228,7 @@ F4DCC9E52E4AACE0008ECE45 /* SentrySDKSettings+Equality.m in Sources */, 7BF536D124BDF3E7004FA6A2 /* SentryEnvelopeTests.swift in Sources */, 7B98D7E025FB73B900C5A389 /* SentryWatchdogTerminationTrackerTests.swift in Sources */, + FAF0F3D02EA7DD0D00E44E9B /* SentryANRTrackerTests.swift in Sources */, 63FE721620DA66EC00CDBAE8 /* SentryCrashReportFixer_Tests.m in Sources */, D4D12E7A2DFC608800DC45C4 /* SentryScreenshotOptionsTests.swift in Sources */, 7B6C5ED6264E62CA0010D138 /* SentryTransactionTests.swift in Sources */, @@ -6309,7 +6324,6 @@ 0A2D7BBA29152CBF008727AF /* SentryWatchdogTerminationScopeObserverTests.swift in Sources */, 7BD4BD4B27EB2DC20071F4FF /* SentryDiscardedEventTests.swift in Sources */, 63FE721A20DA66EC00CDBAE8 /* SentryCrashSysCtl_Tests.m in Sources */, - FAAB967E2EA6D9D80030A2DB /* SentryCrashScopeHelper.m in Sources */, F46E0BA82E6A19F900DAA75C /* SentryCrashWrapperTests.swift in Sources */, 7B88F30424BC8E6500ADF90A /* SentrySerializationTests.swift in Sources */, 843FB3432D156B9900558F18 /* SentryFeedbackTests.swift in Sources */, diff --git a/Sources/Sentry/SentryANRStoppedResultInternal.m b/Sources/Sentry/SentryANRStoppedResultInternal.m new file mode 100644 index 00000000000..63c7716b818 --- /dev/null +++ b/Sources/Sentry/SentryANRStoppedResultInternal.m @@ -0,0 +1,16 @@ +#import "SentryANRStoppedResultInternal.h" + +@implementation SentryANRStoppedResultInternal + +- (instancetype)initWithMinDuration:(NSTimeInterval)minDuration + maxDuration:(NSTimeInterval)maxDuration +{ + if (self = [super init]) { + _minDuration = minDuration; + _maxDuration = maxDuration; + return self; + } + return nil; +} + +@end diff --git a/Sources/Sentry/SentryANRTrackerV1.m b/Sources/Sentry/SentryANRTrackerV1.m index 0e5b4098b00..500277697f1 100644 --- a/Sources/Sentry/SentryANRTrackerV1.m +++ b/Sources/Sentry/SentryANRTrackerV1.m @@ -1,4 +1,5 @@ #import "SentryANRTrackerV1.h" +#import "SentryANRTrackerInternalDelegate.h" #import "SentryDependencyContainer.h" #import "SentryLogC.h" #import "SentrySwift.h" @@ -18,7 +19,7 @@ @interface SentryANRTrackerV1 () @property (nonatomic, strong) SentryCrashWrapper *crashWrapper; @property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueueWrapper; @property (nonatomic, strong) SentryThreadWrapper *threadWrapper; -@property (nonatomic, strong) NSHashTable> *listeners; +@property (nonatomic, strong) NSHashTable> *listeners; @property (nonatomic, assign) NSTimeInterval timeoutInterval; @end @@ -153,8 +154,8 @@ - (void)ANRDetected localListeners = [self.listeners allObjects]; } - for (id target in localListeners) { - [target anrDetectedWithType:SentryANRTypeUnknown]; + for (id target in localListeners) { + [target anrDetected:kSentryANRTypeUnknown]; } } @@ -165,14 +166,14 @@ - (void)ANRStopped targets = [self.listeners allObjects]; } - for (id target in targets) { + for (id target in targets) { // We intentionally don't measure the ANR duration, because V2 will replace V1, so it's not // worth the effort. - [target anrStoppedWithResult:nil]; + [target anrStopped:nil]; } } -- (void)addListener:(id)listener +- (void)addListener:(id)listener { @synchronized(self.listeners) { [self.listeners addObject:listener]; @@ -190,7 +191,7 @@ - (void)addListener:(id)listener } } -- (void)removeListener:(id)listener +- (void)removeListener:(id)listener { @synchronized(self.listeners) { [self.listeners removeObject:listener]; diff --git a/Sources/Sentry/SentryANRTrackerV2.m b/Sources/Sentry/SentryANRTrackerV2.m index c358cb5e1dd..8c62753dbf3 100644 --- a/Sources/Sentry/SentryANRTrackerV2.m +++ b/Sources/Sentry/SentryANRTrackerV2.m @@ -2,6 +2,8 @@ #if SENTRY_HAS_UIKIT +# import "SentryANRStoppedResultInternal.h" +# import "SentryANRTrackerInternalDelegate.h" # import "SentryDependencyContainer.h" # import "SentryLogC.h" # import "SentrySwift.h" @@ -22,7 +24,7 @@ @interface SentryANRTrackerV2 () @property (nonatomic, strong) SentryCrashWrapper *crashWrapper; @property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueueWrapper; @property (nonatomic, strong) SentryThreadWrapper *threadWrapper; -@property (nonatomic, strong) NSHashTable> *listeners; +@property (nonatomic, strong) NSHashTable> *listeners; @property (nonatomic, strong) SentryFramesTracker *framesTracker; @property (nonatomic, assign) NSTimeInterval timeoutInterval; @@ -130,9 +132,9 @@ - (void)detectANRs uint64_t framesDelayStartSystemTime = nowSystemTime - appHangStoppedInterval; - SentryFramesDelayResult *framesDelay = - [self.framesTracker getFramesDelay:framesDelayStartSystemTime - endSystemTimestamp:nowSystemTime]; + SentryFramesDelayResultSPI *framesDelay = + [self.framesTracker getFramesDelaySPI:framesDelayStartSystemTime + endSystemTimestamp:nowSystemTime]; if (framesDelay.delayDuration == -1) { continue; @@ -176,9 +178,9 @@ - (void)detectANRs uint64_t frameDelayStartSystemTime = nowSystemTime - timeoutIntervalInNanos; - SentryFramesDelayResult *framesDelayForTimeInterval = - [self.framesTracker getFramesDelay:frameDelayStartSystemTime - endSystemTimestamp:nowSystemTime]; + SentryFramesDelayResultSPI *framesDelayForTimeInterval = + [self.framesTracker getFramesDelaySPI:frameDelayStartSystemTime + endSystemTimestamp:nowSystemTime]; if (framesDelayForTimeInterval.delayDuration == -1) { continue; @@ -194,7 +196,7 @@ - (void)detectANRs reported = YES; lastAppHangStartedSystemTime = dateProvider.systemTime; - [self ANRDetected:SentryANRTypeFullyBlocking]; + [self ANRDetected:kSentryANRTypeFullyBlocking]; } NSTimeInterval nonFullyBlockingFramesDelayThreshold = self.timeoutInterval * 0.99; @@ -205,7 +207,7 @@ - (void)detectANRs reported = YES; lastAppHangStartedSystemTime = dateProvider.systemTime; - [self ANRDetected:SentryANRTypeNonFullyBlocking]; + [self ANRDetected:kSentryANRTypeNonFullyBlocking]; } } @@ -215,15 +217,15 @@ - (void)detectANRs } } -- (void)ANRDetected:(enum SentryANRType)type +- (void)ANRDetected:(SentryANRTypeInternal)type { NSArray *localListeners; @synchronized(self.listeners) { localListeners = [self.listeners allObjects]; } - for (id target in localListeners) { - [target anrDetectedWithType:type]; + for (id target in localListeners) { + [target anrDetected:type]; } } @@ -234,15 +236,15 @@ - (void)ANRStopped:(NSTimeInterval)hangDurationMinimum to:(NSTimeInterval)hangDu targets = [self.listeners allObjects]; } - SentryANRStoppedResult *result = - [[SentryANRStoppedResult alloc] initWithMinDuration:hangDurationMinimum - maxDuration:hangDurationMaximum]; - for (id target in targets) { - [target anrStoppedWithResult:result]; + SentryANRStoppedResultInternal *result = + [[SentryANRStoppedResultInternal alloc] initWithMinDuration:hangDurationMinimum + maxDuration:hangDurationMaximum]; + for (id target in targets) { + [target anrStopped:result]; } } -- (void)addListener:(id)listener +- (void)addListener:(id)listener { @synchronized(self.listeners) { [self.listeners addObject:listener]; @@ -260,7 +262,7 @@ - (void)addListener:(id)listener } } -- (void)removeListener:(id)listener +- (void)removeListener:(id)listener { @synchronized(self.listeners) { [self.listeners removeObject:listener]; diff --git a/Sources/Sentry/SentryDebugImageProviderInternal.m b/Sources/Sentry/SentryDebugImageProviderInternal.m index 3ff28f88a7e..094665c9f58 100644 --- a/Sources/Sentry/SentryDebugImageProviderInternal.m +++ b/Sources/Sentry/SentryDebugImageProviderInternal.m @@ -24,8 +24,7 @@ @implementation SentryDebugImageProviderInternal - (instancetype)init { - self = - [self initWithBinaryImageCache:SentryDependencyContainer.sharedInstance.binaryImageCache]; + self = [self initWithBinaryImageCache:SentryDependencies.binaryImageCache]; return self; } diff --git a/Sources/Sentry/SentryDelayedFramesTracker.m b/Sources/Sentry/SentryDelayedFramesTracker.m index 57f29cfb174..d805723fecb 100644 --- a/Sources/Sentry/SentryDelayedFramesTracker.m +++ b/Sources/Sentry/SentryDelayedFramesTracker.m @@ -11,6 +11,21 @@ NS_ASSUME_NONNULL_BEGIN +@implementation SentryFramesDelayResultObjC + +- (instancetype)initWithDelayDuration:(CFTimeInterval)delayDuration + framesContributingToDelayCount:(NSUInteger)frames +{ + if (self = [super init]) { + _delayDuration = delayDuration; + _framesContributingToDelayCount = frames; + return self; + } + return nil; +} + +@end + @interface SentryDelayedFramesTracker () @property (nonatomic, assign) CFTimeInterval keepDelayedFramesDuration; @@ -124,14 +139,14 @@ - (void)removeOldDelayedFrames [self.delayedFrames removeObjectsInRange:NSMakeRange(0, left)]; } -- (SentryFramesDelayResult *)getFramesDelay:(uint64_t)startSystemTimestamp - endSystemTimestamp:(uint64_t)endSystemTimestamp - isRunning:(BOOL)isRunning - slowFrameThreshold:(CFTimeInterval)slowFrameThreshold +- (SentryFramesDelayResultObjC *)getFramesDelayObjC:(uint64_t)startSystemTimestamp + endSystemTimestamp:(uint64_t)endSystemTimestamp + isRunning:(BOOL)isRunning + slowFrameThreshold:(CFTimeInterval)slowFrameThreshold { - SentryFramesDelayResult *cantCalculateFrameDelayReturnValue = - [[SentryFramesDelayResult alloc] initWithDelayDuration:-1.0 - framesContributingToDelayCount:0]; + SentryFramesDelayResultObjC *cantCalculateFrameDelayReturnValue = + [[SentryFramesDelayResultObjC alloc] initWithDelayDuration:-1.0 + framesContributingToDelayCount:0]; if (isRunning == NO) { SENTRY_LOG_DEBUG(@"Not calculating frames delay because frames tracker isn't running."); @@ -219,9 +234,9 @@ - (SentryFramesDelayResult *)getFramesDelay:(uint64_t)startSystemTimestamp framesCount++; } - SentryFramesDelayResult *data = - [[SentryFramesDelayResult alloc] initWithDelayDuration:delay - framesContributingToDelayCount:framesCount]; + SentryFramesDelayResultObjC *data = + [[SentryFramesDelayResultObjC alloc] initWithDelayDuration:delay + framesContributingToDelayCount:framesCount]; return data; } diff --git a/Sources/Sentry/SentryDependencyContainer.m b/Sources/Sentry/SentryDependencyContainer.m deleted file mode 100644 index a6ec144e033..00000000000 --- a/Sources/Sentry/SentryDependencyContainer.m +++ /dev/null @@ -1,447 +0,0 @@ -#import "SentryANRTrackerV1.h" - -#import "SentryDefaultThreadInspector.h" -#import "SentryDelayedFramesTracker.h" -#import "SentryDependencyContainerSwiftHelper.h" -#import "SentryInternalCDefines.h" -#import "SentryInternalDefines.h" -#import "SentryLogC.h" -#import "SentryOptions+Private.h" -#import "SentrySDK+Private.h" -#import "SentrySwift.h" -#import "SentrySystemWrapper.h" -#import -#import -#import -#import -#import -#import - -#if SENTRY_HAS_UIKIT -# import "SentryANRTrackerV2.h" -# import -#endif // SENTRY_HAS_UIKIT - -/** - * Macro for implementing lazy initialization with a double-checked lock. The double-checked lock - * speeds up the dependency retrieval by around 5%, so it's worth having it. Measured with - * self.measure in unit tests. - */ -#define SENTRY_LAZY_INIT(instance, initBlock) \ - if (instance == nil) { \ - @synchronized(sentryDependencyContainerDependenciesLock) { \ - if (instance == nil) { \ - instance = initBlock; \ - } \ - } \ - } \ - return instance; - -#define SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK \ - SENTRY_DISABLE_THREAD_SANITIZER("Double-checked locks produce false alarms.") - -typedef id _Nullable (^SentryApplicationProviderBlock)(void); -// Declare the application provider block at the top level to prevent capturing 'self' -// from the dependency container, which would create cyclic dependencies and memory leaks. -SentryApplicationProviderBlock defaultApplicationProvider = ^id _Nullable() -{ -#if SENTRY_HAS_UIKIT - return UIApplication.sharedApplication; -#elif TARGET_OS_OSX - return NSApplication.sharedApplication; -#endif - return nil; -}; - -@interface SentryANRTrackerV1 () -@end - -@interface SentryFileManager () -@end - -#if SENTRY_HAS_UIKIT -@interface SentryDefaultRedactOptions () -@end - -@interface SentryWatchdogTerminationScopeObserver () -@end - -@interface SentryDelayedFramesTracker () -@end - -@interface SentryANRTrackerV2 () -@end -#endif - -@interface SentryDependencyContainer () - -@property (nonatomic, strong) SentryANRTracker *anrTracker; - -@end - -@implementation SentryDependencyContainer - -static SentryDependencyContainer *instance; -static NSObject *sentryDependencyContainerDependenciesLock; -static NSObject *sentryDependencyContainerInstanceLock; -static BOOL isInitialializingDependencyContainer = NO; - -+ (void)initialize -{ - if (self == [SentryDependencyContainer class]) { - // We use two locks, because we don't want the dependencies to block the instance lock. - // Using two locks speeds up the accessing the dependencies around 5%, which is worth having - // the extra lock. Measured with self.measure in unit tests. - sentryDependencyContainerInstanceLock = [[NSObject alloc] init]; - sentryDependencyContainerDependenciesLock = [[NSObject alloc] init]; - - instance = [[SentryDependencyContainer alloc] init]; - } -} - -+ (instancetype)sharedInstance -{ - // This synchronization adds around 5% slowdown compared to no synchronization. - // As we don't call this method in a tight loop, it's acceptable. Measured with self.measure in - // unit tests. - @synchronized(sentryDependencyContainerInstanceLock) { - - if (isInitialializingDependencyContainer) { - SENTRY_GRACEFUL_FATAL( - @"SentryDependencyContainer is currently being initialized, so your requested " - @"dependency via sharedInstance will be nil. You MUST NOT call sharedInstance in " - @"your initializer. Instead, pass the dependency you're trying to get via the " - @"constructor. If the stacktrace doesn't point to the root cause, the easiest way " - @"to identify the root caus is to set a breakpoint exactly here and then check the " - @"stacktrace."); - } - - return instance; - } -} - -+ (void)reset -{ - @synchronized(sentryDependencyContainerInstanceLock) { - [instance->_reachability removeAllObservers]; - -#if SENTRY_HAS_UIKIT - [instance->_framesTracker stop]; -#endif // SENTRY_HAS_UIKIT - - // We create a new instance to reset all dependencies to a fresh state. - // Why don't we reset all dependencies manually so we can avoid using a lock in - // sharedInstance? Good question. This approach comes with the following problems: - // - // 1. We need a lock for all properties, including the init dependencies. - // - // 2. When adding a new dependency it is very easy to forget adding it to the reset list - // - // 3. The lock in sharedInstance only caused around a 5% overhead compared to not using a - // lock. Measured with self.measure in unit tests. So not having locks for all the init - // dependencies is as efficient as having a lock for the instance in sharedInstance. - instance = [[SentryDependencyContainer alloc] init]; - } -} - -- (instancetype)init -{ - if (self = [super init]) { - isInitialializingDependencyContainer = YES; - - _dispatchQueueWrapper = SentryDependencies.dispatchQueueWrapper; - _random = SentryDependencies.random; - _threadWrapper = SentryDependencies.threadWrapper; - _binaryImageCache = [[SentryBinaryImageCache alloc] init]; - _dateProvider = SentryDependencies.dateProvider; - - _notificationCenterWrapper = SentryDependencies.notificationCenterWrapper; - - _processInfoWrapper = SentryDependencies.processInfoWrapper; - _crashWrapper = [[SentryCrashWrapper alloc] initWithProcessInfoWrapper:_processInfoWrapper]; -#if SENTRY_HAS_UIKIT - _uiDeviceWrapper = SentryDependencies.uiDeviceWrapper; - _threadsafeApplication = [[SentryThreadsafeApplication alloc] - initWithApplicationProvider:defaultApplicationProvider - notificationCenter:_notificationCenterWrapper]; -#endif // SENTRY_HAS_UIKIT - - _extraContextProvider = - [[SentryExtraContextProvider alloc] initWithCrashWrapper:_crashWrapper - processInfoWrapper:_processInfoWrapper -#if TARGET_OS_IOS && SENTRY_HAS_UIKIT - deviceWrapper:_uiDeviceWrapper -#endif // TARGET_OS_IOS && SENTRY_HAS_UIKIT - ]; - - _sysctlWrapper = SentryDependencies.sysctlWrapper; - - SentryRetryAfterHeaderParser *retryAfterHeaderParser = [[SentryRetryAfterHeaderParser alloc] - initWithHttpDateParser:[[SentryHttpDateParser alloc] init] - currentDateProvider:_dateProvider]; - SentryRateLimitParser *rateLimitParser = - [[SentryRateLimitParser alloc] initWithCurrentDateProvider:_dateProvider]; - - _rateLimits = - [[SentryDefaultRateLimits alloc] initWithRetryAfterHeaderParser:retryAfterHeaderParser - andRateLimitParser:rateLimitParser - currentDateProvider:_dateProvider]; - - _reachability = [[SentryReachability alloc] init]; - - isInitialializingDependencyContainer = NO; - } - return self; -} - -- (nullable id)application -{ -#if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) - id override = self.applicationOverride; - if (override) { - return override; - } -#endif - return defaultApplicationProvider(); -} - -- (nullable SentryFileManager *)fileManager SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ - SENTRY_LAZY_INIT(_fileManager, ({ - NSError *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); - } - manager; - })); -} - -- (SentryAppStateManager *)appStateManager SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ - SENTRY_LAZY_INIT(_appStateManager, - [[SentryAppStateManager alloc] initWithOptions:SentrySDKInternal.options - crashWrapper:self.crashWrapper - fileManager:self.fileManager - sysctlWrapper:self.sysctlWrapper]); -} -- (SentryThreadInspector *)threadInspector -{ - return SentryDependencies.threadInspector; -} - -- (SentryFileIOTracker *)fileIOTracker -{ - return SentryDependencies.fileIOTracker; -} - -- (SentryCrashSwift *)crashReporter SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ - SENTRY_LAZY_INIT(_crashReporter, - [[SentryCrashSwift alloc] initWith:SentrySDKInternal.options.cacheDirectoryPath]); -} - -- (SentryANRTracker *)getANRTracker:(NSTimeInterval)timeout - SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ -#if SENTRY_HAS_UIKIT - SENTRY_LAZY_INIT(_anrTracker, - [[SentryANRTracker alloc] - initWithHelper:[[SentryANRTrackerV2 alloc] - initWithTimeoutInterval:timeout - crashWrapper:self.crashWrapper - dispatchQueueWrapper:self.dispatchQueueWrapper - threadWrapper:self.threadWrapper - framesTracker:self.framesTracker]]); -#else - SENTRY_LAZY_INIT(_anrTracker, - [[SentryANRTracker alloc] - initWithHelper:[[SentryANRTrackerV1 alloc] - initWithTimeoutInterval:timeout - crashWrapper:self.crashWrapper - dispatchQueueWrapper:self.dispatchQueueWrapper - threadWrapper:self.threadWrapper]]); - ; -#endif -} - -#if SENTRY_TARGET_REPLAY_SUPPORTED -- (nonnull SentryScreenshotSource *)screenshotSource SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ - @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. - SentryOptions *_Nonnull options - = SENTRY_UNWRAP_NULLABLE(SentryOptions, SentrySDKInternal.options); - - id viewRenderer; - if ([SentryDependencyContainerSwiftHelper viewRendererV2Enabled:options]) { - viewRenderer = [[SentryViewRendererV2 alloc] - initWithEnableFastViewRendering:[SentryDependencyContainerSwiftHelper - fastViewRenderingEnabled:options]]; - } else { - viewRenderer = [[SentryDefaultViewRenderer alloc] init]; - } - - SentryViewPhotographer *photographer = [[SentryViewPhotographer alloc] - initWithRenderer:viewRenderer - redactOptions:[SentryDependencyContainerSwiftHelper redactOptions:options] - enableMaskRendererV2:[SentryDependencyContainerSwiftHelper - viewRendererV2Enabled:options]]; - _screenshotSource = [[SentryScreenshotSource alloc] initWithPhotographer:photographer]; - } - - return _screenshotSource; - } -} -#endif // SENTRY_HAS_UIKIT - -#if SENTRY_UIKIT_AVAILABLE -- (SentryViewHierarchyProvider *)viewHierarchyProvider SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ -# if SENTRY_HAS_UIKIT - - SENTRY_LAZY_INIT(_viewHierarchyProvider, - [[SentryViewHierarchyProvider alloc] - initWithDispatchQueueWrapper:self.dispatchQueueWrapper - applicationProvider:defaultApplicationProvider]); -# else - SENTRY_LOG_DEBUG( - @"SentryDependencyContainer.viewHierarchyProvider only works with UIKit " - @"enabled. Ensure you're using the right configuration of Sentry that links UIKit."); - return nil; -# endif // SENTRY_HAS_UIKIT -} - -- (SentryUIViewControllerPerformanceTracker *) - uiViewControllerPerformanceTracker SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ -# if SENTRY_HAS_UIKIT - SENTRY_LAZY_INIT(_uiViewControllerPerformanceTracker, - [[SentryUIViewControllerPerformanceTracker alloc] init]); -# else - SENTRY_LOG_DEBUG(@"SentryDependencyContainer.uiViewControllerPerformanceTracker only works " - @"with UIKit enabled. Ensure you're " - @"using the right configuration of Sentry that links UIKit."); - return nil; -# endif // SENTRY_HAS_UIKIT -} - -- (SentryFramesTracker *)framesTracker SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ -# if SENTRY_HAS_UIKIT - SENTRY_LAZY_INIT(_framesTracker, - [[SentryFramesTracker alloc] - initWithDisplayLinkWrapper:[[SentryDisplayLinkWrapper alloc] init] - dateProvider:self.dateProvider - dispatchQueueWrapper:self.dispatchQueueWrapper - notificationCenter:self.notificationCenterWrapper - delayedFramesTracker: - [[SentryDelayedFramesTracker alloc] - initWithKeepDelayedFramesDuration:SENTRY_AUTO_TRANSACTION_MAX_DURATION - dateProvider:self.dateProvider]]); -# else - SENTRY_LOG_DEBUG( - @"SentryDependencyContainer.framesTracker only works with UIKit enabled. Ensure you're " - @"using the right configuration of Sentry that links UIKit."); - return nil; -# endif // SENTRY_HAS_UIKIT -} - -- (SentrySwizzleWrapper *)swizzleWrapper SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ -# if SENTRY_HAS_UIKIT - SENTRY_LAZY_INIT(_swizzleWrapper, [[SentrySwizzleWrapper alloc] init]); -# else - SENTRY_LOG_DEBUG( - @"SentryDependencyContainer.swizzleWrapper only works with UIKit enabled. Ensure you're " - @"using the right configuration of Sentry that links UIKit."); - return nil; -# endif // SENTRY_HAS_UIKIT -} -#endif // SENTRY_UIKIT_AVAILABLE - -- (SentryDispatchFactory *)dispatchFactory SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ - SENTRY_LAZY_INIT(_dispatchFactory, [[SentryDispatchFactory alloc] init]); -} - -- (SentryNSTimerFactory *)timerFactory SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ - SENTRY_LAZY_INIT(_timerFactory, [[SentryNSTimerFactory alloc] init]); -} - -#if SENTRY_HAS_METRIC_KIT -- (SentryMXManager *)metricKitManager SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ - // Disable crash diagnostics as we only use it for validation of the symbolication - // of stacktraces, because crashes are easy to trigger for MetricKit. We don't want - // crash reports of MetricKit in production as we have SentryCrash. - SENTRY_LAZY_INIT( - _metricKitManager, [[SentryMXManager alloc] initWithDisableCrashDiagnostics:YES]); -} - -#endif // SENTRY_HAS_METRIC_KIT - -- (SentryScopePersistentStore *_Nullable) - scopePersistentStore SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ - SENTRY_LAZY_INIT(_scopePersistentStore, - [[SentryScopePersistentStore alloc] initWithFileManager:self.fileManager]); -} - -- (SentryDebugImageProvider *)debugImageProvider SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ - // SentryDebugImageProvider is public, so we can't initialize the dependency in - // SentryDependencyInitialize because the SentryDebugImageProvider.init uses the - // SentryDependencyContainer, which doesn't work because of a chicken egg problem. For more - // information check SentryDebugImageProvider.sharedInstance. - SENTRY_LAZY_INIT(_debugImageProvider, [[SentryDebugImageProvider alloc] init]); -} - -#if SENTRY_HAS_UIKIT -- (id)getWatchdogTerminationScopeObserverWithOptions:(SentryOptions *)options -{ - // This method is only a factory, therefore do not keep a reference. - // The scope observer will be created each time it is needed. - return [[SentryWatchdogTerminationScopeObserver alloc] - initWithMaxBreadcrumbs:options.maxBreadcrumbs - attributesProcessor:self.watchdogTerminationAttributesProcessor]; -} - -- (SentryWatchdogTerminationAttributesProcessor *) - watchdogTerminationAttributesProcessor SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ - SENTRY_LAZY_INIT(_watchdogTerminationAttributesProcessor, - [[SentryWatchdogTerminationAttributesProcessor alloc] - initWithDispatchQueueWrapper: - [self.dispatchFactory - createUtilityQueue:"io.sentry.watchdog-termination-tracking.fields-processor" - relativePriority:0] - scopePersistentStore:self.scopePersistentStore]) -} -#endif - -- (SentryGlobalEventProcessor *)globalEventProcessor SENTRY_THREAD_SANITIZER_DOUBLE_CHECKED_LOCK -{ - SENTRY_LAZY_INIT(_globalEventProcessor, [[SentryGlobalEventProcessor alloc] init]) -} - -- (SentrySessionTracker *)getSessionTrackerWithOptions:(SentryOptions *)options -{ - return [[SentrySessionTracker alloc] initWithOptions:options - applicationProvider:defaultApplicationProvider - 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/SentrySpan.m b/Sources/Sentry/SentrySpan.m index a4da3d52353..ce331e5e4fd 100644 --- a/Sources/Sentry/SentrySpan.m +++ b/Sources/Sentry/SentrySpan.m @@ -278,7 +278,7 @@ - (void)finishWithStatus:(SentrySpanStatus)status #if SENTRY_HAS_UIKIT if (_framesTracker.isRunning) { CFTimeInterval framesDelay = [_framesTracker - getFramesDelay:_startSystemTime + getFramesDelaySPI:_startSystemTime endSystemTimestamp:SentryDependencyContainer.sharedInstance.dateProvider.systemTime] .delayDuration; diff --git a/Sources/Sentry/SentryTracer.m b/Sources/Sentry/SentryTracer.m index 0efeb081399..1d8da97c1df 100644 --- a/Sources/Sentry/SentryTracer.m +++ b/Sources/Sentry/SentryTracer.m @@ -871,7 +871,7 @@ - (void)addFrameStatistics SentryFramesTracker *framesTracker = SentryDependencyContainer.sharedInstance.framesTracker; if (framesTracker.isRunning) { CFTimeInterval framesDelay = [framesTracker - getFramesDelay:self.startSystemTime + getFramesDelaySPI:self.startSystemTime endSystemTimestamp:SentryDependencyContainer.sharedInstance.dateProvider.systemTime] .delayDuration; diff --git a/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h b/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h index d4b074b4384..8b137891791 100644 --- a/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h +++ b/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h @@ -1,150 +1 @@ -#if __has_include() -# import -#else -# import "SentryDefines.h" -#endif -@class SentryBinaryImageCache; -@class SentryCrashSwift; -@class SentryCrashWrapper; -@class SentryDebugImageProvider; -@class SentryDispatchFactory; -@class SentryDispatchQueueWrapper; -@class SentryExtraContextProvider; -@class SentryFileManager; -@class SentryNSTimerFactory; -@class SentrySwizzleWrapper; -@class SentrySysctl; -@class SentryThreadsafeApplication; -@class SentryThreadWrapper; -@class SentryFileIOTracker; -@class SentryScopePersistentStore; -@class SentryOptions; -@class SentryAppStateManager; -@class SentrySessionTracker; -@class SentryGlobalEventProcessor; -@class SentryThreadInspector; -@class SentryANRTracker; -@class SentryReachability; - -@protocol SentryRandomProtocol; -@protocol SentryCurrentDateProvider; -@protocol SentryRateLimits; -@protocol SentryApplication; -@protocol SentryProcessInfoSource; -@protocol SentryNSNotificationCenterWrapper; -@protocol SentryObjCRuntimeWrapper; - -#if SENTRY_HAS_METRIC_KIT -@class SentryMXManager; -#endif // SENTRY_HAS_METRIC_KIT - -#if SENTRY_UIKIT_AVAILABLE -@class SentryFramesTracker; -@class SentryScreenshotSource; -@class SentryViewHierarchyProvider; -@class SentryWatchdogTerminationAttributesProcessor; -@class SentryUIViewControllerPerformanceTracker; - -@protocol SentryScopeObserver; -#endif // SENTRY_UIKIT_AVAILABLE - -#if SENTRY_HAS_UIKIT -@protocol SentryUIDeviceWrapper; -#endif // TARGET_OS_IOS - -NS_ASSUME_NONNULL_BEGIN - -/** - * The dependency container is optimized to use as few locks as possible and to only keep the - * required dependencies in memory. It splits its dependencies into two groups. - * - * Init Dependencies: These are mandatory dependencies required to run the SDK, no matter the - * options. The dependency container initializes them in init and uses no locks for efficiency. - * - * Lazy Dependencies: These dependencies either have some state or aren't always required and, - * therefore, get initialized lazily to minimize the memory footprint. - */ -@interface SentryDependencyContainer : NSObject -SENTRY_NO_INIT - -+ (instancetype)sharedInstance; - -/** - * Resets all dependencies. - */ -+ (void)reset; - -#pragma mark - Init Dependencies - -@property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueueWrapper; -@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) id notificationCenterWrapper; -@property (nonatomic, strong) SentryCrashWrapper *crashWrapper; -@property (nonatomic, strong) id processInfoWrapper; -@property (nonatomic, strong) SentrySysctl *sysctlWrapper; -@property (nonatomic, strong) id rateLimits; -@property (nonatomic, strong) SentryThreadsafeApplication *threadsafeApplication; - -@property (nonatomic, strong) SentryReachability *reachability; - -#if SENTRY_HAS_UIKIT -@property (nonatomic, strong) id uiDeviceWrapper; -#endif // TARGET_OS_IOS - -#pragma mark - Lazy Dependencies - -@property (nonatomic, strong, nullable) SentryFileManager *fileManager; -@property (nonatomic, strong) SentryAppStateManager *appStateManager; -@property (nonatomic, strong, readonly) SentryThreadInspector *threadInspector; -@property (nonatomic, strong, readonly) SentryFileIOTracker *fileIOTracker; -@property (nonatomic, strong) SentryCrashSwift *crashReporter; -@property (nonatomic, strong, nullable) SentryScopePersistentStore *scopePersistentStore; -@property (nonatomic, strong) SentryDebugImageProvider *debugImageProvider; - -- (SentryANRTracker *)getANRTracker:(NSTimeInterval)timeout; - -- (nullable id)application; - -@property (nonatomic, strong) SentryDispatchFactory *dispatchFactory; -@property (nonatomic, strong) SentryNSTimerFactory *timerFactory; - -@property (nonatomic, strong) SentrySwizzleWrapper *swizzleWrapper; -#if SENTRY_UIKIT_AVAILABLE -@property (nonatomic, strong) SentryFramesTracker *framesTracker; -@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_UNAVAILABLE(tvos, watchos); -#endif // SENTRY_HAS_METRIC_KIT -@property (nonatomic, strong) id objcRuntimeWrapper; - -#if SENTRY_HAS_UIKIT -- (id)getWatchdogTerminationScopeObserverWithOptions:(SentryOptions *)options; -@property (nonatomic, strong) - SentryWatchdogTerminationAttributesProcessor *watchdogTerminationAttributesProcessor; -#endif - -@property (nonatomic, strong) SentryGlobalEventProcessor *globalEventProcessor; -- (SentrySessionTracker *)getSessionTrackerWithOptions:(SentryOptions *)options; - -#if defined(SENTRY_TEST) || defined(SENTRY_TEST_CI) -// Some tests rely on this value being grabbed from the global dependency container -// rather than using dependency injection. -@property (nonatomic, strong) id applicationOverride; -#endif - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryANRStoppedResultInternal.h b/Sources/Sentry/include/SentryANRStoppedResultInternal.h new file mode 100644 index 00000000000..85213de8c2f --- /dev/null +++ b/Sources/Sentry/include/SentryANRStoppedResultInternal.h @@ -0,0 +1,12 @@ +#import + +@interface SentryANRStoppedResultInternal : NSObject + +@property (nonatomic, readonly) NSTimeInterval minDuration; + +@property (nonatomic, readonly) NSTimeInterval maxDuration; + +- (instancetype)initWithMinDuration:(NSTimeInterval)minDuration + maxDuration:(NSTimeInterval)maxDuration; + +@end diff --git a/Sources/Sentry/include/SentryANRTrackerInternalDelegate.h b/Sources/Sentry/include/SentryANRTrackerInternalDelegate.h new file mode 100644 index 00000000000..ab92a3f761b --- /dev/null +++ b/Sources/Sentry/include/SentryANRTrackerInternalDelegate.h @@ -0,0 +1,23 @@ +#import + +@class SentryANRStoppedResultInternal; + +typedef NS_ENUM(NSInteger, SentryANRTypeInternal) { + kSentryANRTypeFatalFullyBlocking, + kSentryANRTypeFatalNonFullyBlocking, + kSentryANRTypeFullyBlocking, + kSentryANRTypeNonFullyBlocking, + kSentryANRTypeUnknown +}; + +NS_ASSUME_NONNULL_BEGIN + +@protocol SentryANRTrackerInternalDelegate + +- (void)anrDetected:(SentryANRTypeInternal)type; + +- (void)anrStopped:(nullable SentryANRStoppedResultInternal *)result; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryANRTrackerV1.h b/Sources/Sentry/include/SentryANRTrackerV1.h index 072f47e6b58..9d882ac0118 100644 --- a/Sources/Sentry/include/SentryANRTrackerV1.h +++ b/Sources/Sentry/include/SentryANRTrackerV1.h @@ -4,7 +4,7 @@ @class SentryCrashWrapper; @class SentryDispatchQueueWrapper; @class SentryThreadWrapper; -@protocol SentryANRTrackerDelegate; +@protocol SentryANRTrackerInternalDelegate; NS_ASSUME_NONNULL_BEGIN @@ -31,8 +31,8 @@ SENTRY_NO_INIT dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper threadWrapper:(SentryThreadWrapper *)threadWrapper; -- (void)addListener:(id)listener; -- (void)removeListener:(id)listener; +- (void)addListener:(id)listener; +- (void)removeListener:(id)listener; - (void)clear; @end diff --git a/Sources/Sentry/include/SentryANRTrackerV2.h b/Sources/Sentry/include/SentryANRTrackerV2.h index ce8dd7f5038..4070f71a673 100644 --- a/Sources/Sentry/include/SentryANRTrackerV2.h +++ b/Sources/Sentry/include/SentryANRTrackerV2.h @@ -6,7 +6,7 @@ @class SentryDispatchQueueWrapper; @class SentryThreadWrapper; @class SentryFramesTracker; -@protocol SentryANRTrackerDelegate; +@protocol SentryANRTrackerInternalDelegate; NS_ASSUME_NONNULL_BEGIN @@ -31,8 +31,8 @@ SENTRY_NO_INIT threadWrapper:(SentryThreadWrapper *)threadWrapper framesTracker:(SentryFramesTracker *)framesTracker; -- (void)addListener:(id)listener; -- (void)removeListener:(id)listener; +- (void)addListener:(id)listener; +- (void)removeListener:(id)listener; - (void)clear; @end diff --git a/Sources/Sentry/include/SentryDelayedFramesTracker.h b/Sources/Sentry/include/SentryDelayedFramesTracker.h index 2ebd15029a1..908c1f87884 100644 --- a/Sources/Sentry/include/SentryDelayedFramesTracker.h +++ b/Sources/Sentry/include/SentryDelayedFramesTracker.h @@ -3,10 +3,16 @@ #if SENTRY_HAS_UIKIT @protocol SentryCurrentDateProvider; -@class SentryFramesDelayResult; NS_ASSUME_NONNULL_BEGIN +@interface SentryFramesDelayResultObjC : NSObject + +@property (nonatomic, readonly) CFTimeInterval delayDuration; +@property (nonatomic, readonly) NSUInteger framesContributingToDelayCount; + +@end + @interface SentryDelayedFramesTracker : NSObject SENTRY_NO_INIT @@ -59,10 +65,10 @@ SENTRY_NO_INIT * @param isRunning Wether the frames tracker is running or not. * @param slowFrameThreshold The threshold for a slow frame. For 60 fps this is roughly 16.67 ms. */ -- (SentryFramesDelayResult *)getFramesDelay:(uint64_t)startSystemTimestamp - endSystemTimestamp:(uint64_t)endSystemTimestamp - isRunning:(BOOL)isRunning - slowFrameThreshold:(CFTimeInterval)slowFrameThreshold; +- (SentryFramesDelayResultObjC *)getFramesDelayObjC:(uint64_t)startSystemTimestamp + endSystemTimestamp:(uint64_t)endSystemTimestamp + isRunning:(BOOL)isRunning + slowFrameThreshold:(CFTimeInterval)slowFrameThreshold; @end diff --git a/Sources/Sentry/include/SentryPrivate.h b/Sources/Sentry/include/SentryPrivate.h index 942d41ae0ec..93ae7fb6acf 100644 --- a/Sources/Sentry/include/SentryPrivate.h +++ b/Sources/Sentry/include/SentryPrivate.h @@ -1,6 +1,8 @@ // Sentry internal headers that are needed for swift code; you cannot import headers that depend on // public interfaces here #import "NSLocale+Sentry.h" +#import "SentryANRStoppedResultInternal.h" +#import "SentryANRTrackerInternalDelegate.h" #import "SentryBinaryImageCacheCallbacks.h" #import "SentryConcurrentRateLimitsDictionary.h" #import "SentryCrashBinaryImageCache.h" @@ -22,6 +24,8 @@ // Headers that also import SentryDefines should be at the end of this list // otherwise it wont compile +#import "SentryANRTrackerV1.h" +#import "SentryANRTrackerV2.h" #import "SentryAsyncLog.h" #import "SentryClient+Logs.h" #import "SentryContinuousProfiler.h" diff --git a/Sources/Swift/Core/Integrations/ANR/SentryANRTracker.swift b/Sources/Swift/Core/Integrations/ANR/SentryANRTracker.swift index 2431083f6e3..54a5a27f598 100644 --- a/Sources/Swift/Core/Integrations/ANR/SentryANRTracker.swift +++ b/Sources/Swift/Core/Integrations/ANR/SentryANRTracker.swift @@ -1,19 +1,32 @@ +@_implementationOnly import _SentryPrivate import Foundation @_spi(Private) @objc public final class SentryANRTracker: NSObject { - let helper: SentryANRTrackerProtocol + let helper: SentryANRTrackerInternalProtocol + var mapping = [ObjectIdentifier: DelegateWrapper]() - @objc public init(helper: SentryANRTrackerProtocol) { + init(helper: SentryANRTrackerInternalProtocol) { self.helper = helper } + // Since this is public to ObjC it can only use parameters defined in Swift + // We have to convert the Swift type to the internal ObjC type. @objc(addListener:) public func add(listener: SentryANRTrackerDelegate) { - helper.addListener(listener) + // Remove entries that no longer have the weak reference + mapping = mapping.filter { _, value in + value.helper != nil + } + let wrapped = DelegateWrapper(helper: listener) + mapping[ObjectIdentifier(listener)] = wrapped + helper.addListener(wrapped) } @objc(removeListener:) public func remove(listener: SentryANRTrackerDelegate) { - helper.removeListener(listener) + guard let mapped = mapping[ObjectIdentifier(listener)] else { + return + } + helper.removeListener(mapped) } @objc public func clear() { @@ -21,9 +34,47 @@ import Foundation } } -@_spi(Private) @objc public protocol SentryANRTrackerProtocol { - @objc func addListener(_ listender: SentryANRTrackerDelegate) - @objc func removeListener(_ listener: SentryANRTrackerDelegate) +final class DelegateWrapper: NSObject, SentryANRTrackerInternalDelegate { + func anrDetected(_ type: SentryANRTypeInternal) { + helper?.anrDetected(type: SentryANRType.fromInternal(internal: type)) + } + + func anrStopped(_ result: SentryANRStoppedResultInternal?) { + helper?.anrStopped(result: result.map { SentryANRStoppedResult(minDuration: $0.minDuration, maxDuration: $0.maxDuration ) }) + } + + weak var helper: SentryANRTrackerDelegate? + + init(helper: SentryANRTrackerDelegate) { + self.helper = helper + } +} + +extension SentryANRType { + static func fromInternal(internal: SentryANRTypeInternal) -> SentryANRType { + switch `internal` { + case SentryANRTypeInternal.fatalFullyBlocking: + return .fatalFullyBlocking + case SentryANRTypeInternal.fatalNonFullyBlocking: + return .fatalNonFullyBlocking + case SentryANRTypeInternal.fullyBlocking: + return .fullyBlocking + case SentryANRTypeInternal.nonFullyBlocking: + return .nonFullyBlocking + case SentryANRTypeInternal.unknown: + return .unknown + @unknown default: + return .unknown + } + } +} + +// The V1/V2 tracker will conform to this +@objc protocol SentryANRTrackerInternalProtocol { + // The types of this protocol must be defined in ObjC since it is conformed to by + // classes defined in ObjC. + @objc func addListener(_ listender: SentryANRTrackerInternalDelegate) + @objc func removeListener(_ listener: SentryANRTrackerInternalDelegate) /// Only used for tests. func clear() diff --git a/Sources/Swift/Core/Integrations/FramesTracking/SentryDelayedFramesTrackerWrapper.swift b/Sources/Swift/Core/Integrations/FramesTracking/SentryDelayedFramesTrackerWrapper.swift index c71e9eb54a1..b6c5ad97e9b 100644 --- a/Sources/Swift/Core/Integrations/FramesTracking/SentryDelayedFramesTrackerWrapper.swift +++ b/Sources/Swift/Core/Integrations/FramesTracking/SentryDelayedFramesTrackerWrapper.swift @@ -1,6 +1,6 @@ import Foundation -@objc @_spi(Private) public protocol SentryDelayedFramesTrackerWrapper { +protocol SentryDelayedFramesTrackerWrapper { func reset() func setPreviousFrameSystemTimestamp(_ previousFrameSystemTimestamp: UInt64) func getFramesDelay(_ startSystemTimestamp: UInt64, endSystemTimestamp: UInt64, isRunning: Bool, slowFrameThreshold: CFTimeInterval) -> SentryFramesDelayResult diff --git a/Sources/Swift/Core/Integrations/FramesTracking/SentryFramesDelayResult.swift b/Sources/Swift/Core/Integrations/FramesTracking/SentryFramesDelayResult.swift index 8a859582fb0..3819b9a57cf 100644 --- a/Sources/Swift/Core/Integrations/FramesTracking/SentryFramesDelayResult.swift +++ b/Sources/Swift/Core/Integrations/FramesTracking/SentryFramesDelayResult.swift @@ -1,12 +1,24 @@ import Foundation -@objcMembers -@_spi(Private) public class SentryFramesDelayResult: NSObject { +final class SentryFramesDelayResult { /// The frames delay for the passed time period. If frame delay can't be calculated this is -1. - public let delayDuration: CFTimeInterval - public let framesContributingToDelayCount: UInt + let delayDuration: CFTimeInterval + let framesContributingToDelayCount: UInt - public init(delayDuration: CFTimeInterval, framesContributingToDelayCount: UInt) { + init(delayDuration: CFTimeInterval, framesContributingToDelayCount: UInt) { + self.delayDuration = delayDuration + self.framesContributingToDelayCount = framesContributingToDelayCount + } +} + +// This class is needed for compatibility with ObjC. +// The pure Swift class also needs to exist since it is used in an internal protocol. +@objc +@_spi(Private) public final class SentryFramesDelayResultSPI: NSObject { + @objc public let delayDuration: CFTimeInterval + @objc public let framesContributingToDelayCount: UInt + + init(delayDuration: CFTimeInterval, framesContributingToDelayCount: UInt) { self.delayDuration = delayDuration self.framesContributingToDelayCount = framesContributingToDelayCount } diff --git a/Sources/Swift/Core/Integrations/FramesTracking/SentryFramesTracker.swift b/Sources/Swift/Core/Integrations/FramesTracking/SentryFramesTracker.swift index c625aed75e3..9025f687b2d 100644 --- a/Sources/Swift/Core/Integrations/FramesTracking/SentryFramesTracker.swift +++ b/Sources/Swift/Core/Integrations/FramesTracking/SentryFramesTracker.swift @@ -49,8 +49,7 @@ public class SentryFramesTracker: NSObject { private static let frozenFrameThreshold: CFTimeInterval = 0.7 private static let previousFrameInitialValue: CFTimeInterval = -1 - @objc - public init( + init( displayLinkWrapper: SentryDisplayLinkWrapper, dateProvider: SentryCurrentDateProvider, dispatchQueueWrapper: SentryDispatchQueueWrapper, @@ -140,7 +139,7 @@ public class SentryFramesTracker: NSObject { #endif } - @objc public func getFramesDelay( + func getFramesDelay( _ startSystemTimestamp: UInt64, endSystemTimestamp: UInt64 ) -> SentryFramesDelayResult { @@ -151,6 +150,14 @@ public class SentryFramesTracker: NSObject { slowFrameThreshold: Self.slowFrameThreshold(currentFrameRate) ) } + + @objc public func getFramesDelaySPI( + _ startSystemTimestamp: UInt64, + endSystemTimestamp: UInt64 + ) -> SentryFramesDelayResultSPI { + let result = getFramesDelay(startSystemTimestamp, endSystemTimestamp: endSystemTimestamp) + return .init(delayDuration: result.delayDuration, framesContributingToDelayCount: result.framesContributingToDelayCount) + } @objc public func addListener(_ listener: SentryFramesTrackerListener) { dispatchQueueWrapper.dispatchAsyncOnMainQueueIfNotMainThread { diff --git a/Sources/Swift/Helper/Dependencies.swift b/Sources/Swift/Helper/Dependencies.swift index 04e8c4e1c61..8f1b41eafba 100644 --- a/Sources/Swift/Helper/Dependencies.swift +++ b/Sources/Swift/Helper/Dependencies.swift @@ -10,6 +10,9 @@ }() @objc public static let dispatchQueueWrapper = SentryDispatchQueueWrapper() @objc public static let notificationCenterWrapper: SentryNSNotificationCenterWrapper = NotificationCenter.default + @objc public static let crashWrapper = SentryCrashWrapper(processInfoWrapper: Dependencies.processInfoWrapper) + @objc public static let binaryImageCache = SentryBinaryImageCache() + @objc public static let debugImageProvider = SentryDebugImageProvider() @objc public static let sysctlWrapper = SentrySysctl() @objc public static let dateProvider = SentryDefaultCurrentDateProvider() public static let objcRuntimeWrapper = SentryDefaultObjCRuntimeWrapper() diff --git a/Sources/Swift/Integrations/Session/SentryWatchdogTerminationScopeObserver.swift b/Sources/Swift/Integrations/WatchdogTerminations/SentryWatchdogTerminationScopeObserver.swift similarity index 62% rename from Sources/Swift/Integrations/Session/SentryWatchdogTerminationScopeObserver.swift rename to Sources/Swift/Integrations/WatchdogTerminations/SentryWatchdogTerminationScopeObserver.swift index 9969aead118..349516abfdf 100644 --- a/Sources/Swift/Integrations/Session/SentryWatchdogTerminationScopeObserver.swift +++ b/Sources/Swift/Integrations/WatchdogTerminations/SentryWatchdogTerminationScopeObserver.swift @@ -6,67 +6,63 @@ * This class doesn't need to be thread safe as the scope already calls the scope observers in a * thread safe manner. */ -@_spi(Private) @objc public class SentryWatchdogTerminationScopeObserver: NSObject, SentryScopeObserver { +class SentryWatchdogTerminationScopeObserver: NSObject, SentryScopeObserver { private let breadcrumbProcessor: SentryWatchdogTerminationBreadcrumbProcessor private let attributesProcessor: SentryWatchdogTerminationAttributesProcessor - + init(breadcrumbProcessor: SentryWatchdogTerminationBreadcrumbProcessor, attributesProcessor: SentryWatchdogTerminationAttributesProcessor) { self.breadcrumbProcessor = breadcrumbProcessor self.attributesProcessor = attributesProcessor } - @objc public convenience init(maxBreadcrumbs: Int, attributesProcessor: SentryWatchdogTerminationAttributesProcessor) { - self.init(breadcrumbProcessor: SentryWatchdogTerminationBreadcrumbProcessor(maxBreadcrumbs: maxBreadcrumbs), attributesProcessor: attributesProcessor) - } - - public func setUser(_ user: User?) { + func setUser(_ user: User?) { attributesProcessor.setUser(user) } - public func setTags(_ tags: [String: String]?) { + func setTags(_ tags: [String: String]?) { attributesProcessor.setTags(tags) } - public func setExtras(_ extras: [String: Any]?) { + func setExtras(_ extras: [String: Any]?) { attributesProcessor.setExtras(extras) } - public func setContext(_ context: [String: [String: Any]]?) { + func setContext(_ context: [String: [String: Any]]?) { attributesProcessor.setContext(context) } - public func setTraceContext(_ traceContext: [String: Any]?) { + func setTraceContext(_ traceContext: [String: Any]?) { // Nothing to do here, Trace Context is not persisted for watchdog termination events // On regular events, we have the current trace in memory, but there isn't time to persist one // in watchdog termination events } - public func setDist(_ dist: String?) { + func setDist(_ dist: String?) { attributesProcessor.setDist(dist) } - public func setEnvironment(_ environment: String?) { + func setEnvironment(_ environment: String?) { attributesProcessor.setEnvironment(environment) } - public func setFingerprint(_ fingerprint: [String]?) { + func setFingerprint(_ fingerprint: [String]?) { attributesProcessor.setFingerprint(fingerprint) } - public func setLevel(_ level: SentryLevel) { + func setLevel(_ level: SentryLevel) { // Nothing to do here, watchdog termination events are always Fatal } - public func addSerializedBreadcrumb(_ serializedBreadcrumb: [String: Any]) { + func addSerializedBreadcrumb(_ serializedBreadcrumb: [String: Any]) { breadcrumbProcessor.addSerializedBreadcrumb(serializedBreadcrumb) } - public func clearBreadcrumbs() { + func clearBreadcrumbs() { breadcrumbProcessor.clearBreadcrumbs() } - public func clear() { + func clear() { breadcrumbProcessor.clear() attributesProcessor.clear() } diff --git a/Sources/Swift/SentryDependencyContainer.swift b/Sources/Swift/SentryDependencyContainer.swift new file mode 100644 index 00000000000..26331ae1758 --- /dev/null +++ b/Sources/Swift/SentryDependencyContainer.swift @@ -0,0 +1,268 @@ +@_implementationOnly import _SentryPrivate +#if (os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT +import UIKit +#endif + +// Declare the application provider block at the top level to prevent capturing 'self' +// from the dependency container, which would create cyclic dependencies and memory leaks. +let defaultApplicationProvider: () -> SentryApplication? = { +#if (os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT + return UIApplication.shared +#elseif os(macOS) + return NSApplication.shared +#else + return nil +#endif +} + +let SENTRY_AUTO_TRANSACTION_MAX_DURATION = 500.0 + +// MARK: - RedactWrapper + +final class RedactWrapper: SentryRedactOptions { + var maskAllText: Bool { + defaultOptions.maskAllText + } + + var maskAllImages: Bool { + defaultOptions.maskAllImages + } + + var maskedViewClasses: [AnyClass] { + defaultOptions.maskedViewClasses + } + + var unmaskedViewClasses: [AnyClass] { + defaultOptions.unmaskedViewClasses + } + + private let defaultOptions: SentryDefaultRedactOptions + init(_ defaultOptions: SentryDefaultRedactOptions) { + self.defaultOptions = defaultOptions + } +} + +// MARK: - Extensions + +extension SentryFileManager: SentryFileManagerProtocol { } +@_spi(Private) extension SentryANRTrackerV1: SentryANRTrackerInternalProtocol { } + +#if (os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT +@_spi(Private) extension SentryANRTrackerV2: SentryANRTrackerInternalProtocol { } + +@_spi(Private) extension SentryDelayedFramesTracker: SentryDelayedFramesTrackerWrapper { + func getFramesDelay(_ startSystemTimestamp: UInt64, endSystemTimestamp: UInt64, isRunning: Bool, slowFrameThreshold: CFTimeInterval) -> SentryFramesDelayResult { + let objcResult = getFramesDelayObjC(startSystemTimestamp, endSystemTimestamp: endSystemTimestamp, isRunning: isRunning, slowFrameThreshold: slowFrameThreshold) + return .init(delayDuration: objcResult.delayDuration, framesContributingToDelayCount: objcResult.framesContributingToDelayCount) + } +} +#endif + +// MARK: - SentryDependencyContainer +@_spi(Private) @objc public final class SentryDependencyContainer: NSObject { + + // MARK: Private + + private static let instanceLock = NSRecursiveLock() + private static var instance = SentryDependencyContainer() + private let paramLock = NSRecursiveLock() + + private func getLazyVar(_ keyPath: ReferenceWritableKeyPath, builder: () -> T) -> T { + paramLock.synchronized { + guard let result = self[keyPath: keyPath] else { + let result = builder() + self[keyPath: keyPath] = result + return result + } + return result + } + } + + private func getOptionalLazyVar(_ keyPath: ReferenceWritableKeyPath, builder: () -> T?) -> T? { + paramLock.synchronized { + guard let result = self[keyPath: keyPath] else { + let result = builder() + self[keyPath: keyPath] = result + return result + } + return result + } + } + + // MARK: Public + + @objc public static func sharedInstance() -> SentryDependencyContainer { + instanceLock.synchronized { + return instance + } + } + + /** + * Resets all dependencies. + */ + @objc public static func reset() { + instanceLock.synchronized { + instance.reachability.removeAllObservers() +#if (os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT + instance._framesTracker?.stop() +#endif + instance = SentryDependencyContainer() + } + } + +#if SENTRY_TEST || SENTRY_TEST_CI + var applicationOverride: SentryApplication? +#endif + @objc public func application() -> SentryApplication? { +#if SENTRY_TEST || SENTRY_TEST_CI + let `override` = self.applicationOverride + if let `override` { + return `override` + } +#endif + return defaultApplicationProvider() + } + + @objc(getSessionTrackerWithOptions:) public func getSessionTracker(with options: Options) -> SessionTracker { + return SessionTracker(options: options, applicationProvider: defaultApplicationProvider, dateProvider: dateProvider, notificationCenter: notificationCenterWrapper) + } + + @objc public var dispatchQueueWrapper = Dependencies.dispatchQueueWrapper + @objc public var random = Dependencies.random + @objc public var threadWrapper = Dependencies.threadWrapper + @objc public var binaryImageCache = Dependencies.binaryImageCache + @objc public var dateProvider: SentryCurrentDateProvider = Dependencies.dateProvider + @objc public var notificationCenterWrapper = Dependencies.notificationCenterWrapper + @objc public var processInfoWrapper = Dependencies.processInfoWrapper + @objc public var crashWrapper = Dependencies.crashWrapper + @objc public var dispatchFactory = SentryDispatchFactory() + @objc public var timerFactory = SentryNSTimerFactory() + @objc public var fileIOTracker = Dependencies.fileIOTracker + @objc public var threadInspector = Dependencies.threadInspector + @objc public var rateLimits: RateLimits = DefaultRateLimits( + retryAfterHeaderParser: RetryAfterHeaderParser(httpDateParser: HttpDateParser(), currentDateProvider: Dependencies.dateProvider), + andRateLimitParser: RateLimitParser(currentDateProvider: Dependencies.dateProvider), + currentDateProvider: Dependencies.dateProvider) + @objc public var reachability = SentryReachability() + @objc public var sysctlWrapper = Dependencies.sysctlWrapper + @objc public var sessionReplayEnvironmentChecker = Dependencies.sessionReplayEnvironmentChecker + @objc public var debugImageProvider = Dependencies.debugImageProvider + @objc public var objcRuntimeWrapper: SentryObjCRuntimeWrapper = SentryDefaultObjCRuntimeWrapper() + +#if os(iOS) && !SENTRY_NO_UIKIT + @objc public var extraContextProvider = SentryExtraContextProvider(crashWrapper: Dependencies.crashWrapper, processInfoWrapper: Dependencies.processInfoWrapper, deviceWrapper: Dependencies.uiDeviceWrapper) +#else + @objc public var extraContextProvider = SentryExtraContextProvider(crashWrapper: Dependencies.crashWrapper, processInfoWrapper: Dependencies.processInfoWrapper) +#endif + +#if os(iOS) || os(macOS) + // Disable crash diagnostics as we only use it for validation of the symbolication + // of stacktraces, because crashes are easy to trigger for MetricKit. We don't want + // crash reports of MetricKit in production as we have SentryCrash. + @objc public var metricKitManager = SentryMXManager(disableCrashDiagnostics: true) +#endif + +#if (os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT + @objc public var uiDeviceWrapper: SentryUIDeviceWrapper = Dependencies.uiDeviceWrapper + @objc public var threadsafeApplication = SentryThreadsafeApplication(applicationProvider: defaultApplicationProvider, notificationCenter: Dependencies.notificationCenterWrapper) + @objc public var swizzleWrapper = SentrySwizzleWrapper() + + // MARK: Lazy Vars + + private var _watchdogTerminationAttributesProcessor: SentryWatchdogTerminationAttributesProcessor? + @objc public lazy var watchdogTerminationAttributesProcessor = + getLazyVar(\._watchdogTerminationAttributesProcessor) { + SentryWatchdogTerminationAttributesProcessor( + withDispatchQueueWrapper: dispatchFactory.createUtilityQueue("io.sentry.watchdog-termination-tracking.fields-processor", relativePriority: 0), + scopePersistentStore: scopePersistentStore) + } + + private var _uiViewControllerPerformanceTracker: SentryUIViewControllerPerformanceTracker? + @objc public lazy var uiViewControllerPerformanceTracker = getLazyVar(\._uiViewControllerPerformanceTracker) { + SentryUIViewControllerPerformanceTracker() + } + + private var _framesTracker: SentryFramesTracker? + @objc public lazy var framesTracker = getLazyVar(\._framesTracker) { + let delayedFramesTracker = SentryDelayedFramesTracker(keepDelayedFramesDuration: SENTRY_AUTO_TRANSACTION_MAX_DURATION) + return SentryFramesTracker(displayLinkWrapper: SentryDisplayLinkWrapper(), dateProvider: dateProvider, dispatchQueueWrapper: dispatchQueueWrapper, notificationCenter: notificationCenterWrapper, delayedFramesTracker: delayedFramesTracker) + } + + private var _viewHierarchyProvider: SentryViewHierarchyProvider? + @objc public lazy var viewHierarchyProvider = getLazyVar(\._viewHierarchyProvider) { + SentryViewHierarchyProvider(dispatchQueueWrapper: dispatchQueueWrapper, applicationProvider: defaultApplicationProvider) + } + + @objc public func getWatchdogTerminationScopeObserverWithOptions(_ options: Options) -> SentryScopeObserver { + return SentryWatchdogTerminationScopeObserver( + breadcrumbProcessor: SentryWatchdogTerminationBreadcrumbProcessor( + maxBreadcrumbs: Int(options.maxBreadcrumbs)), + attributesProcessor: watchdogTerminationAttributesProcessor) + } +#endif + +#if (os(iOS) || os(tvOS)) && !SENTRY_NO_UIKIT + private var _screenshotSource: SentryScreenshotSource? + @objc public lazy var screenshotSource: SentryScreenshotSource? = getOptionalLazyVar(\._screenshotSource) { + // The options could be null here, but this is a general issue in the dependency + // container and will be fixed in a future refactoring. + guard let options = SentrySDKInternal.options else { + return nil + } + + let viewRenderer: SentryViewRenderer + if SentryDependencyContainerSwiftHelper.viewRendererV2Enabled(options) { + viewRenderer = SentryViewRendererV2(enableFastViewRendering: SentryDependencyContainerSwiftHelper.fastViewRenderingEnabled(options)) + } else { + viewRenderer = SentryDefaultViewRenderer() + } + + let photographer = SentryViewPhotographer( + renderer: viewRenderer, + redactOptions: RedactWrapper(SentryDependencyContainerSwiftHelper.redactOptions(options)), + enableMaskRendererV2: SentryDependencyContainerSwiftHelper.viewRendererV2Enabled(options)) + return SentryScreenshotSource(photographer: photographer) + } +#endif + + private var _fileManager: SentryFileManager? + @objc public lazy var fileManager: SentryFileManager? = getOptionalLazyVar(\._fileManager) { + do { + return try SentryFileManager(options: SentrySDKInternal.options, dateProvider: Dependencies.dateProvider, dispatchQueueWrapper: Dependencies.dispatchQueueWrapper) + } catch { + SentrySDKLog.debug("Could not create file manager - \(error)") + return nil + } + } + private var _scopePersistentStore: SentryScopePersistentStore? + @objc public lazy var scopePersistentStore = getOptionalLazyVar(\._scopePersistentStore) { + SentryScopePersistentStore(fileManager: fileManager) + } + private var _globalEventProcessor: SentryGlobalEventProcessor? + @objc public lazy var globalEventProcessor = getLazyVar(\._globalEventProcessor) { + SentryGlobalEventProcessor() + } + private var _appStateManager: SentryAppStateManager? + @objc public lazy var appStateManager = getLazyVar(\._appStateManager) { + SentryAppStateManager( + options: SentrySDKInternal.options, + crashWrapper: crashWrapper, + fileManager: fileManager, + sysctlWrapper: sysctlWrapper) + } + private var _crashReporter: SentryCrashSwift? + @objc public lazy var crashReporter = getLazyVar(\._crashReporter) { + SentryCrashSwift(with: SentrySDKInternal.options?.cacheDirectoryPath) + } + + private var anrTracker: SentryANRTracker? + @objc public func getANRTracker(_ timeout: TimeInterval) -> SentryANRTracker { + getLazyVar(\.anrTracker) { + #if (os(iOS) || os(tvOS) || (swift(>=5.9) && os(visionOS))) && !SENTRY_NO_UIKIT + SentryANRTracker(helper: SentryANRTrackerV2(timeoutInterval: timeout)) + #else + SentryANRTracker(helper: SentryANRTrackerV1(timeoutInterval: timeout)) + #endif + } + } +} diff --git a/Tests/SentryProfilerTests/SentryProfileTestFixture.swift b/Tests/SentryProfilerTests/SentryProfileTestFixture.swift index 53a6bca97e2..720099cd189 100644 --- a/Tests/SentryProfilerTests/SentryProfileTestFixture.swift +++ b/Tests/SentryProfilerTests/SentryProfileTestFixture.swift @@ -6,7 +6,7 @@ import XCTest #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) #if !os(macOS) -class TestDelayedWrapper: SentryDelayedFramesTracker, SentryDelayedFramesTrackerWrapper {} +class TestDelayedWrapper: SentryDelayedFramesTracker {} #endif // !os(macOS) class SentryProfileTestFixture { diff --git a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerTests.swift b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerTests.swift new file mode 100644 index 00000000000..f40292f0d16 --- /dev/null +++ b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerTests.swift @@ -0,0 +1,39 @@ +@_spi(Private) @testable import Sentry +import XCTest + +final class SentryANRTrackerTests: XCTestCase { + + func testRemovesDeallocatedDelegates() throws { + let helper = MockSentryANRTrackerHelper() + let tracker = SentryANRTracker(helper: helper) + var delegate: MockANRTrackerDelegate? = MockANRTrackerDelegate() + weak var delegateWeak: MockANRTrackerDelegate? = delegate + tracker.add(listener: try XCTUnwrap(delegate)) + + delegate = nil + XCTAssertNil(delegateWeak) + tracker.add(listener: MockANRTrackerDelegate()) + XCTAssertEqual(1, tracker.mapping.count) + } + +} + +final class MockSentryANRTrackerHelper: SentryANRTrackerInternalProtocol { + func addListener(_ listender: any SentryANRTrackerInternalDelegate) { + } + + func removeListener(_ listener: any SentryANRTrackerInternalDelegate) { + } + + func clear() { + } + +} + +final class MockANRTrackerDelegate: SentryANRTrackerDelegate { + func anrDetected(type: Sentry.SentryANRType) { + } + + func anrStopped(result: Sentry.SentryANRStoppedResult?) { + } +} diff --git a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1Tests.swift b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1Tests.swift index 95cd67e7ce8..3ed72c338e1 100644 --- a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1Tests.swift +++ b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV1Tests.swift @@ -2,8 +2,6 @@ @_spi(Private) import SentryTestUtils import XCTest -@_spi(Private) extension SentryANRTrackerV1: SentryANRTrackerProtocol { } - #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) class SentryANRTrackerV1Tests: XCTestCase, SentryANRTrackerDelegate { diff --git a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV2Tests.swift b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV2Tests.swift index 5cfafb462f3..13f147fcc84 100644 --- a/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV2Tests.swift +++ b/Tests/SentryTests/Integrations/ANR/SentryANRTrackerV2Tests.swift @@ -4,8 +4,6 @@ import XCTest #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) -@_spi(Private) extension SentryANRTrackerV2: SentryANRTrackerProtocol { } - class SentryANRTrackerV2Tests: XCTestCase { private let waitTimeout: TimeInterval = 10.0 diff --git a/Tests/SentryTests/Integrations/Performance/UIViewController/SentryTimeToDisplayTrackerTest.swift b/Tests/SentryTests/Integrations/Performance/UIViewController/SentryTimeToDisplayTrackerTest.swift index 7ec8246a579..fc04cf316d3 100644 --- a/Tests/SentryTests/Integrations/Performance/UIViewController/SentryTimeToDisplayTrackerTest.swift +++ b/Tests/SentryTests/Integrations/Performance/UIViewController/SentryTimeToDisplayTrackerTest.swift @@ -5,7 +5,7 @@ import XCTest #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) -class TestDelayedWrapper: SentryDelayedFramesTracker, SentryDelayedFramesTrackerWrapper {} +class TestDelayedWrapper: SentryDelayedFramesTracker {} class SentryTimeToDisplayTrackerTest: XCTestCase { diff --git a/Tests/SentryTests/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationBreadcrumbProcessorTests.swift b/Tests/SentryTests/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationBreadcrumbProcessorTests.swift index 43ce36d5855..6dadcc82b41 100644 --- a/Tests/SentryTests/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationBreadcrumbProcessorTests.swift +++ b/Tests/SentryTests/Integrations/WatchdogTerminations/Processors/SentryWatchdogTerminationBreadcrumbProcessorTests.swift @@ -35,8 +35,7 @@ class SentryWatchdogTerminationBreadcrumbProcessorTests: XCTestCase { func getSut(fileManager: SentryFileManager) -> SentryWatchdogTerminationBreadcrumbProcessor { return SentryWatchdogTerminationBreadcrumbProcessor( maxBreadcrumbs: maxBreadcrumbs, - fileManager: fileManager - ) + fileManager: fileManager) } } diff --git a/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackerTests.swift b/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackerTests.swift index ce4cf0f7253..c2c9b293f3f 100644 --- a/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackerTests.swift +++ b/Tests/SentryTests/Integrations/WatchdogTerminations/SentryWatchdogTerminationTrackerTests.swift @@ -2,12 +2,6 @@ @_spi(Private) import SentryTestUtils import XCTest -#if compiler(>=6.0) -@_spi(Private) extension SentryFileManager: @retroactive SentryFileManagerProtocol { } -#else -@_spi(Private) extension SentryFileManager: SentryFileManagerProtocol { } -#endif - #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) class SentryWatchdogTerminationTrackerTests: NotificationCenterTestCase {