diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 2c5b801004b..9983748c461 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -59,6 +59,7 @@ 33EB2A912C3412E4004FED3D /* SentryWithoutUIKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 33EB2A8F2C3411AE004FED3D /* SentryWithoutUIKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 33EB2A922C341300004FED3D /* Sentry.h in Headers */ = {isa = PBXBuildFile; fileRef = 63AA76931EB9C1C200D153DE /* Sentry.h */; settings = {ATTRIBUTES = (Public, ); }; }; 51B15F802BE88D510026A2F2 /* URLSessionTaskHelperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51B15F7F2BE88D510026A2F2 /* URLSessionTaskHelperTests.swift */; }; + 51BDCFDD5F944B40ADBB4811DAE797D1 /* SentryCrashIntegration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77D29A8724614DEBA55BABC775BFC3E6 /* SentryCrashIntegration.swift */; }; 620078722D38F00D0022CB67 /* SentryGeoCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 620078712D38F00D0022CB67 /* SentryGeoCodable.swift */; }; 620078742D38F0DF0022CB67 /* SentryCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 620078732D38F0DF0022CB67 /* SentryCodable.swift */; }; 620078782D3906BF0022CB67 /* SentryCodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 620078772D3906BF0022CB67 /* SentryCodableTests.swift */; }; @@ -162,8 +163,6 @@ 632F43521F581D5400A18A36 /* SentryCrashExceptionApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 632F434F1F581D5400A18A36 /* SentryCrashExceptionApplication.m */; }; 6334314120AD9AE40077E581 /* SentryMechanism.h in Headers */ = {isa = PBXBuildFile; fileRef = 6334313F20AD9AE40077E581 /* SentryMechanism.h */; settings = {ATTRIBUTES = (Public, ); }; }; 6334314320AD9AE40077E581 /* SentryMechanism.m in Sources */ = {isa = PBXBuildFile; fileRef = 6334314020AD9AE40077E581 /* SentryMechanism.m */; }; - 6344DDB01EC308E400D9160D /* SentryCrashInstallationReporter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6344DDAE1EC308E400D9160D /* SentryCrashInstallationReporter.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 6344DDB11EC308E400D9160D /* SentryCrashInstallationReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 6344DDAF1EC308E400D9160D /* SentryCrashInstallationReporter.m */; }; 6344DDB41EC309E000D9160D /* SentryCrashReportSink.h in Headers */ = {isa = PBXBuildFile; fileRef = 6344DDB21EC309E000D9160D /* SentryCrashReportSink.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6344DDB51EC309E000D9160D /* SentryCrashReportSink.m in Sources */ = {isa = PBXBuildFile; fileRef = 6344DDB31EC309E000D9160D /* SentryCrashReportSink.m */; }; 6344DDB91EC3115C00D9160D /* SentryCrashReportConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 6344DDB71EC3115C00D9160D /* SentryCrashReportConverter.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -357,8 +356,6 @@ 7B3B473E25D6CEA500D01640 /* SentryNSErrorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B3B473D25D6CEA500D01640 /* SentryNSErrorTests.swift */; }; 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 */; }; - 7B4E23C2251A2C2B00060D68 /* SentryCrashIntegrationSessionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B4E23C1251A2C2B00060D68 /* SentryCrashIntegrationSessionHandler.m */; }; 7B4E24FC251C97B500060D68 /* SentrySessionInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B4E24FB251C97B400060D68 /* SentrySessionInternal.h */; }; 7B4E375525822C4500059C93 /* SentryAttachment.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B4E375425822C4500059C93 /* SentryAttachment.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7B4E375B2582313100059C93 /* SentryAttachmentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4E375A2582313100059C93 /* SentryAttachmentTests.swift */; }; @@ -536,8 +533,6 @@ 7DB3A687238EA75E00A2D442 /* SentryHttpTransport.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DB3A684238EA75E00A2D442 /* SentryHttpTransport.m */; }; 7DC27EC523997EB7006998B5 /* SentryAutoBreadcrumbTrackingIntegration.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DC27EC323997EB7006998B5 /* SentryAutoBreadcrumbTrackingIntegration.h */; }; 7DC27EC723997EB7006998B5 /* SentryAutoBreadcrumbTrackingIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DC27EC423997EB7006998B5 /* SentryAutoBreadcrumbTrackingIntegration.m */; }; - 7DC8310A2398283C0043DD9A /* SentryCrashIntegration.h in Headers */ = {isa = PBXBuildFile; fileRef = 7DC831082398283C0043DD9A /* SentryCrashIntegration.h */; }; - 7DC8310C2398283C0043DD9A /* SentryCrashIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DC831092398283C0043DD9A /* SentryCrashIntegration.m */; }; 81BC357F116F0147283DA824 /* PropertyExtractorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E69CEDDF745ECE10243A13FA /* PropertyExtractorTests.swift */; }; 840A11122B61E27500650D02 /* SentrySamplerDecision.m in Sources */ = {isa = PBXBuildFile; fileRef = 840A11102B61E27500650D02 /* SentrySamplerDecision.m */; }; 841325BC2BF4184B0029228F /* TestHub.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B944FAD2469B43700A10721 /* TestHub.swift */; }; @@ -1003,6 +998,8 @@ F458D1152E1869AD0028273E /* SentryScopePersistentStore+String.swift in Sources */ = {isa = PBXBuildFile; fileRef = F458D1142E1869AD0028273E /* SentryScopePersistentStore+String.swift */; }; F458D1172E186DF20028273E /* SentryScopePersistentStore+Fingerprint.swift in Sources */ = {isa = PBXBuildFile; fileRef = F458D1162E186DF20028273E /* SentryScopePersistentStore+Fingerprint.swift */; }; F458D1192E186E000028273E /* SentryScopePersistentStore+Extras.swift in Sources */ = {isa = PBXBuildFile; fileRef = F458D1182E186E000028273E /* SentryScopePersistentStore+Extras.swift */; }; + F46298472F19EBA700F127B5 /* SentryCrashInstallationReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46298452F19EBA700F127B5 /* SentryCrashInstallationReporter.swift */; }; + F46298482F19EBA700F127B5 /* SentryCrashIntegrationSessionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46298462F19EBA700F127B5 /* SentryCrashIntegrationSessionHandler.swift */; }; F465D2132E87E36F00FE2DD9 /* RateLimits.swift in Sources */ = {isa = PBXBuildFile; fileRef = F465D2122E87E36F00FE2DD9 /* RateLimits.swift */; }; F465D2142E87E36F00FE2DD9 /* DefaultRateLimits.swift in Sources */ = {isa = PBXBuildFile; fileRef = F465D2112E87E36F00FE2DD9 /* DefaultRateLimits.swift */; }; F46DA6C32E1DBCA000DF6E3B /* SentryScopePersistentStore+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46DA6C22E1DBCA000DF6E3B /* SentryScopePersistentStore+Helper.swift */; }; @@ -1475,8 +1472,6 @@ 632F434F1F581D5400A18A36 /* SentryCrashExceptionApplication.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashExceptionApplication.m; sourceTree = ""; }; 6334313F20AD9AE40077E581 /* SentryMechanism.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryMechanism.h; path = Public/SentryMechanism.h; sourceTree = ""; }; 6334314020AD9AE40077E581 /* SentryMechanism.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryMechanism.m; sourceTree = ""; }; - 6344DDAE1EC308E400D9160D /* SentryCrashInstallationReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashInstallationReporter.h; path = include/SentryCrashInstallationReporter.h; sourceTree = ""; }; - 6344DDAF1EC308E400D9160D /* SentryCrashInstallationReporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashInstallationReporter.m; sourceTree = ""; }; 6344DDB21EC309E000D9160D /* SentryCrashReportSink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashReportSink.h; path = include/SentryCrashReportSink.h; sourceTree = ""; }; 6344DDB31EC309E000D9160D /* SentryCrashReportSink.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashReportSink.m; sourceTree = ""; }; 6344DDB71EC3115C00D9160D /* SentryCrashReportConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashReportConverter.h; path = include/SentryCrashReportConverter.h; sourceTree = ""; }; @@ -1532,7 +1527,7 @@ 63FE6FBD20DA4C1000CDBAE8 /* SentryDictionaryDeepSearch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryDictionaryDeepSearch.m; sourceTree = ""; }; 63FE6FBF20DA4C1000CDBAE8 /* SentryDictionaryDeepSearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryDictionaryDeepSearch.h; sourceTree = ""; }; 63FE6FC120DA4C1000CDBAE8 /* SentryCrashVarArgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashVarArgs.h; sourceTree = ""; }; - 63FE6FC420DA4C1000CDBAE8 /* SentryCrashReportFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashReportFilter.h; sourceTree = ""; }; + 63FE6FC420DA4C1000CDBAE8 /* SentryCrashReportFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashReportFilter.h; path = ../../../Sentry/include/SentryCrashReportFilter.h; sourceTree = ""; }; 63FE6FC820DA4C1000CDBAE8 /* SentryCrashReportFilterBasic.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashReportFilterBasic.m; sourceTree = ""; }; 63FE6FCC20DA4C1000CDBAE8 /* SentryCrashReportFilterBasic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashReportFilterBasic.h; sourceTree = ""; }; 63FE6FEA20DA4C1000CDBAE8 /* SentryCrashReportFixer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashReportFixer.c; sourceTree = ""; }; @@ -1542,10 +1537,10 @@ 63FE6FF020DA4C1000CDBAE8 /* SentryCrashMonitor_NSException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashMonitor_NSException.m; sourceTree = ""; }; 63FE6FF120DA4C1000CDBAE8 /* SentryCrashMonitor_MachException.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashMonitor_MachException.c; sourceTree = ""; }; 63FE6FF320DA4C1000CDBAE8 /* SentryCrashMonitor_System.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashMonitor_System.m; sourceTree = ""; }; - 63FE6FF420DA4C1000CDBAE8 /* SentryCrashMonitor_Signal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMonitor_Signal.h; sourceTree = ""; }; + 63FE6FF420DA4C1000CDBAE8 /* SentryCrashMonitor_Signal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashMonitor_Signal.h; path = ../../../Sentry/include/SentryCrashMonitor_Signal.h; sourceTree = ""; }; 63FE6FF520DA4C1000CDBAE8 /* SentryCrashMonitorType.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashMonitorType.c; sourceTree = ""; }; 63FE6FF620DA4C1000CDBAE8 /* SentryCrashMonitor_CPPException.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SentryCrashMonitor_CPPException.cpp; sourceTree = ""; }; - 63FE6FF820DA4C1000CDBAE8 /* SentryCrashMonitor_CPPException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMonitor_CPPException.h; sourceTree = ""; }; + 63FE6FF820DA4C1000CDBAE8 /* SentryCrashMonitor_CPPException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashMonitor_CPPException.h; path = ../../../Sentry/include/SentryCrashMonitor_CPPException.h; sourceTree = ""; }; 63FE6FF920DA4C1000CDBAE8 /* SentryCrashMonitor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashMonitor.c; sourceTree = ""; }; 63FE6FFB20DA4C1000CDBAE8 /* SentryCrashMonitor_MachException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMonitor_MachException.h; sourceTree = ""; }; 63FE6FFC20DA4C1000CDBAE8 /* SentryCrashMonitor_NSException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMonitor_NSException.h; sourceTree = ""; }; @@ -1556,7 +1551,7 @@ 63FE700220DA4C1000CDBAE8 /* SentryCrashMonitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashMonitor.h; path = ../../../Sentry/include/SentryCrashMonitor.h; sourceTree = ""; }; 63FE700420DA4C1000CDBAE8 /* SentryCrashCachedData.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashCachedData.c; sourceTree = ""; }; 63FE700720DA4C1000CDBAE8 /* SentryCrashDate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashDate.h; sourceTree = ""; }; - 63FE700820DA4C1000CDBAE8 /* SentryCrashMachineContext_Apple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMachineContext_Apple.h; sourceTree = ""; }; + 63FE700820DA4C1000CDBAE8 /* SentryCrashMachineContext_Apple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashMachineContext_Apple.h; path = ../../../Sentry/include/SentryCrashMachineContext_Apple.h; sourceTree = ""; }; 63FE700920DA4C1000CDBAE8 /* SentryAsyncSafeLog.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryAsyncSafeLog.c; sourceTree = ""; }; 63FE700A20DA4C1000CDBAE8 /* SentryCrashStackCursor_SelfThread.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashStackCursor_SelfThread.m; sourceTree = ""; }; 63FE700B20DA4C1000CDBAE8 /* SentryCrashFileUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashFileUtils.h; sourceTree = ""; }; @@ -1574,7 +1569,7 @@ 63FE701920DA4C1000CDBAE8 /* SentryCrashSignalInfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashSignalInfo.c; sourceTree = ""; }; 63FE701A20DA4C1000CDBAE8 /* SentryCrashThread.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashThread.c; sourceTree = ""; }; 63FE701B20DA4C1000CDBAE8 /* SentryCrashCPU_arm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashCPU_arm.c; sourceTree = ""; }; - 63FE701C20DA4C1000CDBAE8 /* SentryCrashStackCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashStackCursor.h; sourceTree = ""; }; + 63FE701C20DA4C1000CDBAE8 /* SentryCrashStackCursor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashStackCursor.h; path = ../../../Sentry/include/SentryCrashStackCursor.h; sourceTree = ""; }; 63FE701D20DA4C1000CDBAE8 /* SentryCrashJSONCodecObjC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashJSONCodecObjC.m; sourceTree = ""; }; 63FE701E20DA4C1000CDBAE8 /* SentryCrashSysCtl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashSysCtl.c; sourceTree = ""; }; 63FE701F20DA4C1000CDBAE8 /* SentryCrashDynamicLinker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashDynamicLinker.c; sourceTree = ""; }; @@ -1587,7 +1582,7 @@ 63FE702620DA4C1000CDBAE8 /* SentryCrashStackCursor_SelfThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashStackCursor_SelfThread.h; sourceTree = ""; }; 63FE702720DA4C1000CDBAE8 /* SentryCrashDate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashDate.c; sourceTree = ""; }; 63FE702920DA4C1000CDBAE8 /* SentryCrashObjC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashObjC.c; sourceTree = ""; }; - 63FE702A20DA4C1000CDBAE8 /* SentryCrashMachineContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMachineContext.h; sourceTree = ""; }; + 63FE702A20DA4C1000CDBAE8 /* SentryCrashMachineContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashMachineContext.h; path = ../../../Sentry/include/SentryCrashMachineContext.h; sourceTree = ""; }; 63FE702B20DA4C1000CDBAE8 /* SentryCrashStackCursor_Backtrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashStackCursor_Backtrace.h; sourceTree = ""; }; 63FE702C20DA4C1000CDBAE8 /* SentryCrashString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashString.h; sourceTree = ""; }; 63FE702D20DA4C1000CDBAE8 /* SentryCrashJSONCodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashJSONCodec.h; sourceTree = ""; }; @@ -1615,14 +1610,14 @@ 63FE704620DA4C1000CDBAE8 /* SentryCrashReportFields.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashReportFields.h; sourceTree = ""; }; 63FE704720DA4C1000CDBAE8 /* SentryCrashDoctor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashDoctor.m; sourceTree = ""; }; 63FE704820DA4C1000CDBAE8 /* SentryCrashReportFixer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashReportFixer.h; sourceTree = ""; }; - 63FE704920DA4C1000CDBAE8 /* SentryCrashC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashC.h; sourceTree = ""; }; + 63FE704920DA4C1000CDBAE8 /* SentryCrashC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashC.h; path = ../../Sentry/include/SentryCrashC.h; sourceTree = ""; }; 63FE704A20DA4C1000CDBAE8 /* SentryCrashReportVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashReportVersion.h; sourceTree = ""; }; 63FE704B20DA4C1000CDBAE8 /* SentryCrash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrash.h; path = ../../Sentry/include/SentryCrash.h; sourceTree = ""; }; 63FE704C20DA4C1000CDBAE8 /* SentryCrashReport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashReport.h; sourceTree = ""; }; 63FE704D20DA4C1000CDBAE8 /* SentryCrashReportStore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashReportStore.c; sourceTree = ""; }; 63FE705C20DA4C1000CDBAE8 /* SentryCrashInstallation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashInstallation.m; sourceTree = ""; }; - 63FE706320DA4C1000CDBAE8 /* SentryCrashInstallation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashInstallation.h; sourceTree = ""; }; - 63FE706920DA4C1000CDBAE8 /* SentryCrashInstallation+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SentryCrashInstallation+Private.h"; sourceTree = ""; }; + 63FE706320DA4C1000CDBAE8 /* SentryCrashInstallation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashInstallation.h; path = ../../Sentry/include/SentryCrashInstallation.h; sourceTree = ""; }; + 63FE706920DA4C1000CDBAE8 /* SentryCrashInstallation+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "SentryCrashInstallation+Private.h"; path = "../../Sentry/include/SentryCrashInstallation+Private.h"; sourceTree = ""; }; 63FE71D520DA66E600CDBAE8 /* RFC3339UTFString_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RFC3339UTFString_Tests.m; sourceTree = ""; }; 63FE71D720DA66E700CDBAE8 /* SentryCrashCPU_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashCPU_Tests.m; sourceTree = ""; }; 63FE71D820DA66E700CDBAE8 /* SentryCrashString_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashString_Tests.m; sourceTree = ""; }; @@ -1653,6 +1648,7 @@ 69BEE6F62620729E006DF9DF /* UrlSessionDelegateSpy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UrlSessionDelegateSpy.swift; sourceTree = ""; }; 7071C2D29C27DFEA10F7C5EE /* SentryOptionsDocumentationSyncTests.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = SentryOptionsDocumentationSyncTests.swift; sourceTree = ""; }; 71F11CDEF5952DF5CC69AC74 /* SentryCrashUUIDConversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCrashUUIDConversion.h; path = ../../../Sentry/include/SentryCrashUUIDConversion.h; sourceTree = ""; }; + 77D29A8724614DEBA55BABC775BFC3E6 /* SentryCrashIntegration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashIntegration.swift; sourceTree = ""; }; 7B0002312477F0520035FEF1 /* SentrySessionTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySessionTests.m; sourceTree = ""; }; 7B0002332477F52D0035FEF1 /* SentrySessionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySessionTests.swift; sourceTree = ""; }; 7B01CE3C271993AB00B5AF31 /* SentryTransportFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryTransportFactoryTests.swift; sourceTree = ""; }; @@ -1685,10 +1681,7 @@ 7B3B473D25D6CEA500D01640 /* SentryNSErrorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSErrorTests.swift; 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 = ""; }; 7B4E23B5251A07BD00060D68 /* SentryDispatchQueueWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryDispatchQueueWrapperTests.swift; sourceTree = ""; }; - 7B4E23BD251A2BD500060D68 /* SentryCrashIntegrationSessionHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryCrashIntegrationSessionHandler.h; path = include/SentryCrashIntegrationSessionHandler.h; sourceTree = ""; }; - 7B4E23C1251A2C2B00060D68 /* SentryCrashIntegrationSessionHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashIntegrationSessionHandler.m; sourceTree = ""; }; 7B4E24FB251C97B400060D68 /* SentrySessionInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentrySessionInternal.h; path = include/SentrySessionInternal.h; sourceTree = ""; }; 7B4E375425822C4500059C93 /* SentryAttachment.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryAttachment.h; path = Public/SentryAttachment.h; sourceTree = ""; }; 7B4E375A2582313100059C93 /* SentryAttachmentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryAttachmentTests.swift; sourceTree = ""; }; @@ -1892,8 +1885,6 @@ 7DC27E9823995F97006998B5 /* Sentry.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = Sentry.modulemap; path = ../Resources/Sentry.modulemap; sourceTree = ""; }; 7DC27EC323997EB7006998B5 /* SentryAutoBreadcrumbTrackingIntegration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryAutoBreadcrumbTrackingIntegration.h; path = include/SentryAutoBreadcrumbTrackingIntegration.h; sourceTree = ""; }; 7DC27EC423997EB7006998B5 /* SentryAutoBreadcrumbTrackingIntegration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryAutoBreadcrumbTrackingIntegration.m; sourceTree = ""; }; - 7DC831082398283C0043DD9A /* SentryCrashIntegration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryCrashIntegration.h; path = include/SentryCrashIntegration.h; sourceTree = ""; }; - 7DC831092398283C0043DD9A /* SentryCrashIntegration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryCrashIntegration.m; sourceTree = ""; }; 840A11102B61E27500650D02 /* SentrySamplerDecision.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySamplerDecision.m; sourceTree = ""; }; 840B7EEA2BBF2ABA008B8120 /* .slather.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = .slather.yml; sourceTree = ""; }; 840B7EEC2BBF2AFE008B8120 /* .gitattributes */ = {isa = PBXFileReference; lastKnownFileType = text; path = .gitattributes; sourceTree = ""; }; @@ -2410,6 +2401,8 @@ F458D1142E1869AD0028273E /* SentryScopePersistentStore+String.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+String.swift"; sourceTree = ""; }; F458D1162E186DF20028273E /* SentryScopePersistentStore+Fingerprint.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+Fingerprint.swift"; sourceTree = ""; }; F458D1182E186E000028273E /* SentryScopePersistentStore+Extras.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+Extras.swift"; sourceTree = ""; }; + F46298452F19EBA700F127B5 /* SentryCrashInstallationReporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashInstallationReporter.swift; sourceTree = ""; }; + F46298462F19EBA700F127B5 /* SentryCrashIntegrationSessionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashIntegrationSessionHandler.swift; sourceTree = ""; }; F465D2112E87E36F00FE2DD9 /* DefaultRateLimits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultRateLimits.swift; sourceTree = ""; }; F465D2122E87E36F00FE2DD9 /* RateLimits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RateLimits.swift; sourceTree = ""; }; F46DA6C22E1DBCA000DF6E3B /* SentryScopePersistentStore+Helper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+Helper.swift"; sourceTree = ""; }; @@ -2681,6 +2674,16 @@ path = ViewHierarchy; sourceTree = ""; }; + 2568E9C78967E5C15401CC4E /* SentryCrash */ = { + isa = PBXGroup; + children = ( + F46298452F19EBA700F127B5 /* SentryCrashInstallationReporter.swift */, + F46298462F19EBA700F127B5 /* SentryCrashIntegrationSessionHandler.swift */, + 77D29A8724614DEBA55BABC775BFC3E6 /* SentryCrashIntegration.swift */, + ); + path = SentryCrash; + sourceTree = ""; + }; 620078752D38F1110022CB67 /* Codable */ = { isa = PBXGroup; children = ( @@ -2947,8 +2950,6 @@ 632F434F1F581D5400A18A36 /* SentryCrashExceptionApplication.m */, F49D419B2DEA30B800D9244E /* SentryCrashExceptionApplicationHelper.h */, F49D419D2DEA3D0300D9244E /* SentryCrashExceptionApplicationHelper.m */, - 6344DDAE1EC308E400D9160D /* SentryCrashInstallationReporter.h */, - 6344DDAF1EC308E400D9160D /* SentryCrashInstallationReporter.m */, 6344DDB21EC309E000D9160D /* SentryCrashReportSink.h */, 6344DDB31EC309E000D9160D /* SentryCrashReportSink.m */, 6344DDB71EC3115C00D9160D /* SentryCrashReportConverter.h */, @@ -3733,8 +3734,6 @@ children = ( FAD882C32EDB3F450055AA44 /* SentryCrashAsync.h */, FAAB95DD2EA1EB470030A2DB /* SentryDeviceContextKeys.h */, - 7DC831082398283C0043DD9A /* SentryCrashIntegration.h */, - 7DC831092398283C0043DD9A /* SentryCrashIntegration.m */, 7BCFBD6C2681D0A900BC27D8 /* SentryCrashScopeObserver.h */, 7BCFBD6E2681D0EE00BC27D8 /* SentryCrashScopeObserver.m */, 7B96571F26830C9100C66E25 /* SentryScopeSyncC.h */, @@ -3746,8 +3745,6 @@ 7BE0DC36272AE80A004FA8B7 /* Session */ = { isa = PBXGroup; children = ( - 7B4E23BD251A2BD500060D68 /* SentryCrashIntegrationSessionHandler.h */, - 7B4E23C1251A2C2B00060D68 /* SentryCrashIntegrationSessionHandler.m */, ); name = Session; sourceTree = ""; @@ -3862,7 +3859,6 @@ 7B965727268321CD00C66E25 /* SentryCrashScopeObserverTests.swift */, 7B6ADFCE26A02CAE0076C206 /* SentryCrashReportTests.swift */, 7BD337E324A356180050DB6E /* SentryCrashIntegrationTests.swift */, - 7B4E23AE2519E13800060D68 /* SentryCrashIntegration+TestInit.h */, 7BE2C7F625700093003B66C7 /* SentryTestIntegration.h */, 7BE2C7F72570009F003B66C7 /* SentryTestIntegration.m */, 62D6B2A62CCA354B004DDBF1 /* SentryUncaughtNSExceptionsTests.swift */, @@ -4944,6 +4940,7 @@ isa = PBXGroup; children = ( FAFA35A62EFDDD94006B145F /* SentryHangTrackingIntegration.swift */, + 2568E9C78967E5C15401CC4E /* SentryCrash */, F4FE86BC2EECAC31003D845F /* Screenshot */, 925189AB2EDDA6A300557BD1 /* Log */, D46B04162EDF167800AF4A0A /* Metrics */, @@ -5252,7 +5249,6 @@ 7BA0C04628055F8E003E0326 /* SentryTransportAdapter.h in Headers */, 63FE717720DA4C1100CDBAE8 /* SentryCrashReportWriter.h in Headers */, 84DEE86B2B686BD400A7BC17 /* SentrySamplerDecision.h in Headers */, - 7B4E23BE251A2BD500060D68 /* SentryCrashIntegrationSessionHandler.h in Headers */, D81A346C291AECC7005A27A9 /* PrivateSentrySDKOnly.h in Headers */, D88817DA26D72AB800BF2251 /* SentryTraceContext.h in Headers */, 63FE708520DA4C1000CDBAE8 /* SentryCrashReportFilter.h in Headers */, @@ -5415,7 +5411,6 @@ D456B4362D706BF2007068CB /* SentryTraceOrigin.h in Headers */, 7BD86ECF264A7C77005439DB /* SentryAppStartMeasurement.h in Headers */, 0354A22B2A134D9C003C3A04 /* SentryProfilerState.h in Headers */, - 7DC8310A2398283C0043DD9A /* SentryCrashIntegration.h in Headers */, 63FE718320DA4C1100CDBAE8 /* SentryCrashReportFixer.h in Headers */, 03F84D2027DD414C008FE43F /* SentryStackBounds.hpp in Headers */, 6273513F2CBD14970021D100 /* SentryDebugImageProviderInternal.h in Headers */, @@ -5462,7 +5457,6 @@ 63FE714720DA4C1100CDBAE8 /* SentryCrashMachineContext.h in Headers */, 7BC63F0828081242009D9E37 /* SentrySwizzleWrapperHelper.h in Headers */, 638DC9A01EBC6B6400A66E41 /* SentryRequestOperation.h in Headers */, - 6344DDB01EC308E400D9160D /* SentryCrashInstallationReporter.h in Headers */, 63FE70ED20DA4C1000CDBAE8 /* SentryCrashMonitor_NSException.h in Headers */, 63FE713D20DA4C1100CDBAE8 /* SentryAsyncSafeLog.h in Headers */, D43A2A102DD47FB700114724 /* SentryWeakMap.h in Headers */, @@ -5944,6 +5938,9 @@ D48953FE2EF5756A0086F240 /* SentryMetricValue.swift in Sources */, F4FE86BD2EECAC31003D845F /* SentryScreenshotOptions.swift in Sources */, F4FE86BE2EECAC31003D845F /* SentryScreenshotIntegration.swift in Sources */, + 51BDCFDD5F944B40ADBB4811DAE797D1 /* SentryCrashIntegration.swift in Sources */, + F46298472F19EBA700F127B5 /* SentryCrashInstallationReporter.swift in Sources */, + F46298482F19EBA700F127B5 /* SentryCrashIntegrationSessionHandler.swift in Sources */, 92D957732E05A44600E20E66 /* SentryAsyncLog.m in Sources */, 623FD9022D3FA5E000803EDA /* SentryFrameCodable.swift in Sources */, 62BDDD122D51FD540024CCD1 /* SentryThreadCodable.swift in Sources */, @@ -6194,7 +6191,6 @@ D81988C52BEC18CA0020E36C /* SentryRRWebCustomEvent.swift in Sources */, 639889B81EDECFA800EA7442 /* SentryBreadcrumbTracker.m in Sources */, 84AF45A729A7FFA500FBB177 /* SentryProfiledTracerConcurrency.mm in Sources */, - 7DC8310C2398283C0043DD9A /* SentryCrashIntegration.m in Sources */, D45CE9752E5F454E00BFEDB2 /* SentryScreenshotSource.swift in Sources */, FAE579BA2E7DBE9900B710F9 /* SentryGlobalEventProcessor.swift in Sources */, 03F84D3227DD4191008FE43F /* SentryProfiler.mm in Sources */, @@ -6204,7 +6200,6 @@ D4CD2A802DE9F91900DA9F59 /* SentryRedactRegion.swift in Sources */, D4CD2A812DE9F91900DA9F59 /* SentryRedactRegionType.swift in Sources */, FAEEBFEA2E74517B00E79CA9 /* SentryFileManager.swift in Sources */, - 6344DDB11EC308E400D9160D /* SentryCrashInstallationReporter.m in Sources */, 84BA62272CAE2EEF0049F636 /* SentryUserFeedbackWidgetButtonView.swift in Sources */, FAE5798D2E7D9D4C00B710F9 /* SentrySysctl.swift in Sources */, 92ECD73E2E05AD320063EC10 /* SentryLogLevel.swift in Sources */, @@ -6236,7 +6231,6 @@ FAE2DAB82E1F317900262307 /* SentryProfilingSwiftHelpers.m in Sources */, 8EA1ED0B2668F8C400E62B98 /* SentryUIViewControllerSwizzling.m in Sources */, 8E5D38DD261D4A3E000D363D /* SentryPerformanceTrackingIntegration.m in Sources */, - 7B4E23C2251A2C2B00060D68 /* SentryCrashIntegrationSessionHandler.m in Sources */, 9286059729A5098900F96038 /* SentryGeo.m in Sources */, D43B26D82D70A550007747FD /* SentryTraceOrigin.m in Sources */, FAE57C082E83092E00B710F9 /* SentryDispatchFactory.swift in Sources */, diff --git a/Sources/Sentry/SentryClient.m b/Sources/Sentry/SentryClient.m index a033cc8e9ea..e2c875e4424 100644 --- a/Sources/Sentry/SentryClient.m +++ b/Sources/Sentry/SentryClient.m @@ -3,7 +3,6 @@ #import "SentryAttachment.h" #import "SentryClient+Private.h" #import "SentryCrashDefaultMachineContextWrapper.h" -#import "SentryCrashIntegration.h" #import "SentryCrashStackEntryMapper.h" #import "SentryDefaultThreadInspector.h" #import "SentryDeviceContextKeys.h" diff --git a/Sources/Sentry/SentryCrashInstallationReporter.m b/Sources/Sentry/SentryCrashInstallationReporter.m deleted file mode 100644 index fb17d0a40bd..00000000000 --- a/Sources/Sentry/SentryCrashInstallationReporter.m +++ /dev/null @@ -1,59 +0,0 @@ -#import "SentryCrashInstallationReporter.h" -#import "SentryCrash.h" -#import "SentryCrashInstallation+Private.h" -#import "SentryCrashReportSink.h" -#import "SentryDefines.h" -#import "SentryLogC.h" -#import "SentrySwift.h" - -@interface SentryCrashReportSink () -@end - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryCrashInstallationReporter () - -@property (nonatomic, strong) SentryInAppLogic *inAppLogic; -@property (nonatomic, strong) SentryCrashWrapper *crashWrapper; -@property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueue; - -@end - -@implementation SentryCrashInstallationReporter - -- (instancetype)initWithInAppLogic:(SentryInAppLogic *)inAppLogic - crashWrapper:(SentryCrashWrapper *)crashWrapper - dispatchQueue:(SentryDispatchQueueWrapper *)dispatchQueue -{ - if (self = [super initWithRequiredProperties:[NSArray new]]) { - self.inAppLogic = inAppLogic; - self.crashWrapper = crashWrapper; - self.dispatchQueue = dispatchQueue; - } - return self; -} - -- (id)sink -{ - return [[SentryCrashReportSink alloc] initWithInAppLogic:self.inAppLogic - crashWrapper:self.crashWrapper - dispatchQueue:self.dispatchQueue]; -} - -- (void)sendAllReportsWithCompletion:(nullable SentryCrashReportFilterCompletion)onCompletion -{ - [super - sendAllReportsWithCompletion:^(NSArray *filteredReports, BOOL completed, NSError *error) { - if (nil != error) { - SENTRY_LOG_ERROR(@"%@", error.localizedDescription); - } - SENTRY_LOG_DEBUG(@"Sent %lu crash report(s)", (unsigned long)filteredReports.count); - if (completed && onCompletion) { - onCompletion(filteredReports, completed, error); - } - }]; -} - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryCrashIntegration.m b/Sources/Sentry/SentryCrashIntegration.m deleted file mode 100644 index 89831028825..00000000000 --- a/Sources/Sentry/SentryCrashIntegration.m +++ /dev/null @@ -1,281 +0,0 @@ -#import "SentryCrashIntegration.h" -#import "SentryCrashC.h" -#import "SentryCrashInstallationReporter.h" -#import "SentryCrashIntegrationSessionHandler.h" -#import "SentryCrashMonitor_CPPException.h" -#include "SentryCrashMonitor_Signal.h" -#import "SentryEvent.h" -#import "SentryHub.h" -#import "SentryInternalDefines.h" -#import "SentrySDK+Private.h" -#import "SentryScope+Private.h" -#import "SentryScope+PrivateSwift.h" -#import "SentrySpanInternal+Private.h" -#import "SentrySwift.h" -#import "SentryTracer.h" -#import -#import -#import -#import - -#if SENTRY_HAS_UIKIT -# import -#endif - -#if TARGET_OS_OSX -# import "SentryUncaughtNSExceptions.h" -#endif // TARGET_OS_OSX - -static dispatch_once_t installationToken = 0; -static SentryCrashInstallationReporter *installation = nil; - -static NSString *const LOCALE_KEY = @"locale"; - -void -sentry_finishAndSaveTransaction(void) -{ - SentrySpanInternal *_Nullable span = [SentrySDKInternal.currentHub.scope getCastedInternalSpan]; - - if (span != nil) { - SentryTracer *tracer = [span tracer]; - [tracer finishForCrash]; - } -} - -@interface SentryCrashScopeObserver () -@end - -@interface SentryCrashIntegration () - -@property (nonatomic, weak) SentryOptions *options; -@property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueueWrapper; -@property (nonatomic, strong) SentryCrashWrapper *crashAdapter; -@property (nonatomic, strong) SentryCrashIntegrationSessionHandler *sessionHandler; -@property (nonatomic, strong) SentryCrashScopeObserver *scopeObserver; - -@end - -@implementation SentryCrashIntegration - -- (instancetype)init -{ - self = [self initWithCrashAdapter:SentryDependencyContainer.sharedInstance.crashWrapper - andDispatchQueueWrapper:[[SentryDispatchQueueWrapper alloc] init]]; - - return self; -} - -/** Internal constructor for testing */ -- (instancetype)initWithCrashAdapter:(SentryCrashWrapper *)crashAdapter - andDispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper -{ - if (self = [super init]) { - self.crashAdapter = crashAdapter; - self.dispatchQueueWrapper = dispatchQueueWrapper; - } - - return self; -} - -- (BOOL)installWithOptions:(nonnull SentryOptions *)options -{ - if (![super installWithOptions:options]) { - return NO; - } - - self.options = options; - -#if SENTRY_HAS_UIKIT - SentryAppStateManager *appStateManager = - [SentryDependencyContainer sharedInstance].appStateManager; - SentryWatchdogTerminationLogic *logic = - [[SentryWatchdogTerminationLogic alloc] initWithOptions:options - crashAdapter:self.crashAdapter - appStateManager:appStateManager]; - self.sessionHandler = - [[SentryCrashIntegrationSessionHandler alloc] initWithCrashWrapper:self.crashAdapter - watchdogTerminationLogic:logic]; -#else - self.sessionHandler = - [[SentryCrashIntegrationSessionHandler alloc] initWithCrashWrapper:self.crashAdapter]; -#endif // SENTRY_HAS_UIKIT - - self.scopeObserver = - [[SentryCrashScopeObserver alloc] initWithMaxBreadcrumbs:options.maxBreadcrumbs]; - - BOOL enableSigtermReporting = NO; -#if !TARGET_OS_WATCH - enableSigtermReporting = options.enableSigtermReporting; -#endif // !TARGET_OS_WATCH - - BOOL enableUncaughtNSExceptionReporting = NO; -#if TARGET_OS_OSX - if (options.enableSwizzling) { - enableUncaughtNSExceptionReporting = options.enableUncaughtNSExceptionReporting; - } -#endif // TARGET_OS_OSX - - [self startCrashHandler:options.cacheDirectoryPath - enableSigtermReporting:enableSigtermReporting - enableReportingUncaughtExceptions:enableUncaughtNSExceptionReporting - enableCppExceptionsV2:options.experimental.enableUnhandledCPPExceptionsV2]; - - [self configureScope]; - - if (options.enablePersistingTracesWhenCrashing) { - [self configureTracingWhenCrashing]; - } - - return YES; -} - -- (SentryIntegrationOption)integrationOptions -{ - return kIntegrationOptionEnableCrashHandler; -} - -- (void)startCrashHandler:(NSString *)cacheDirectory - enableSigtermReporting:(BOOL)enableSigtermReporting - enableReportingUncaughtExceptions:(BOOL)enableReportingUncaughtExceptions - enableCppExceptionsV2:(BOOL)enableCppExceptionsV2 -{ - void (^block)(void) = ^{ - BOOL canSendReports = NO; - if (installation == nil) { - SentryInAppLogic *inAppLogic = - [[SentryInAppLogic alloc] initWithInAppIncludes:self.options.inAppIncludes]; - - installation = [[SentryCrashInstallationReporter alloc] - initWithInAppLogic:inAppLogic - crashWrapper:self.crashAdapter - dispatchQueue:self.dispatchQueueWrapper]; - - canSendReports = YES; - } - - sentrycrashcm_setEnableSigtermReporting(enableSigtermReporting); - - [installation install:cacheDirectory]; - -#if TARGET_OS_OSX - if (enableReportingUncaughtExceptions) { - [SentryUncaughtNSExceptions configureCrashOnExceptions]; - [SentryUncaughtNSExceptions swizzleNSApplicationReportException]; - } -#endif // TARGET_OS_OSX - - if (enableCppExceptionsV2) { - SENTRY_LOG_DEBUG(@"Enabling CppExceptionsV2 by swapping cxa_throw."); - - sentrycrashcm_cppexception_enable_swap_cxa_throw(); - } - - // We need to send the crashed event together with the crashed session in the same envelope - // to have proper statistics in release health. To achieve this we need both synchronously - // in the hub. The crashed event is converted from a SentryCrashReport to an event in - // SentryCrashReportSink and then passed to the SDK on a background thread. This process is - // started with installing this integration. We need to end and delete the previous session - // before being able to start a new session for the AutoSessionTrackingIntegration. The - // SentryCrashIntegration is installed before the AutoSessionTrackingIntegration so there is - // no guarantee if the crashed event is created before or after the - // AutoSessionTrackingIntegration. By ending the previous session and storing it as crashed - // in here we have the guarantee once the crashed event is sent to the hub it is already - // there and the AutoSessionTrackingIntegration can work properly. - // - // This is a pragmatic and not the most optimal place for this logic. - [self.sessionHandler endCurrentSessionIfRequired]; - - // We only need to send all reports on the first initialization of SentryCrash. If - // SenryCrash was deactivated there are no new reports to send. Furthermore, the - // g_reportsPath in SentryCrashReportsStore gets set when SentryCrash is installed. In - // production usage, this path is not supposed to change. When testing, this path can - // change, and therefore, the initial set g_reportsPath can be deleted. sendAllReports calls - // deleteAllReports, which fails it can't access g_reportsPath. We could fix SentryCrash or - // just not call sendAllReports as it doesn't make sense to call it twice as described - // above. - if (canSendReports) { - [SentryCrashIntegration sendAllSentryCrashReports]; - } - }; - [self.dispatchQueueWrapper dispatchOnce:&installationToken block:block]; -} - -/** - * Internal, only needed for testing. - */ -+ (void)sendAllSentryCrashReports -{ - [installation sendAllReportsWithCompletion:NULL]; -} - -- (void)uninstall -{ - if (nil != installation) { - [installation uninstall]; - installationToken = 0; - } - - sentrycrash_setSaveTransaction(NULL); - - [NSNotificationCenter.defaultCenter removeObserver:self - name:NSCurrentLocaleDidChangeNotification - object:nil]; -} - -- (void)configureScope -{ - // We need to make sure to set always the scope to KSCrash so we have it in - // case of a crash - [SentrySDKInternal.currentHub configureScope:^(SentryScope *_Nonnull outerScope) { - NSMutableDictionary *userInfo = - [[NSMutableDictionary alloc] initWithDictionary:[outerScope serialize]]; - // SentryCrashReportConverter.convertReportToEvent needs the release name and - // the dist of the SentryOptions in the UserInfo. When SentryCrash records a - // crash it writes the UserInfo into SentryCrashField_User of the report. - // SentryCrashReportConverter.initWithReport loads the contents of - // SentryCrashField_User into self.userContext and convertReportToEvent can map - // the release name and dist to the SentryEvent. Fixes GH-581 - userInfo[@"release"] = self.options.releaseName; - userInfo[@"dist"] = self.options.dist; - - // Crashes don't use the attributes field, we remove them to avoid uploading them - // unnecessarily. - [userInfo removeObjectForKey:@"attributes"]; - - [SentryDependencyContainer.sharedInstance.crashReporter setUserInfo:userInfo]; - - [outerScope addScopeObserver:self.scopeObserver]; - }]; - - [NSNotificationCenter.defaultCenter addObserver:self - selector:@selector(currentLocaleDidChange) - name:NSCurrentLocaleDidChangeNotification - object:nil]; -} - -- (void)currentLocaleDidChange -{ - [SentrySDKInternal.currentHub configureScope:^(SentryScope *_Nonnull scope) { - NSMutableDictionary *device; - if (scope.contextDictionary != nil - && scope.contextDictionary[SENTRY_CONTEXT_DEVICE_KEY] != nil) { - device = [[NSMutableDictionary alloc] - initWithDictionary:SENTRY_UNWRAP_NULLABLE_DICT(NSString *, id, - scope.contextDictionary[SENTRY_CONTEXT_DEVICE_KEY])]; - } else { - device = [NSMutableDictionary new]; - } - - NSString *locale = [[NSLocale autoupdatingCurrentLocale] objectForKey:NSLocaleIdentifier]; - device[LOCALE_KEY] = locale; - - [scope setContextValue:device forKey:SENTRY_CONTEXT_DEVICE_KEY]; - }]; -} - -- (void)configureTracingWhenCrashing -{ - sentrycrash_setSaveTransaction(&sentry_finishAndSaveTransaction); -} - -@end diff --git a/Sources/Sentry/SentryCrashIntegrationSessionHandler.m b/Sources/Sentry/SentryCrashIntegrationSessionHandler.m deleted file mode 100644 index 4952a65c443..00000000000 --- a/Sources/Sentry/SentryCrashIntegrationSessionHandler.m +++ /dev/null @@ -1,88 +0,0 @@ -#import "SentryCrashIntegrationSessionHandler.h" -#import "SentryClient+Private.h" -#import "SentryHub.h" -#import "SentryInternalDefines.h" -#import "SentryLogC.h" -#import "SentrySDK+Private.h" -#import "SentrySwift.h" - -@interface SentryCrashIntegrationSessionHandler () - -@property (nonatomic, strong) SentryCrashWrapper *crashWrapper; -#if SENTRY_HAS_UIKIT -@property (nonatomic, strong) SentryWatchdogTerminationLogic *watchdogTerminationLogic; -#endif // SENTRY_HAS_UIKIT - -@end - -@implementation SentryCrashIntegrationSessionHandler - -#if SENTRY_HAS_UIKIT -- (instancetype)initWithCrashWrapper:(SentryCrashWrapper *)crashWrapper - watchdogTerminationLogic:(SentryWatchdogTerminationLogic *)watchdogTerminationLogic -#else -- (instancetype)initWithCrashWrapper:(SentryCrashWrapper *)crashWrapper -#endif // SENTRY_HAS_UIKIT -{ - self = [self init]; - self.crashWrapper = crashWrapper; -#if SENTRY_HAS_UIKIT - self.watchdogTerminationLogic = watchdogTerminationLogic; -#endif // SENTRY_HAS_UIKIT - - return self; -} - -- (void)endCurrentSessionIfRequired -{ - SentryFileManager *fileManager = [[[SentrySDKInternal currentHub] getClient] fileManager]; - - if (nil == fileManager) { - SENTRY_LOG_DEBUG(@"File manager is nil. Cannot end current session."); - return; - } - - SentrySession *session = [fileManager readCurrentSession]; - if (session == nil) { - SENTRY_LOG_DEBUG(@"No current session found to end."); - return; - } - - if (self.crashWrapper.crashedLastLaunch -#if SENTRY_HAS_UIKIT - || [self.watchdogTerminationLogic isWatchdogTermination] -#endif // SENTRY_HAS_UIKIT - ) { - NSDate *timeSinceLastCrash = [[SentryDependencyContainer.sharedInstance.dateProvider date] - dateByAddingTimeInterval:-self.crashWrapper.activeDurationSinceLastCrash]; - - [session endSessionCrashedWithTimestamp:timeSinceLastCrash]; - [fileManager storeCrashedSession:session]; - [fileManager deleteCurrentSession]; - } -#if SENTRY_HAS_UIKIT - else { - // Checking the file existence is way cheaper than reading the file and parsing its contents - // to an SentryEvent. - if (![fileManager appHangEventExists]) { - SENTRY_LOG_DEBUG(@"No app hang event found. Won't end current session."); - return; - } - - SentryEvent *appHangEvent = [fileManager readAppHangEvent]; - // Just in case the file was deleted between the check and the read. - if (appHangEvent == nil) { - SENTRY_LOG_WARN( - @"App hang event deleted between check and read. Cannot end current session."); - return; - } - - [session - endSessionAbnormalWithTimestamp:SENTRY_UNWRAP_NULLABLE(NSDate, appHangEvent).timestamp]; - [fileManager storeAbnormalSession:session]; - [fileManager deleteCurrentSession]; - } -#endif // SENTRY_HAS_UIKIT -} - -@end diff --git a/Sources/Sentry/SentrySDKInternal.m b/Sources/Sentry/SentrySDKInternal.m index 142186e7faa..a61d2d2bd63 100644 --- a/Sources/Sentry/SentrySDKInternal.m +++ b/Sources/Sentry/SentrySDKInternal.m @@ -6,7 +6,6 @@ #import "SentryClient+Private.h" #import "SentryCoreDataTrackingIntegration.h" #import "SentryCrash.h" -#import "SentryCrashIntegration.h" #import "SentryFileIOTrackingIntegration.h" #import "SentryHub+Private.h" #import "SentryInternalDefines.h" @@ -502,13 +501,11 @@ + (void)endSession + (NSArray *)defaultIntegrationClasses { // The order of integrations here is important. - // SentryCrashIntegration needs to be initialized before SentryAutoSessionTrackingIntegration. - // And SentrySessionReplayIntegration before SentryCrashIntegration. + // SentrySessionReplayIntegration needs to be initialized before SentryCrashIntegration. NSMutableArray *defaultIntegrations = [NSMutableArray arrayWithObjects: #if SENTRY_TARGET_REPLAY_SUPPORTED [SentrySessionReplayIntegration class], #endif // SENTRY_TARGET_REPLAY_SUPPORTED - [SentryCrashIntegration class], #if SENTRY_HAS_UIKIT [SentryAppStartTrackingIntegration class], [SentryPerformanceTrackingIntegration class], [SentryUIEventTrackingIntegration class], [SentryViewHierarchyIntegration class], diff --git a/Sources/SentryCrash/Installations/SentryCrashInstallation+Private.h b/Sources/Sentry/include/SentryCrashInstallation+Private.h similarity index 100% rename from Sources/SentryCrash/Installations/SentryCrashInstallation+Private.h rename to Sources/Sentry/include/SentryCrashInstallation+Private.h diff --git a/Sources/SentryCrash/Installations/SentryCrashInstallation.h b/Sources/Sentry/include/SentryCrashInstallation.h similarity index 100% rename from Sources/SentryCrash/Installations/SentryCrashInstallation.h rename to Sources/Sentry/include/SentryCrashInstallation.h diff --git a/Sources/Sentry/include/SentryCrashInstallationReporter.h b/Sources/Sentry/include/SentryCrashInstallationReporter.h deleted file mode 100644 index de8957ee2d0..00000000000 --- a/Sources/Sentry/include/SentryCrashInstallationReporter.h +++ /dev/null @@ -1,22 +0,0 @@ -#import "SentryCrash.h" -#import "SentryCrashInstallation.h" -#import "SentryDefines.h" - -@class SentryCrashWrapper; -@class SentryDispatchQueueWrapper; -@class SentryInAppLogic; - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryCrashInstallationReporter : SentryCrashInstallation -SENTRY_NO_INIT - -- (instancetype)initWithInAppLogic:(SentryInAppLogic *)inAppLogic - crashWrapper:(SentryCrashWrapper *)crashWrapper - dispatchQueue:(SentryDispatchQueueWrapper *)dispatchQueue; - -- (void)sendAllReportsWithCompletion:(nullable SentryCrashReportFilterCompletion)onCompletion; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryCrashIntegration.h b/Sources/Sentry/include/SentryCrashIntegration.h deleted file mode 100644 index 0da16c8c42b..00000000000 --- a/Sources/Sentry/include/SentryCrashIntegration.h +++ /dev/null @@ -1,17 +0,0 @@ -#import "SentryBaseIntegration.h" - -NS_ASSUME_NONNULL_BEGIN - -@class SentryCrashWrapper; -@class SentryScope; - -@interface SentryCrashIntegration : SentryBaseIntegration - -/** - * Needed for testing. - */ -+ (void)sendAllSentryCrashReports; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryCrashIntegrationSessionHandler.h b/Sources/Sentry/include/SentryCrashIntegrationSessionHandler.h deleted file mode 100644 index 4d2ee4ad09e..00000000000 --- a/Sources/Sentry/include/SentryCrashIntegrationSessionHandler.h +++ /dev/null @@ -1,29 +0,0 @@ -#import "SentryDefines.h" - -@class SentryCrashWrapper; - -#if SENTRY_HAS_UIKIT -@class SentryWatchdogTerminationLogic; -#endif // SENTRY_HAS_UIKIT - -@interface SentryCrashIntegrationSessionHandler : NSObject - -#if SENTRY_HAS_UIKIT -- (instancetype)initWithCrashWrapper:(SentryCrashWrapper *)crashWrapper - watchdogTerminationLogic:(SentryWatchdogTerminationLogic *)watchdogTerminationLogic; -#else -- (instancetype)initWithCrashWrapper:(SentryCrashWrapper *)crashWrapper; -#endif // SENTRY_HAS_UIKIT - -/** - * When a crash or a watchdog termination happens, we end the current session as crashed, store it - * in a dedicated location, and delete the current one. The same applies if a fatal app hang occurs. - * Then, we end the current session as abnormal and store it in a dedicated abnormal session - * location. - * - * Check out the SentryHub, which implements most of the session logic, for more details about - * sessions. - */ -- (void)endCurrentSessionIfRequired; - -@end diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashMachineContext.h b/Sources/Sentry/include/SentryCrashMachineContext.h similarity index 100% rename from Sources/SentryCrash/Recording/Tools/SentryCrashMachineContext.h rename to Sources/Sentry/include/SentryCrashMachineContext.h diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashMachineContext_Apple.h b/Sources/Sentry/include/SentryCrashMachineContext_Apple.h similarity index 100% rename from Sources/SentryCrash/Recording/Tools/SentryCrashMachineContext_Apple.h rename to Sources/Sentry/include/SentryCrashMachineContext_Apple.h diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_CPPException.h b/Sources/Sentry/include/SentryCrashMonitor_CPPException.h similarity index 100% rename from Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_CPPException.h rename to Sources/Sentry/include/SentryCrashMonitor_CPPException.h diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_Signal.h b/Sources/Sentry/include/SentryCrashMonitor_Signal.h similarity index 100% rename from Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_Signal.h rename to Sources/Sentry/include/SentryCrashMonitor_Signal.h diff --git a/Sources/Sentry/include/SentryCrashReportSink.h b/Sources/Sentry/include/SentryCrashReportSink.h index 728bacf1ac0..eb038438565 100644 --- a/Sources/Sentry/include/SentryCrashReportSink.h +++ b/Sources/Sentry/include/SentryCrashReportSink.h @@ -10,9 +10,10 @@ NS_ASSUME_NONNULL_BEGIN @interface SentryCrashReportSink : NSObject SENTRY_NO_INIT -- (instancetype)initWithInAppLogic:(SentryInAppLogic *)inAppLogic - crashWrapper:(SentryCrashWrapper *)crashWrapper - dispatchQueue:(SentryDispatchQueueWrapper *)dispatchQueue; +- (instancetype)initWithInAppLogic:(SENTRY_SWIFT_MIGRATION_ID(SentryInAppLogic))inAppLogic + crashWrapper:(SENTRY_SWIFT_MIGRATION_ID(SentryCrashWrapper))crashWrapper + dispatchQueue: + (SENTRY_SWIFT_MIGRATION_ID(SentryDispatchQueueWrapper))dispatchQueue; @end diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor.h b/Sources/Sentry/include/SentryCrashStackCursor.h similarity index 100% rename from Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor.h rename to Sources/Sentry/include/SentryCrashStackCursor.h diff --git a/Sources/Sentry/include/SentryPrivate.h b/Sources/Sentry/include/SentryPrivate.h index ed6feb968f8..c6000e4c48e 100644 --- a/Sources/Sentry/include/SentryPrivate.h +++ b/Sources/Sentry/include/SentryPrivate.h @@ -30,6 +30,7 @@ #import "SentryScope+Private.h" #import "SentrySwizzleWrapperHelper.h" #import "SentryTime.h" +#import "SentryTracer.h" #import "SentryUserAccess.h" #import "SentryViewHierarchyProviderHelper.h" #import "_SentryDispatchQueueWrapperInternal.h" @@ -42,8 +43,14 @@ #import "SentryContinuousProfiler.h" #import "SentryCrash.h" #import "SentryCrashDebug.h" +#import "SentryCrashInstallation+Private.h" +#import "SentryCrashInstallation.h" #import "SentryCrashMonitor_AppState.h" +#import "SentryCrashMonitor_CPPException.h" +#import "SentryCrashMonitor_Signal.h" #import "SentryCrashMonitor_System.h" +#import "SentryCrashReportSink.h" +#import "SentryCrashScopeObserver.h" #import "SentryDateUtils.h" #import "SentryDebugImageProviderInternal.h" #import "SentryDefaultAppStateManager.h" @@ -62,7 +69,7 @@ #import "SentryPerformanceTracker.h" #import "SentryProfiler+Private.h" #import "SentrySDKInternal.h" -#import "SentryScope+PrivateSwift.h" +#import "SentryScope+Private.h" #import "SentryScope.h" #import "SentrySerialization.h" #import "SentrySessionInternal.h" @@ -73,4 +80,5 @@ #import "SentryTraceHeader.h" #import "SentryTraceOrigin.h" #import "SentryTraceProfiler.h" +#import "SentryUncaughtNSExceptions.h" #import "SentryWatchdogTerminationBreadcrumbProcessor.h" diff --git a/Sources/Sentry/include/SentryScope+Private.h b/Sources/Sentry/include/SentryScope+Private.h index a411bd4f744..3c7fd7d5c9e 100644 --- a/Sources/Sentry/include/SentryScope+Private.h +++ b/Sources/Sentry/include/SentryScope+Private.h @@ -1,6 +1,7 @@ #import #import "SentryLevel.h" +#import "SentryScope+PrivateSwift.h" #import "SentryScope.h" @class SentryAttachment; diff --git a/Sources/Swift/Core/Integrations/Integrations.swift b/Sources/Swift/Core/Integrations/Integrations.swift index 7106ccb8ac2..6cb980c3384 100644 --- a/Sources/Swift/Core/Integrations/Integrations.swift +++ b/Sources/Swift/Core/Integrations/Integrations.swift @@ -36,8 +36,12 @@ private struct AnyIntegration { @objc public class func install(with options: Options) { let dependencies = SentryDependencyContainer.sharedInstance() + // The order of integrations here is important. + // SentryCrashIntegration needs to be initialized before SentryAutoSessionTrackingIntegration. + // And SentrySessionReplayIntegration before SentryCrashIntegration. var integrations: [AnyIntegration] = [ .init(SwiftAsyncIntegration.self), + .init(SentryCrashIntegration.self), .init(SentryAutoSessionTrackingIntegration.self), .init(SentryNetworkTrackingIntegration.self), .init(SentryHangTrackerIntegrationObjC.self), diff --git a/Sources/Swift/Integrations/SentryCrash/SentryCrashInstallationReporter.swift b/Sources/Swift/Integrations/SentryCrash/SentryCrashInstallationReporter.swift new file mode 100644 index 00000000000..e7bfa2b53c3 --- /dev/null +++ b/Sources/Swift/Integrations/SentryCrash/SentryCrashInstallationReporter.swift @@ -0,0 +1,46 @@ +@_implementationOnly import _SentryPrivate +import Foundation + +/** + * Crash installation reporter that handles Sentry-specific reporting details. + * + * This class extends SentryCrashInstallation to provide Sentry-specific crash report + * processing through a SentryCrashReportSink. + */ +final class SentryCrashInstallationReporter: SentryCrashInstallation { + + private let inAppLogic: SentryInAppLogic + private let crashWrapper: SentryCrashWrapper + private let dispatchQueue: SentryDispatchQueueWrapper + + init( + inAppLogic: SentryInAppLogic, + crashWrapper: SentryCrashWrapper, + dispatchQueue: SentryDispatchQueueWrapper + ) { + self.inAppLogic = inAppLogic + self.crashWrapper = crashWrapper + self.dispatchQueue = dispatchQueue + super.init(requiredProperties: []) + } + + override func sink() -> (any SentryCrashReportFilter)? { + return SentryCrashReportSink( + inAppLogic: inAppLogic, + crashWrapper: crashWrapper, + dispatchQueue: dispatchQueue + ) + } + + override func sendAllReports(completion onCompletion: SentryCrashReportFilterCompletion?) { + super.sendAllReports { filteredReports, completed, error in + if let error = error { + SentrySDKLog.error("Error sending crash reports: \(error.localizedDescription)") + } + SentrySDKLog.debug("Sent \(String(describing: filteredReports?.count)) crash report(s)") + if completed, let onCompletion = onCompletion { + onCompletion(filteredReports, completed, error) + } + } + } +} diff --git a/Sources/Swift/Integrations/SentryCrash/SentryCrashIntegration.swift b/Sources/Swift/Integrations/SentryCrash/SentryCrashIntegration.swift new file mode 100644 index 00000000000..57d56cc659f --- /dev/null +++ b/Sources/Swift/Integrations/SentryCrash/SentryCrashIntegration.swift @@ -0,0 +1,246 @@ +@_implementationOnly import _SentryPrivate +import Foundation + +#if (os(iOS) || os(tvOS) || os(visionOS)) && !SENTRY_NO_UIKIT +import UIKit +#endif + +// MARK: - C Callback Function + +/// Global function to finish and save transaction when a crash occurs. +/// This function is called from C crash reporting code. +@_cdecl("sentry_finishAndSaveTransaction") +public func sentry_finishAndSaveTransaction() { + let scope = SentrySDKInternal.currentHub().scope as Scope + guard let span = scope.getCastedInternalSpan() else { + SentrySDKLog.debug("No span found in current scope, skipping transaction finish and save") + return + } + span.tracer?.finishForCrash() +} + +// MARK: - Dependency Provider + +/// Provides dependencies for `SentryCrashIntegration`. +typealias CrashIntegrationProvider = SentryCrashReporterProvider & CrashIntegrationSessionHandlerBuilder & CrashInstallationReporterBuilder + +// MARK: - SentryCrashIntegration + +final class SentryCrashIntegration: NSObject, SwiftIntegration { + + private weak var options: Options? + private var sessionHandler: SentryCrashIntegrationSessionHandler? + private var scopeObserver: SentryCrashScopeObserver? + private var crashReporter: SentryCrashSwift + private var installation: SentryCrashInstallationReporter? + + // MARK: - Initialization + + // swiftlint:disable function_body_length + init?(with options: Options, dependencies: Dependencies) { + guard options.enableCrashHandler else { + SentrySDKLog.debug("Not going to enable \(Self.name) because enableCrashHandler is disabled.") + return nil + } + + self.options = options + self.crashReporter = dependencies.crashReporter + + super.init() + + self.sessionHandler = dependencies.getCrashIntegrationSessionBuilder(options) + self.scopeObserver = SentryCrashScopeObserver(maxBreadcrumbs: Int(options.maxBreadcrumbs)) + + guard self.sessionHandler != nil, self.scopeObserver != nil else { + SentrySDKLog.warning("Failed to initialize SentryCrashIntegration dependencies") + return nil + } + + var enableSigtermReporting = false + #if !os(watchOS) + enableSigtermReporting = options.enableSigtermReporting + #endif + + var enableUncaughtNSExceptionReporting = false + #if os(macOS) + if options.enableSwizzling { + enableUncaughtNSExceptionReporting = options.enableUncaughtNSExceptionReporting + } + #endif + + startCrashHandler( + cacheDirectory: options.cacheDirectoryPath, + enableSigtermReporting: enableSigtermReporting, + enableReportingUncaughtExceptions: enableUncaughtNSExceptionReporting, + enableCppExceptionsV2: options.experimental.enableUnhandledCPPExceptionsV2, + dependencies: dependencies + ) + + configureScope() + + if options.enablePersistingTracesWhenCrashing { + configureTracingWhenCrashing() + } + } + // swiftlint:enable function_body_length + + // MARK: - SwiftIntegration + + static var name: String { + "SentryCrashIntegration" + } + + func uninstall() { + if let installation = installation { + installation.uninstall() + } + + sentrycrash_setSaveTransaction(nil) + + NotificationCenter.default.removeObserver( + self, + name: NSLocale.currentLocaleDidChangeNotification, + object: nil + ) + } + + // MARK: - Crash Handler + + private func startCrashHandler( + cacheDirectory: String, + enableSigtermReporting: Bool, + enableReportingUncaughtExceptions: Bool, + enableCppExceptionsV2: Bool, + dependencies: Dependencies + ) { + var canSendReports = false + + if installation == nil { + guard let options = self.options else { + SentrySDKLog.debug("No options found, skipping crash handler initialization") + return + } + + self.installation = dependencies.getCrashInstallationReporter(options) + canSendReports = true + } + + sentrycrashcm_setEnableSigtermReporting(enableSigtermReporting) + + installation?.install(cacheDirectory) + + #if os(macOS) + if enableReportingUncaughtExceptions { + SentryUncaughtNSExceptions.configureCrashOnExceptions() + SentryUncaughtNSExceptions.swizzleNSApplicationReportException() + } + #endif + + if enableCppExceptionsV2 { + SentrySDKLog.debug("Enabling CppExceptionsV2 by swapping cxa_throw.") + sentrycrashcm_cppexception_enable_swap_cxa_throw() + } + + // We need to send the crashed event together with the crashed session in the same envelope + // to have proper statistics in release health. To achieve this we need both synchronously + // in the hub. The crashed event is converted from a SentryCrashReport to an event in + // SentryCrashReportSink and then passed to the SDK on a background thread. This process is + // started with installing this integration. We need to end and delete the previous session + // before being able to start a new session for the AutoSessionTrackingIntegration. The + // SentryCrashIntegration is installed before the AutoSessionTrackingIntegration so there is + // no guarantee if the crashed event is created before or after the + // AutoSessionTrackingIntegration. By ending the previous session and storing it as crashed + // in here we have the guarantee once the crashed event is sent to the hub it is already + // there and the AutoSessionTrackingIntegration can work properly. + // + // This is a pragmatic and not the most optimal place for this logic. + self.sessionHandler?.endCurrentSessionIfRequired() + + // We only need to send all reports on the first initialization of SentryCrash. If + // SentryCrash was deactivated there are no new reports to send. Furthermore, the + // g_reportsPath in SentryCrashReportsStore gets set when SentryCrash is installed. In + // production usage, this path is not supposed to change. When testing, this path can + // change, and therefore, the initial set g_reportsPath can be deleted. sendAllReports calls + // deleteAllReports, which fails it can't access g_reportsPath. We could fix SentryCrash or + // just not call sendAllReports as it doesn't make sense to call it twice as described + // above. + if canSendReports { + sendAllSentryCrashReportsInternal() + } + } + +#if SENTRY_TEST || SENTRY_TEST_CI + /// Sends all pending crash reports. Called internally during initialization, + /// and exposed for testing purposes. + func sendAllSentryCrashReports() { + sendAllSentryCrashReportsInternal() + } +#endif + + /// Sends all pending crash reports. Called internally during initialization. + private func sendAllSentryCrashReportsInternal() { + installation?.sendAllReports(completion: nil) + } + + // MARK: - Scope Configuration + + private func configureScope() { + // We need to make sure to set always the scope to SentryCrash so we have it in + // case of a crash + SentrySDKInternal.currentHub().configureScope { [weak self] outerScope in + guard let self = self, let options = self.options else { return } + + var userInfo = outerScope.serialize() + + // SentryCrashReportConverter.convertReportToEvent needs the release name and + // the dist of the SentryOptions in the UserInfo. When SentryCrash records a + // crash it writes the UserInfo into SentryCrashField_User of the report. + // SentryCrashReportConverter.initWithReport loads the contents of + // SentryCrashField_User into self.userContext and convertReportToEvent can map + // the release name and dist to the SentryEvent. Fixes GH-581 + userInfo["release"] = options.releaseName + userInfo["dist"] = options.dist + + // Crashes don't use the attributes field, we remove them to avoid uploading them + // unnecessarily. + userInfo.removeValue(forKey: "attributes") + + crashReporter.userInfo = userInfo + + if let scopeObserver = self.scopeObserver { + outerScope.add(scopeObserver) + } + } + + NotificationCenter.default.addObserver( + self, + selector: #selector(currentLocaleDidChange), + name: NSLocale.currentLocaleDidChangeNotification, + object: nil + ) + } + + // Exposed to objc for the NotificationCenter in configureScope() + @objc private func currentLocaleDidChange() { + SentrySDKInternal.currentHub().configureScope { scope in + var device: [String: Any] + let contextDictionary = scope.contextDictionary + if let existingDevice = contextDictionary[SENTRY_CONTEXT_DEVICE_KEY] as? [String: Any] { + device = existingDevice + } else { + device = [:] + } + + let locale = Locale.autoupdatingCurrent.identifier + device["locale"] = locale + + scope.setContext(value: device, key: SENTRY_CONTEXT_DEVICE_KEY) + } + } + + // MARK: - Tracing Configuration + + private func configureTracingWhenCrashing() { + sentrycrash_setSaveTransaction(sentry_finishAndSaveTransaction) + } +} diff --git a/Sources/Swift/Integrations/SentryCrash/SentryCrashIntegrationSessionHandler.swift b/Sources/Swift/Integrations/SentryCrash/SentryCrashIntegrationSessionHandler.swift new file mode 100644 index 00000000000..3cf6af5a204 --- /dev/null +++ b/Sources/Swift/Integrations/SentryCrash/SentryCrashIntegrationSessionHandler.swift @@ -0,0 +1,86 @@ +@_implementationOnly import _SentryPrivate +import Foundation + +#if (os(iOS) || os(tvOS) || os(visionOS)) && !SENTRY_NO_UIKIT +import UIKit +#endif + +final class SentryCrashIntegrationSessionHandler: NSObject { + + private let crashWrapper: SentryCrashWrapper + private let fileManager: SentryFileManager + + #if (os(iOS) || os(tvOS) || os(visionOS)) && !SENTRY_NO_UIKIT + private let watchdogTerminationLogic: SentryWatchdogTerminationLogic + #endif + + #if (os(iOS) || os(tvOS) || os(visionOS)) && !SENTRY_NO_UIKIT + init( + crashWrapper: SentryCrashWrapper, + watchdogTerminationLogic: SentryWatchdogTerminationLogic, + fileManager: SentryFileManager + ) { + self.crashWrapper = crashWrapper + self.watchdogTerminationLogic = watchdogTerminationLogic + self.fileManager = fileManager + super.init() + } + #else + init(crashWrapper: SentryCrashWrapper, fileManager: SentryFileManager) { + self.crashWrapper = crashWrapper + self.fileManager = fileManager + super.init() + } + #endif + + /** + * When a crash or a watchdog termination happens, we end the current session as crashed, store it + * in a dedicated location, and delete the current one. The same applies if a fatal app hang occurs. + * Then, we end the current session as abnormal and store it in a dedicated abnormal session + * location. + * + * Check out the SentryHub, which implements most of the session logic, for more details about + * sessions. + */ + func endCurrentSessionIfRequired() { + guard let session = fileManager.readCurrentSession() else { + SentrySDKLog.debug("No current session found to end.") + return + } + + #if (os(iOS) || os(tvOS) || os(visionOS)) && !SENTRY_NO_UIKIT + let shouldEndAsCrashed = crashWrapper.crashedLastLaunch || watchdogTerminationLogic.isWatchdogTermination() + #else + let shouldEndAsCrashed = crashWrapper.crashedLastLaunch + #endif + + if shouldEndAsCrashed { + let timeSinceLastCrash = SentryDependencyContainer.sharedInstance().dateProvider.date() + .addingTimeInterval(-crashWrapper.activeDurationSinceLastCrash) + + session.endCrashed(withTimestamp: timeSinceLastCrash) + fileManager.storeCrashedSession(session) + fileManager.deleteCurrentSession() + } else { +#if (os(iOS) || os(tvOS) || os(visionOS)) && !SENTRY_NO_UIKIT + // Checking the file existence is way cheaper than reading the file and parsing its contents + // to an Event. + guard fileManager.appHangEventExists() else { + SentrySDKLog.debug("No app hang event found. Won't end current session.") + return + } + + guard let appHangEvent = fileManager.readAppHangEvent() else { + // Just in case the file was deleted between the check and the read. + SentrySDKLog.warning("App hang event deleted between check and read. Cannot end current session.") + return + } + + session.endAbnormal(withTimestamp: appHangEvent.timestamp ?? Date()) + fileManager.storeAbnormalSession(session) + fileManager.deleteCurrentSession() +#endif + } + + } +} diff --git a/Sources/Swift/SentryDependencyContainer.swift b/Sources/Swift/SentryDependencyContainer.swift index 6421e2003bc..c0f4dfd4ce8 100644 --- a/Sources/Swift/SentryDependencyContainer.swift +++ b/Sources/Swift/SentryDependencyContainer.swift @@ -1,4 +1,5 @@ -// swiftlint:disable missing_docs +//swiftlint:disable file_length missing_docs + @_implementationOnly import _SentryPrivate #if (os(iOS) || os(tvOS) || os(visionOS)) && !SENTRY_NO_UIKIT import UIKit @@ -200,6 +201,30 @@ extension SentryFileManager: SentryFileManagerProtocol { } } } #endif + + private var crashIntegrationSessionHandler: SentryCrashIntegrationSessionHandler? + func getCrashIntegrationSessionBuilder(_ options: Options) -> SentryCrashIntegrationSessionHandler? { + getOptionalLazyVar(\.crashIntegrationSessionHandler) { + + guard let fileManager = fileManager else { + SentrySDKLog.fatal("File manager is not available") + return nil + } + +#if (os(iOS) || os(tvOS) || os(visionOS)) && !SENTRY_NO_UIKIT + let watchdogLogic = SentryWatchdogTerminationLogic(options: options, + crashAdapter: crashWrapper, + appStateManager: appStateManager) + return SentryCrashIntegrationSessionHandler( + crashWrapper: crashWrapper, + watchdogTerminationLogic: watchdogLogic, + fileManager: fileManager + ) +#else + return SentryCrashIntegrationSessionHandler(crashWrapper: crashWrapper, fileManager: fileManager) +#endif + } + } #if (os(iOS) || os(tvOS)) && !SENTRY_NO_UIKIT private var _screenshotSource: SentryScreenshotSource? @@ -266,6 +291,19 @@ extension SentryFileManager: SentryFileManagerProtocol { } #endif } } + + private var crashInstallationReporter: SentryCrashInstallationReporter? + func getCrashInstallationReporter(_ options: Options) -> SentryCrashInstallationReporter { + getLazyVar(\.crashInstallationReporter) { + let inAppLogic = SentryInAppLogic(inAppIncludes: options.inAppIncludes) + + return SentryCrashInstallationReporter( + inAppLogic: inAppLogic, + crashWrapper: crashWrapper, + dispatchQueue: dispatchQueueWrapper + ) + } + } } #if os(iOS) && !SENTRY_NO_UIKIT @@ -371,4 +409,20 @@ extension SentryDependencyContainer: NetworkTrackerProvider { SentryNetworkTracker.sharedInstance } } -// swiftlint:enable missing_docs + +protocol SentryCrashReporterProvider { + var crashReporter: SentryCrashSwift { get } +} +extension SentryDependencyContainer: SentryCrashReporterProvider {} + +protocol CrashIntegrationSessionHandlerBuilder { + func getCrashIntegrationSessionBuilder(_ options: Options) -> SentryCrashIntegrationSessionHandler? +} +extension SentryDependencyContainer: CrashIntegrationSessionHandlerBuilder {} + +protocol CrashInstallationReporterBuilder { + func getCrashInstallationReporter(_ options: Options) -> SentryCrashInstallationReporter +} +extension SentryDependencyContainer: CrashInstallationReporterBuilder {} + +//swiftlint:enable file_length missing_docs diff --git a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegration+TestInit.h b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegration+TestInit.h deleted file mode 100644 index b56a3af0ff8..00000000000 --- a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegration+TestInit.h +++ /dev/null @@ -1,12 +0,0 @@ -#import "SentryCrashIntegration.h" - -NS_ASSUME_NONNULL_BEGIN - -@interface SentryCrashIntegration (TestInit) - -- (instancetype)initWithCrashAdapter:(SentryCrashWrapper *)crashWrapper - andDispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper; - -@end - -NS_ASSUME_NONNULL_END diff --git a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift index f0619b7e7d2..19ea19902c3 100644 --- a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift @@ -49,18 +49,20 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { return session } - func getSut() -> SentryCrashIntegration { - return getSut(crashWrapper: sentryCrash) + func getSut() throws -> SentryCrashIntegration { + return try getSut(crashWrapper: sentryCrash) } - - func getSut(crashWrapper: SentryCrashWrapper) -> SentryCrashIntegration { - return SentryCrashIntegration(crashAdapter: crashWrapper, andDispatchQueueWrapper: dispatchQueueWrapper) + + func getSut(crashWrapper: SentryCrashWrapper, fileManager: SentryFileManager? = nil, options: Options? = nil) throws -> SentryCrashIntegration { + let mockedDependencies = MockCrashDependencies(crashWrapper: crashWrapper, dispatchQueueWrapper: dispatchQueueWrapper, fileManager: fileManager) + return try XCTUnwrap(SentryCrashIntegration(with: options ?? self.options, dependencies: mockedDependencies)) } - - var sutWithoutCrash: SentryCrashIntegration { + + var sutWithoutCrash: SentryCrashIntegration? { let crash = sentryCrash crash.internalCrashedLastLaunch = false - return SentryCrashIntegration(crashAdapter: crash, andDispatchQueueWrapper: dispatchQueueWrapper) + let mockedDependencies = MockCrashDependencies(crashWrapper: crash, dispatchQueueWrapper: dispatchQueueWrapper) + return SentryCrashIntegration(with: options, dependencies: mockedDependencies) } } @@ -129,8 +131,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { try advanceTime(bySeconds: 10) - let sut = fixture.getSut() - sut.install(with: Options()) + _ = try fixture.getSut() assertCrashedSessionStored(expected: expectedCrashedSession) } @@ -145,21 +146,20 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { SentrySDKInternal.setCurrentHub(fixture.hub) try advanceTime(bySeconds: 10) - let sut = fixture.sutWithoutCrash - sut.install(with: fixture.options) + _ = try XCTUnwrap(fixture.sutWithoutCrash) assertCrashedSessionStored(expected: expectedCrashedSession) } - func testOutOfMemoryTrackingDisabled() { + func testOutOfMemoryTrackingDisabled() throws { givenOOMAppState() let session = givenCurrentSession() - let sut = fixture.sutWithoutCrash + _ = try XCTUnwrap(fixture.sutWithoutCrash) + let options = fixture.options options.enableWatchdogTerminationTracking = false - sut.install(with: options) let fileManager = fixture.client.fileManager XCTAssertEqual(session, fileManager.readCurrentSession()) @@ -168,11 +168,9 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { } #endif - - func testEndSessionAsCrashed_NoClientSet() { - let (sut, _) = givenSutWithGlobalHub() - - sut.install(with: Options()) + + func testEndSessionAsCrashed_NoClientSet() throws { + let (_, _) = try givenSutWithGlobalHub() let fileManager = fixture.client.fileManager XCTAssertNil(fileManager.readCurrentSession()) @@ -180,24 +178,21 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { XCTAssertNil(fileManager.readAbnormalSession()) } - func testEndSessionAsCrashed_NoCrashLastLaunch() { + func testEndSessionAsCrashed_NoCrashLastLaunch() throws { let session = givenCurrentSession() - + let sentryCrash = fixture.sentryCrash sentryCrash.internalCrashedLastLaunch = false - let sut = SentryCrashIntegration(crashAdapter: sentryCrash, andDispatchQueueWrapper: fixture.dispatchQueueWrapper) - sut.install(with: Options()) - + _ = try fixture.getSut(crashWrapper: sentryCrash) + let fileManager = fixture.client.fileManager XCTAssertEqual(session, fileManager.readCurrentSession()) XCTAssertNil(fileManager.readCrashedSession()) XCTAssertNil(fileManager.readAbnormalSession()) } - func testEndSessionAsCrashed_NoCurrentSession() { - let (sut, _) = givenSutWithGlobalHub() - - sut.install(with: Options()) + func testEndSessionAsCrashed_NoCurrentSession() throws { + let (_, _) = try givenSutWithGlobalHub() let fileManager = fixture.client.fileManager XCTAssertNil(fileManager.readCurrentSession()) @@ -208,14 +203,13 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { // Abnormal sessions only work when we the SDK can detect fatal app hang events. These only work on iOS, tvOS and macCatalyst #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) - func testEndSessionAsAbnormal_NoHubBound() { + func testEndSessionAsAbnormal_NoHubBound() throws { // Arrange let sentryCrash = fixture.sentryCrash sentryCrash.internalCrashedLastLaunch = false - let sut = SentryCrashIntegration(crashAdapter: sentryCrash, andDispatchQueueWrapper: fixture.dispatchQueueWrapper) // Act - sut.install(with: Options()) + _ = try fixture.getSut(crashWrapper: sentryCrash) // Assert let fileManager = fixture.client.fileManager @@ -224,15 +218,14 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { XCTAssertNil(fileManager.readAbnormalSession()) } - func testEndSessionAsAbnormal_NoCurrentSession() { + func testEndSessionAsAbnormal_NoCurrentSession() throws { // Arrange SentrySDKInternal.setCurrentHub(fixture.hub) let sentryCrash = fixture.sentryCrash sentryCrash.internalCrashedLastLaunch = false - let sut = SentryCrashIntegration(crashAdapter: sentryCrash, andDispatchQueueWrapper: fixture.dispatchQueueWrapper) // Act - sut.install(with: Options()) + _ = try fixture.getSut(crashWrapper: sentryCrash) // Assert let fileManager = fixture.client.fileManager @@ -241,17 +234,16 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { XCTAssertNil(fileManager.readAbnormalSession()) } - func testEndSessionAsAbnormal_NoAppHangEvent() { + func testEndSessionAsAbnormal_NoAppHangEvent() throws { // Arrange SentrySDKInternal.setCurrentHub(fixture.hub) let sentryCrash = fixture.sentryCrash sentryCrash.internalCrashedLastLaunch = false - let sut = SentryCrashIntegration(crashAdapter: sentryCrash, andDispatchQueueWrapper: fixture.dispatchQueueWrapper) let session = givenCurrentSession() // Act - sut.install(with: Options()) + _ = try fixture.getSut(crashWrapper: sentryCrash) // Assert let fileManager = fixture.client.fileManager @@ -272,14 +264,13 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { SentrySDKInternal.setCurrentHub(fixture.hub) let sentryCrash = fixture.sentryCrash sentryCrash.internalCrashedLastLaunch = false - let sut = SentryCrashIntegration(crashAdapter: sentryCrash, andDispatchQueueWrapper: fixture.dispatchQueueWrapper) let session = givenCurrentSession() let appHangEvent = Event() fileManager.storeAppHang(appHangEvent) - + // Act - sut.install(with: Options()) + _ = try fixture.getSut(crashWrapper: sentryCrash, fileManager: fileManager) // Assert XCTAssertEqual(session, fileManager.readCurrentSession()) @@ -292,7 +283,6 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { SentrySDKInternal.setCurrentHub(fixture.hub) let sentryCrash = fixture.sentryCrash sentryCrash.internalCrashedLastLaunch = false - let sut = SentryCrashIntegration(crashAdapter: sentryCrash, andDispatchQueueWrapper: fixture.dispatchQueueWrapper) let session = givenCurrentSession() @@ -301,7 +291,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { fileManager.storeAppHang(appHangEvent) // Act - sut.install(with: Options()) + _ = try fixture.getSut(crashWrapper: sentryCrash) // Assert XCTAssertNil(fileManager.readCurrentSession()) @@ -328,8 +318,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { try advanceTime(bySeconds: 10) // Act - let sut = fixture.getSut() - sut.install(with: Options()) + _ = try fixture.getSut() // Assert assertCrashedSessionStored(expected: expectedCrashedSession) @@ -338,10 +327,8 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { #endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) - func testUninstall_DoesNotUpdateLocale_OnLocaleDidChangeNotification() { - let (sut, hub) = givenSutWithGlobalHubAndCrashWrapper() - - sut.install(with: Options()) + func testUninstall_DoesNotUpdateLocale_OnLocaleDidChangeNotification() throws { + let (sut, hub) = try givenSutWithGlobalHubAndCrashWrapper() let locale = "garbage" setLocaleToGlobalScope(locale: locale) @@ -353,18 +340,17 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { assertLocaleOnHub(locale: locale, hub: hub) } - func testOSCorrectlySetToScopeContext() { - let (sut, hub) = givenSutWithGlobalHubAndCrashWrapper() - - sut.install(with: Options()) + func testOSCorrectlySetToScopeContext() throws { + let (_, hub) = try givenSutWithGlobalHubAndCrashWrapper() assertContext(context: hub.scope.contextDictionary as? [String: Any] ?? ["": ""]) } - func testLocaleChanged_NoDeviceContext_SetsCurrentLocale() { - let (sut, hub) = givenSutWithGlobalHub() - - sut.install(with: Options()) + func testLocaleChanged_NoDeviceContext_SetsCurrentLocale() throws { + let (sut, hub) = try givenSutWithGlobalHub() + defer { + sut.uninstall() + } SentrySDK.configureScope { scope in scope.removeContext(key: "device") @@ -375,10 +361,11 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { assertLocaleOnHub(locale: Locale.autoupdatingCurrent.identifier, hub: hub) } - func testLocaleChanged_DifferentLocale_SetsCurrentLocale() { - let (sut, hub) = givenSutWithGlobalHubAndCrashWrapper() - - sut.install(with: Options()) + func testLocaleChanged_DifferentLocale_SetsCurrentLocale() throws { + let (sut, hub) = try givenSutWithGlobalHubAndCrashWrapper() + defer { + sut.uninstall() + } setLocaleToGlobalScope(locale: "garbage") @@ -388,8 +375,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { } func testStartUpCrash_CallsFlush() throws { - let (sut, hub) = givenSutWithGlobalHubAndCrashWrapper() - sut.install(with: Options()) + let (sut, hub) = try givenSutWithGlobalHubAndCrashWrapper() // Manually reset and enable the crash state because tearing down the global state in SentryCrash to achieve the same is complicated and doesn't really work. let crashStatePath = String(cString: sentrycrashstate_filePath()) @@ -412,7 +398,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { // Force reloading of crash state sentrycrashstate_initialize(sentrycrashstate_filePath()) // Force sending all reports, because the crash reports are only sent once after first init. - SentryCrashIntegration.sendAllSentryCrashReports() + sut.sendAllSentryCrashReports() XCTAssertEqual(1, transport.flushInvocations.count) XCTAssertEqual(5.0, transport.flushInvocations.first) @@ -426,130 +412,136 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { func testUncaughtExceptions_Enabled() throws { defer { resetUserDefaults() } - - let (sut, _) = givenSutWithGlobalHubAndCrashWrapper() + let options = Options() options.enableUncaughtNSExceptionReporting = true - sut.install(with: options) - + options.enableSwizzling = true + options.enableCrashHandler = true + + let (_, _) = try givenSutWithGlobalHubAndCrashWrapper(options) + XCTAssertTrue(UserDefaults.standard.bool(forKey: "NSApplicationCrashOnExceptions")) // We have to set the flat to false, cause otherwise we would crash UserDefaults.standard.set(false, forKey: "NSApplicationCrashOnExceptions") - + let crashReporter = SentryDependencyContainer.sharedInstance().crashReporter - + defer { crashReporter.uncaughtExceptionHandler = nil wasUncaughtExceptionHandlerCalled = false } crashReporter.uncaughtExceptionHandler = uncaughtExceptionHandler - + NSApplication.shared.reportException(uncaughtInternalInconsistencyException) XCTAssertTrue(wasUncaughtExceptionHandlerCalled) } - + func testUncaughtExceptions_Enabled_ButSwizzlingDisabled() throws { defer { resetUserDefaults() } - - let (sut, _) = givenSutWithGlobalHubAndCrashWrapper() + let options = Options() options.enableUncaughtNSExceptionReporting = true options.enableSwizzling = false - sut.install(with: options) - + options.enableCrashHandler = true + + let (_, _) = try givenSutWithGlobalHubAndCrashWrapper(options) + XCTAssertFalse(UserDefaults.standard.bool(forKey: "NSApplicationCrashOnExceptions")) - + let crashReporter = SentryDependencyContainer.sharedInstance().crashReporter - + defer { crashReporter.uncaughtExceptionHandler = nil wasUncaughtExceptionHandlerCalled = false } crashReporter.uncaughtExceptionHandler = uncaughtExceptionHandler - + NSApplication.shared.reportException(uncaughtInternalInconsistencyException) XCTAssertFalse(wasUncaughtExceptionHandlerCalled) } - - func testUncaughtExceptions_Disabled() { + + func testUncaughtExceptions_Disabled() throws { defer { resetUserDefaults() } - - let (sut, _) = givenSutWithGlobalHubAndCrashWrapper() + let options = Options() options.enableUncaughtNSExceptionReporting = false - sut.install(with: options) - + options.enableCrashHandler = true + + let (_, _) = try givenSutWithGlobalHubAndCrashWrapper(options) + XCTAssertFalse(UserDefaults.standard.bool(forKey: "NSApplicationCrashOnExceptions")) - + let crashReporter = SentryDependencyContainer.sharedInstance().crashReporter - + defer { crashReporter.uncaughtExceptionHandler = nil wasUncaughtExceptionHandlerCalled = false } crashReporter.uncaughtExceptionHandler = uncaughtExceptionHandler - + NSApplication.shared.reportException(uncaughtInternalInconsistencyException) XCTAssertFalse(wasUncaughtExceptionHandlerCalled) } #endif // os(macOS) - func testEnableCppExceptionsV2_SwapsCxaThrow() { + func testEnableCppExceptionsV2_SwapsCxaThrow() throws { // Arrange defer { sentrycrashct_unswap_cxa_throw() } - let (sut, _) = givenSutWithGlobalHubAndCrashWrapper() let options = Options() options.experimental.enableUnhandledCPPExceptionsV2 = true + options.enableCrashHandler = true - // Act - sut.install(with: options) + let (_, _) = try givenSutWithGlobalHubAndCrashWrapper(options) // Assert XCTAssertTrue(sentrycrashct_is_cxa_throw_swapped(), "C++ exception throw handler must be swapped when enableUnhandledCPPExceptionsV2 is true.") } - func testCppExceptionsV2NotEnabled_DoesNotSwapCxaThrow() { + func testCppExceptionsV2NotEnabled_DoesNotSwapCxaThrow() throws { // Arrange defer { sentrycrashct_unswap_cxa_throw() } - let (sut, _) = givenSutWithGlobalHubAndCrashWrapper() let options = Options() options.experimental.enableUnhandledCPPExceptionsV2 = false + options.enableCrashHandler = true // Act - sut.install(with: options) + let (_, _) = try givenSutWithGlobalHubAndCrashWrapper(options) // Assert XCTAssertFalse(sentrycrashct_is_cxa_throw_swapped(), "C++ exception throw handler must NOT be swapped when enableUnhandledCPPExceptionsV2 is false.") } func testEnableTracingForCrashes_SetsCallback() throws { - let (sut, _) = givenSutWithGlobalHubAndCrashWrapper() let options = Options() options.enablePersistingTracesWhenCrashing = true - sut.install(with: options) - + options.enableCrashHandler = true + + let (_, _) = try givenSutWithGlobalHubAndCrashWrapper(options) + XCTAssertTrue(sentrycrash_hasSaveTransaction()) } - + func testEnableTracingForCrashes_Uninstall_RemovesCallback() throws { - let (sut, _) = givenSutWithGlobalHubAndCrashWrapper() let options = Options() options.enablePersistingTracesWhenCrashing = true - sut.install(with: options) - + options.enableCrashHandler = true + + let (sut, _) = try givenSutWithGlobalHubAndCrashWrapper(options) + sut.uninstall() - + XCTAssertFalse(sentrycrash_hasSaveTransaction()) } - + func testEnableTracingForCrashes_Disabled_DoesNotSetCallback() throws { - let (sut, _) = givenSutWithGlobalHubAndCrashWrapper() let options = Options() options.enablePersistingTracesWhenCrashing = false - sut.install(with: options) - + options.enableCrashHandler = true + + let (_, _) = try givenSutWithGlobalHubAndCrashWrapper(options) + XCTAssertFalse(sentrycrash_hasSaveTransaction()) } @@ -562,8 +554,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { let hub = SentryHubInternal(client: client, andScope: nil) SentrySDKInternal.setCurrentHub(hub) - let sut = fixture.getSut(crashWrapper: SentryDependencyContainer.sharedInstance().crashWrapper) - sut.install(with: options) + _ = try fixture.getSut(crashWrapper: SentryDependencyContainer.sharedInstance().crashWrapper) let transaction = SentrySDK.startTransaction(name: "Crashing", operation: "Operation", bindToScope: true) @@ -587,8 +578,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { let hub = SentryHubInternal(client: client, andScope: nil) SentrySDKInternal.setCurrentHub(hub) - let sut = fixture.getSut(crashWrapper: SentryDependencyContainer.sharedInstance().crashWrapper) - sut.install(with: options) + _ = try fixture.getSut(crashWrapper: SentryDependencyContainer.sharedInstance().crashWrapper) let transaction = SentrySDK.startTransaction(name: "name", operation: "operation", bindToScope: true) SentrySDKInternal.currentHub().scope.span = nil @@ -608,8 +598,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { let hub = SentryHubInternal(client: client, andScope: nil) SentrySDKInternal.setCurrentHub(hub) - let sut = fixture.getSut(crashWrapper: SentryDependencyContainer.sharedInstance().crashWrapper) - sut.install(with: options) + _ = try fixture.getSut(crashWrapper: SentryDependencyContainer.sharedInstance().crashWrapper) let transaction = SentrySDK.startTransaction(name: "name", operation: "operation", bindToScope: true) let span = transaction.startChild(operation: "child") @@ -638,11 +627,8 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { } // UserInfo is set when installing the integration, so let's manually install it again to use the new scope values - let sentryCrash = fixture.sentryCrash - let sut = SentryCrashIntegration(crashAdapter: sentryCrash, andDispatchQueueWrapper: fixture.dispatchQueueWrapper) + _ = try fixture.getSut() - sut.install(with: Options()) - let userInfo = try XCTUnwrap(SentryDependencyContainer.sharedInstance().crashReporter.userInfo) // Double check the environment just set is in the user info assertUserInfoField(userInfo: userInfo, key: "environment", expected: "test-attributes") @@ -673,19 +659,19 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { } #endif - private func givenSutWithGlobalHub() -> (SentryCrashIntegration, SentryHubInternal) { - let sut = fixture.getSut() + private func givenSutWithGlobalHub() throws -> (SentryCrashIntegration, SentryHubInternal) { + let sut = try XCTUnwrap(fixture.getSut()) let hub = fixture.hub SentrySDKInternal.setCurrentHub(hub) return (sut, hub) } - private func givenSutWithGlobalHubAndCrashWrapper() -> (SentryCrashIntegration, SentryHubInternal) { + private func givenSutWithGlobalHubAndCrashWrapper(_ options: Options? = nil) throws -> (SentryCrashIntegration, SentryHubInternal) { #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) SentryDependencyContainer.sharedInstance().uiDeviceWrapper.start() #endif - let sut = fixture.getSut(crashWrapper: SentryDependencyContainer.sharedInstance().crashWrapper) + let sut = try fixture.getSut(crashWrapper: SentryDependencyContainer.sharedInstance().crashWrapper, options: options) let hub = fixture.hub SentrySDKInternal.setCurrentHub(hub) @@ -778,3 +764,56 @@ private class DeleteAppHangWhenCheckingExistenceFileManager: SentryFileManager { return result } } + +class MockCrashDependencies: CrashIntegrationProvider { + + let mockedCrashWrapper: SentryCrashWrapper + let mockedDispatchQueueWrapper: SentryDispatchQueueWrapper + let mockedFileManager: SentryFileManager? + + init(crashWrapper: SentryCrashWrapper, dispatchQueueWrapper: SentryDispatchQueueWrapper, fileManager: SentryFileManager? = nil) { + self.mockedCrashWrapper = crashWrapper + self.mockedDispatchQueueWrapper = dispatchQueueWrapper + self.mockedFileManager = fileManager + } + + var appStateManager: Sentry.SentryAppStateManager { + SentryDependencyContainer.sharedInstance().appStateManager + } + + var fileManager: Sentry.SentryFileManager? { + mockedFileManager ?? SentryDependencyContainer.sharedInstance().fileManager + } + + func getCrashIntegrationSessionBuilder(_ options: Sentry.Options) -> Sentry.SentryCrashIntegrationSessionHandler? { + guard let fileManager else { + return nil + } +#if (os(iOS) || os(tvOS) || os(visionOS)) && !SENTRY_NO_UIKIT + let watchdogLogic = SentryWatchdogTerminationLogic(options: options, + crashAdapter: mockedCrashWrapper, + appStateManager: appStateManager) + return SentryCrashIntegrationSessionHandler( + crashWrapper: mockedCrashWrapper, + watchdogTerminationLogic: watchdogLogic, + fileManager: fileManager + ) +#else + return SentryCrashIntegrationSessionHandler(crashWrapper: mockedCrashWrapper, fileManager: fileManager) +#endif + } + + var crashReporter: Sentry.SentryCrashSwift { + SentryDependencyContainer.sharedInstance().crashReporter + } + + func getCrashInstallationReporter(_ options: Options) -> SentryCrashInstallationReporter { + let inAppLogic = SentryInAppLogic(inAppIncludes: options.inAppIncludes) + + return SentryCrashInstallationReporter( + inAppLogic: inAppLogic, + crashWrapper: mockedCrashWrapper, + dispatchQueue: mockedDispatchQueueWrapper + ) + } +} diff --git a/Tests/SentryTests/Integrations/Session/SentrySessionGeneratorTests.swift b/Tests/SentryTests/Integrations/Session/SentrySessionGeneratorTests.swift index 127a9e45065..e38e0ccecea 100644 --- a/Tests/SentryTests/Integrations/Session/SentrySessionGeneratorTests.swift +++ b/Tests/SentryTests/Integrations/Session/SentrySessionGeneratorTests.swift @@ -17,7 +17,8 @@ class SentrySessionGeneratorTests: NotificationCenterTestCase { private var sentryCrash: TestSentryCrashWrapper! private var autoSessionTrackingIntegration: SentryAutoSessionTrackingIntegration! - private var crashIntegration: SentryCrashIntegration! + private var crashIntegration: SentryCrashIntegration! + private var mockedCrashDependencies: MockCrashDependencies! private var options: Options! private var fileManager: SentryFileManager! @@ -60,12 +61,12 @@ class SentrySessionGeneratorTests: NotificationCenterTestCase { /** * Disabled on purpose. This test just sends sessions to Sentry, but doesn't verify that they arrive there properly. */ - func testSendSessions() { - sendSessions(amount: Sessions(healthy: 10, errored: 10, crashed: 3, oom: 1, abnormal: 1)) + func testSendSessions() throws { + try sendSessions(amount: Sessions(healthy: 10, errored: 10, crashed: 3, oom: 1, abnormal: 1)) } - private func sendSessions(amount: Sessions ) { - startSdk() + private func sendSessions(amount: Sessions ) throws { + try startSdk() goToForeground() // On healthy session will be sent at the end @@ -91,7 +92,7 @@ class SentrySessionGeneratorTests: NotificationCenterTestCase { sentryCrash.internalCrashedLastLaunch = true for _ in Array(1...amount.crashed) { // send crashed session - crashIntegration.install(with: options) + crashIntegration = try XCTUnwrap(SentryCrashIntegration(with: options, dependencies: mockedCrashDependencies)) autoSessionTrackingIntegration.uninstall() autoSessionTrackingIntegration = SentryAutoSessionTrackingIntegration(with: options, dependencies: SentryDependencyContainer.sharedInstance()) goToForeground() @@ -113,7 +114,7 @@ class SentrySessionGeneratorTests: NotificationCenterTestCase { for _ in Array(1...amount.oom) { // send crashed session - crashIntegration.install(with: options) + crashIntegration = try XCTUnwrap(SentryCrashIntegration(with: options, dependencies: mockedCrashDependencies)) autoSessionTrackingIntegration.uninstall() autoSessionTrackingIntegration = SentryAutoSessionTrackingIntegration(with: options, dependencies: SentryDependencyContainer.sharedInstance()) @@ -137,7 +138,7 @@ class SentrySessionGeneratorTests: NotificationCenterTestCase { delayNonBlocking(timeout: 5) } - private func startSdk() { + private func startSdk() throws { SentrySDK.start(options: options) @@ -146,8 +147,8 @@ class SentrySessionGeneratorTests: NotificationCenterTestCase { let hub = SentryHubInternal(client: client, andScope: nil, andCrashWrapper: self.sentryCrash, andDispatchQueue: SentryDispatchQueueWrapper()) SentrySDKInternal.setCurrentHub(hub) - crashIntegration = SentryCrashIntegration(crashAdapter: sentryCrash, andDispatchQueueWrapper: TestSentryDispatchQueueWrapper()) - crashIntegration.install(with: options) + mockedCrashDependencies = MockCrashDependencies(crashWrapper: sentryCrash, dispatchQueueWrapper: TestSentryDispatchQueueWrapper(), fileManager: fileManager) + crashIntegration = try XCTUnwrap(SentryCrashIntegration(with: options, dependencies: mockedCrashDependencies)) // We need to enable auto session tracking in options or SentryAutoSessionTrackingIntegration's init will return nil options.enableAutoSessionTracking = true diff --git a/Tests/SentryTests/SentryTests-Bridging-Header.h b/Tests/SentryTests/SentryTests-Bridging-Header.h index e0f81a3a817..8b4c81014db 100644 --- a/Tests/SentryTests/SentryTests-Bridging-Header.h +++ b/Tests/SentryTests/SentryTests-Bridging-Header.h @@ -70,9 +70,6 @@ #import "SentryCrashDefaultMachineContextWrapper.h" #import "SentryCrashDoctor.h" #import "SentryCrashInstallation+Private.h" -#import "SentryCrashInstallationReporter.h" -#import "SentryCrashIntegration+TestInit.h" -#import "SentryCrashIntegration.h" #import "SentryCrashJSONCodecObjC.h" #import "SentryCrashMachineContext.h" #import "SentryCrashMachineContext_Apple.h" diff --git a/sdk_api.json b/sdk_api.json index eac650ed1df..339037a1076 100644 --- a/sdk_api.json +++ b/sdk_api.json @@ -33762,6 +33762,29 @@ ], "funcSelfKind": "NonMutating" }, + { + "kind": "Function", + "name": "sentry_finishAndSaveTransaction", + "printedName": "sentry_finishAndSaveTransaction()", + "children": [ + { + "kind": "TypeNameAlias", + "name": "Void", + "printedName": "Swift.Void", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ] + } + ], + "declKind": "Func", + "usr": "c:@M@Sentry@F@sentry_finishAndSaveTransaction", + "moduleName": "Sentry", + "funcSelfKind": "NonMutating" + }, { "kind": "TypeAlias", "name": "swift_double2", @@ -39050,6 +39073,26 @@ } ] }, + { + "kind": "Function", + "name": "sentry_finishAndSaveTransaction", + "printedName": "sentry_finishAndSaveTransaction()", + "children": [ + { + "kind": "TypeNominal", + "name": "Void", + "printedName": "()" + } + ], + "declKind": "Func", + "usr": "c:(cm)sentry_finishAndSaveTransaction", + "mangledName": "$s6Sentry31sentry_finishAndSaveTransactionyyF", + "moduleName": "Sentry", + "declAttributes": [ + "CDecl" + ], + "funcSelfKind": "NonMutating" + }, { "kind": "TypeDecl", "name": "SentryLog",