diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 80146e2594e..41a75eb8b64 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,7 +35,7 @@ jobs: Carthage/Sentry.xcframework.zip Carthage/Sentry-Dynamic.xcframework.zip Carthage/SentrySwiftUI.xcframework.zip - Carthage/Sentry-WihoutUIKitOrAppKit.zip + Carthage/Sentry-WithoutUIKitOrAppKit.zip overwrite: true job_release: diff --git a/CHANGELOG.md b/CHANGELOG.md index df073a30b36..0ba0db1e2c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixes - UIKitless configurations now produce a module with a different name (#4140) +- Sentry Replay Serialized Breadcrumbs include level name ([#4141](https://github.com/getsentry/sentry-cocoa/pull/4141)) ## 8.30.0 diff --git a/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme b/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme index 34b3ee04702..b4ea1e92fba 100644 --- a/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme +++ b/Samples/iOS-Swift/iOS-Swift.xcodeproj/xcshareddata/xcschemes/iOS-Swift.xcscheme @@ -50,8 +50,8 @@ + isEnabled = "NO"> + isEnabled = "YES"> diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index ea8cc91daef..f4c39e0fc5d 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -12,7 +12,6 @@ 03BCC38C27E1C01A003232C7 /* SentryTime.mm in Sources */ = {isa = PBXBuildFile; fileRef = 03BCC38B27E1C01A003232C7 /* SentryTime.mm */; }; 03BCC38E27E2A377003232C7 /* SentryProfilingConditionals.h in Headers */ = {isa = PBXBuildFile; fileRef = 03BCC38D27E2A377003232C7 /* SentryProfilingConditionals.h */; settings = {ATTRIBUTES = (Public, ); }; }; 03F84D1E27DD414C008FE43F /* SentryBacktrace.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 03F84D1227DD414C008FE43F /* SentryBacktrace.hpp */; }; - 03F84D1F27DD414C008FE43F /* SentryAsyncSafeLogging.h in Headers */ = {isa = PBXBuildFile; fileRef = 03F84D1327DD414C008FE43F /* SentryAsyncSafeLogging.h */; }; 03F84D2027DD414C008FE43F /* SentryStackBounds.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 03F84D1427DD414C008FE43F /* SentryStackBounds.hpp */; }; 03F84D2127DD414C008FE43F /* SentrySamplingProfiler.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 03F84D1527DD414C008FE43F /* SentrySamplingProfiler.hpp */; }; 03F84D2227DD414C008FE43F /* SentryStackFrame.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 03F84D1627DD414C008FE43F /* SentryStackFrame.hpp */; }; @@ -22,12 +21,10 @@ 03F84D2627DD414C008FE43F /* SentryThreadMetadataCache.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 03F84D1A27DD414C008FE43F /* SentryThreadMetadataCache.hpp */; }; 03F84D2727DD414C008FE43F /* SentryMachLogging.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 03F84D1B27DD414C008FE43F /* SentryMachLogging.hpp */; }; 03F84D2827DD414C008FE43F /* SentryCPU.h in Headers */ = {isa = PBXBuildFile; fileRef = 03F84D1C27DD414C008FE43F /* SentryCPU.h */; }; - 03F84D2A27DD416B008FE43F /* SentryProfilingLogging.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 03F84D2927DD416B008FE43F /* SentryProfilingLogging.hpp */; }; 03F84D3227DD4191008FE43F /* SentryProfiler.mm in Sources */ = {isa = PBXBuildFile; fileRef = 03F84D2B27DD4191008FE43F /* SentryProfiler.mm */; }; 03F84D3327DD4191008FE43F /* SentryMachLogging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 03F84D2C27DD4191008FE43F /* SentryMachLogging.cpp */; }; 03F84D3427DD4191008FE43F /* SentryThreadMetadataCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 03F84D2D27DD4191008FE43F /* SentryThreadMetadataCache.cpp */; }; 03F84D3527DD4191008FE43F /* SentryThreadHandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 03F84D2E27DD4191008FE43F /* SentryThreadHandle.cpp */; }; - 03F84D3627DD4191008FE43F /* SentryProfilingLogging.mm in Sources */ = {isa = PBXBuildFile; fileRef = 03F84D2F27DD4191008FE43F /* SentryProfilingLogging.mm */; }; 03F84D3727DD4191008FE43F /* SentrySamplingProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 03F84D3027DD4191008FE43F /* SentrySamplingProfiler.cpp */; }; 03F84D3827DD4191008FE43F /* SentryBacktrace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 03F84D3127DD4191008FE43F /* SentryBacktrace.cpp */; }; 0A1B497328E597DD00D7BFA3 /* TestLogOutput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A1B497228E597DD00D7BFA3 /* TestLogOutput.swift */; }; @@ -234,7 +231,7 @@ 63FE70FD20DA4C1000CDBAE8 /* SentryCrashCachedData.c in Sources */ = {isa = PBXBuildFile; fileRef = 63FE700420DA4C1000CDBAE8 /* SentryCrashCachedData.c */; }; 63FE710120DA4C1000CDBAE8 /* SentryCrashDate.h in Headers */ = {isa = PBXBuildFile; fileRef = 63FE700720DA4C1000CDBAE8 /* SentryCrashDate.h */; }; 63FE710320DA4C1000CDBAE8 /* SentryCrashMachineContext_Apple.h in Headers */ = {isa = PBXBuildFile; fileRef = 63FE700820DA4C1000CDBAE8 /* SentryCrashMachineContext_Apple.h */; }; - 63FE710520DA4C1000CDBAE8 /* SentryCrashLogger.c in Sources */ = {isa = PBXBuildFile; fileRef = 63FE700920DA4C1000CDBAE8 /* SentryCrashLogger.c */; }; + 63FE710520DA4C1000CDBAE8 /* SentryAsyncSafeLog.c in Sources */ = {isa = PBXBuildFile; fileRef = 63FE700920DA4C1000CDBAE8 /* SentryAsyncSafeLog.c */; }; 63FE710720DA4C1000CDBAE8 /* SentryCrashStackCursor_SelfThread.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FE700A20DA4C1000CDBAE8 /* SentryCrashStackCursor_SelfThread.m */; }; 63FE710920DA4C1000CDBAE8 /* SentryCrashFileUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 63FE700B20DA4C1000CDBAE8 /* SentryCrashFileUtils.h */; }; 63FE710B20DA4C1000CDBAE8 /* SentryCrashMach.c in Sources */ = {isa = PBXBuildFile; fileRef = 63FE700C20DA4C1000CDBAE8 /* SentryCrashMach.c */; }; @@ -261,7 +258,7 @@ 63FE713720DA4C1100CDBAE8 /* SentryCrashCPU_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = 63FE702220DA4C1000CDBAE8 /* SentryCrashCPU_x86_64.c */; }; 63FE713920DA4C1100CDBAE8 /* SentryCrashMach.h in Headers */ = {isa = PBXBuildFile; fileRef = 63FE702320DA4C1000CDBAE8 /* SentryCrashMach.h */; }; 63FE713B20DA4C1100CDBAE8 /* SentryCrashFileUtils.c in Sources */ = {isa = PBXBuildFile; fileRef = 63FE702420DA4C1000CDBAE8 /* SentryCrashFileUtils.c */; }; - 63FE713D20DA4C1100CDBAE8 /* SentryCrashLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 63FE702520DA4C1000CDBAE8 /* SentryCrashLogger.h */; }; + 63FE713D20DA4C1100CDBAE8 /* SentryAsyncSafeLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 63FE702520DA4C1000CDBAE8 /* SentryAsyncSafeLog.h */; }; 63FE713F20DA4C1100CDBAE8 /* SentryCrashStackCursor_SelfThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 63FE702620DA4C1000CDBAE8 /* SentryCrashStackCursor_SelfThread.h */; }; 63FE714120DA4C1100CDBAE8 /* SentryCrashDate.c in Sources */ = {isa = PBXBuildFile; fileRef = 63FE702720DA4C1000CDBAE8 /* SentryCrashDate.c */; }; 63FE714520DA4C1100CDBAE8 /* SentryCrashObjC.c in Sources */ = {isa = PBXBuildFile; fileRef = 63FE702920DA4C1000CDBAE8 /* SentryCrashObjC.c */; }; @@ -285,7 +282,6 @@ 63FE716B20DA4C1100CDBAE8 /* SentryCrashJSONCodecObjC.h in Headers */ = {isa = PBXBuildFile; fileRef = 63FE703C20DA4C1000CDBAE8 /* SentryCrashJSONCodecObjC.h */; }; 63FE716D20DA4C1100CDBAE8 /* SentryCrashSysCtl.h in Headers */ = {isa = PBXBuildFile; fileRef = 63FE703D20DA4C1000CDBAE8 /* SentryCrashSysCtl.h */; }; 63FE716F20DA4C1100CDBAE8 /* SentryCrashCPU_Apple.h in Headers */ = {isa = PBXBuildFile; fileRef = 63FE703E20DA4C1000CDBAE8 /* SentryCrashCPU_Apple.h */; }; - 63FE717120DA4C1100CDBAE8 /* SentryCrashSystemCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 63FE703F20DA4C1000CDBAE8 /* SentryCrashSystemCapabilities.h */; }; 63FE717320DA4C1100CDBAE8 /* SentryCrashC.c in Sources */ = {isa = PBXBuildFile; fileRef = 63FE704020DA4C1000CDBAE8 /* SentryCrashC.c */; }; 63FE717520DA4C1100CDBAE8 /* SentryCrash.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FE704120DA4C1000CDBAE8 /* SentryCrash.m */; }; 63FE717720DA4C1100CDBAE8 /* SentryCrashReportWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = 63FE704220DA4C1000CDBAE8 /* SentryCrashReportWriter.h */; }; @@ -312,7 +308,6 @@ 63FE720920DA66EC00CDBAE8 /* XCTestCase+SentryCrash.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FE71DE20DA66E800CDBAE8 /* XCTestCase+SentryCrash.m */; }; 63FE720C20DA66EC00CDBAE8 /* SentryCrashMonitor_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FE71E120DA66E800CDBAE8 /* SentryCrashMonitor_Tests.m */; }; 63FE720D20DA66EC00CDBAE8 /* SentryCrashNSErrorUtilTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FE71E220DA66E800CDBAE8 /* SentryCrashNSErrorUtilTests.m */; }; - 63FE720F20DA66EC00CDBAE8 /* SentryCrashLogger_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FE71E420DA66E800CDBAE8 /* SentryCrashLogger_Tests.m */; }; 63FE721020DA66EC00CDBAE8 /* SentryCrashCachedData_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FE71E520DA66E800CDBAE8 /* SentryCrashCachedData_Tests.m */; }; 63FE721220DA66EC00CDBAE8 /* SentryCrashMach_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FE71E720DA66E900CDBAE8 /* SentryCrashMach_Tests.m */; }; 63FE721320DA66EC00CDBAE8 /* SentryCrashMonitor_Signal_Tests.m in Sources */ = {isa = PBXBuildFile; fileRef = 63FE71E820DA66E900CDBAE8 /* SentryCrashMonitor_Signal_Tests.m */; }; @@ -695,6 +690,7 @@ 84AC61D729F75A98009EEF61 /* SentryDispatchFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 84AC61D529F75A98009EEF61 /* SentryDispatchFactory.m */; }; 84AC61D929F7643B009EEF61 /* TestDispatchFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AC61D829F7643B009EEF61 /* TestDispatchFactory.swift */; }; 84AC61DB29F7654A009EEF61 /* TestDispatchSourceWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AC61DA29F7654A009EEF61 /* TestDispatchSourceWrapper.swift */; }; + 84AEB46A2C2F97FC007E46E1 /* ArrayAccesses.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84AEB4682C2F9673007E46E1 /* ArrayAccesses.swift */; }; 84AF45A629A7FFA500FBB177 /* SentryProfiledTracerConcurrency.h in Headers */ = {isa = PBXBuildFile; fileRef = 84AF45A429A7FFA500FBB177 /* SentryProfiledTracerConcurrency.h */; }; 84AF45A729A7FFA500FBB177 /* SentryProfiledTracerConcurrency.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84AF45A529A7FFA500FBB177 /* SentryProfiledTracerConcurrency.mm */; }; 84B7FA3529B285FC00AD93B1 /* Sentry.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63AA759B1EB8AEF500D153DE /* Sentry.framework */; }; @@ -879,7 +875,6 @@ D8B0542E2A7D2C720056BAF6 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = D8B0542D2A7D2C720056BAF6 /* PrivacyInfo.xcprivacy */; }; D8B088B629C9E3FF00213258 /* SentryTracerConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = D8B088B429C9E3FF00213258 /* SentryTracerConfiguration.h */; }; D8B088B729C9E3FF00213258 /* SentryTracerConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = D8B088B529C9E3FF00213258 /* SentryTracerConfiguration.m */; }; - D8B425122B9A0FD6000BFDF3 /* StringExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8B425112B9A0FD6000BFDF3 /* StringExtensionTests.swift */; }; D8B665BC2B95F73200BD0E7B /* SentryPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = D8B665BA2B95F54200BD0E7B /* SentryPrivate.h */; }; D8B76B062808066D000A58C4 /* SentryScreenshotIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8B76B042808060E000A58C4 /* SentryScreenshotIntegrationTests.swift */; }; D8B76B0828081461000A58C4 /* TestSentryScreenShot.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8B76B0728081461000A58C4 /* TestSentryScreenShot.swift */; }; @@ -987,7 +982,6 @@ 03BCC38B27E1C01A003232C7 /* SentryTime.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = SentryTime.mm; path = Sources/Sentry/SentryTime.mm; sourceTree = SOURCE_ROOT; }; 03BCC38D27E2A377003232C7 /* SentryProfilingConditionals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryProfilingConditionals.h; path = ../Public/SentryProfilingConditionals.h; sourceTree = ""; }; 03F84D1227DD414C008FE43F /* SentryBacktrace.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryBacktrace.hpp; path = Sources/Sentry/include/SentryBacktrace.hpp; sourceTree = SOURCE_ROOT; }; - 03F84D1327DD414C008FE43F /* SentryAsyncSafeLogging.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryAsyncSafeLogging.h; path = Sources/Sentry/include/SentryAsyncSafeLogging.h; sourceTree = SOURCE_ROOT; }; 03F84D1427DD414C008FE43F /* SentryStackBounds.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryStackBounds.hpp; path = Sources/Sentry/include/SentryStackBounds.hpp; sourceTree = SOURCE_ROOT; }; 03F84D1527DD414C008FE43F /* SentrySamplingProfiler.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentrySamplingProfiler.hpp; path = Sources/Sentry/include/SentrySamplingProfiler.hpp; sourceTree = SOURCE_ROOT; }; 03F84D1627DD414C008FE43F /* SentryStackFrame.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryStackFrame.hpp; path = Sources/Sentry/include/SentryStackFrame.hpp; sourceTree = SOURCE_ROOT; }; @@ -997,12 +991,10 @@ 03F84D1A27DD414C008FE43F /* SentryThreadMetadataCache.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryThreadMetadataCache.hpp; path = Sources/Sentry/include/SentryThreadMetadataCache.hpp; sourceTree = SOURCE_ROOT; }; 03F84D1B27DD414C008FE43F /* SentryMachLogging.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryMachLogging.hpp; path = Sources/Sentry/include/SentryMachLogging.hpp; sourceTree = SOURCE_ROOT; }; 03F84D1C27DD414C008FE43F /* SentryCPU.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryCPU.h; path = Sources/Sentry/include/SentryCPU.h; sourceTree = SOURCE_ROOT; }; - 03F84D2927DD416B008FE43F /* SentryProfilingLogging.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = SentryProfilingLogging.hpp; path = Sources/Sentry/include/SentryProfilingLogging.hpp; sourceTree = SOURCE_ROOT; }; 03F84D2B27DD4191008FE43F /* SentryProfiler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = SentryProfiler.mm; path = Sources/Sentry/SentryProfiler.mm; sourceTree = SOURCE_ROOT; }; 03F84D2C27DD4191008FE43F /* SentryMachLogging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SentryMachLogging.cpp; path = Sources/Sentry/SentryMachLogging.cpp; sourceTree = SOURCE_ROOT; }; 03F84D2D27DD4191008FE43F /* SentryThreadMetadataCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SentryThreadMetadataCache.cpp; path = Sources/Sentry/SentryThreadMetadataCache.cpp; sourceTree = SOURCE_ROOT; }; 03F84D2E27DD4191008FE43F /* SentryThreadHandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SentryThreadHandle.cpp; path = Sources/Sentry/SentryThreadHandle.cpp; sourceTree = SOURCE_ROOT; }; - 03F84D2F27DD4191008FE43F /* SentryProfilingLogging.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = SentryProfilingLogging.mm; path = Sources/Sentry/SentryProfilingLogging.mm; sourceTree = SOURCE_ROOT; }; 03F84D3027DD4191008FE43F /* SentrySamplingProfiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SentrySamplingProfiler.cpp; path = Sources/Sentry/SentrySamplingProfiler.cpp; sourceTree = SOURCE_ROOT; }; 03F84D3127DD4191008FE43F /* SentryBacktrace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SentryBacktrace.cpp; path = Sources/Sentry/SentryBacktrace.cpp; sourceTree = SOURCE_ROOT; }; 03F9D37B2819A65C00602916 /* SentryProfilerTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryProfilerTests.mm; sourceTree = ""; }; @@ -1223,7 +1215,7 @@ 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 = ""; }; - 63FE700920DA4C1000CDBAE8 /* SentryCrashLogger.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashLogger.c; 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 = ""; }; 63FE700C20DA4C1000CDBAE8 /* SentryCrashMach.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashMach.c; sourceTree = ""; }; @@ -1250,7 +1242,7 @@ 63FE702220DA4C1000CDBAE8 /* SentryCrashCPU_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashCPU_x86_64.c; sourceTree = ""; }; 63FE702320DA4C1000CDBAE8 /* SentryCrashMach.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashMach.h; sourceTree = ""; }; 63FE702420DA4C1000CDBAE8 /* SentryCrashFileUtils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashFileUtils.c; sourceTree = ""; }; - 63FE702520DA4C1000CDBAE8 /* SentryCrashLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashLogger.h; sourceTree = ""; }; + 63FE702520DA4C1000CDBAE8 /* SentryAsyncSafeLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryAsyncSafeLog.h; sourceTree = ""; }; 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 = ""; }; @@ -1274,7 +1266,6 @@ 63FE703C20DA4C1000CDBAE8 /* SentryCrashJSONCodecObjC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashJSONCodecObjC.h; sourceTree = ""; }; 63FE703D20DA4C1000CDBAE8 /* SentryCrashSysCtl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashSysCtl.h; sourceTree = ""; }; 63FE703E20DA4C1000CDBAE8 /* SentryCrashCPU_Apple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashCPU_Apple.h; sourceTree = ""; }; - 63FE703F20DA4C1000CDBAE8 /* SentryCrashSystemCapabilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashSystemCapabilities.h; sourceTree = ""; }; 63FE704020DA4C1000CDBAE8 /* SentryCrashC.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryCrashC.c; sourceTree = ""; }; 63FE704120DA4C1000CDBAE8 /* SentryCrash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrash.m; sourceTree = ""; }; 63FE704220DA4C1000CDBAE8 /* SentryCrashReportWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryCrashReportWriter.h; sourceTree = ""; }; @@ -1302,7 +1293,6 @@ 63FE71DE20DA66E800CDBAE8 /* XCTestCase+SentryCrash.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCTestCase+SentryCrash.m"; sourceTree = ""; }; 63FE71E120DA66E800CDBAE8 /* SentryCrashMonitor_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashMonitor_Tests.m; sourceTree = ""; }; 63FE71E220DA66E800CDBAE8 /* SentryCrashNSErrorUtilTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashNSErrorUtilTests.m; sourceTree = ""; }; - 63FE71E420DA66E800CDBAE8 /* SentryCrashLogger_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashLogger_Tests.m; sourceTree = ""; }; 63FE71E520DA66E800CDBAE8 /* SentryCrashCachedData_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashCachedData_Tests.m; sourceTree = ""; }; 63FE71E720DA66E900CDBAE8 /* SentryCrashMach_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashMach_Tests.m; sourceTree = ""; }; 63FE71E820DA66E900CDBAE8 /* SentryCrashMonitor_Signal_Tests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryCrashMonitor_Signal_Tests.m; sourceTree = ""; }; @@ -1751,6 +1741,7 @@ 84AC61D529F75A98009EEF61 /* SentryDispatchFactory.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDispatchFactory.m; sourceTree = ""; }; 84AC61D829F7643B009EEF61 /* TestDispatchFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestDispatchFactory.swift; sourceTree = ""; }; 84AC61DA29F7654A009EEF61 /* TestDispatchSourceWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestDispatchSourceWrapper.swift; sourceTree = ""; }; + 84AEB4682C2F9673007E46E1 /* ArrayAccesses.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrayAccesses.swift; sourceTree = ""; }; 84AF45A429A7FFA500FBB177 /* SentryProfiledTracerConcurrency.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryProfiledTracerConcurrency.h; path = ../include/SentryProfiledTracerConcurrency.h; sourceTree = ""; }; 84AF45A529A7FFA500FBB177 /* SentryProfiledTracerConcurrency.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryProfiledTracerConcurrency.mm; sourceTree = ""; }; 84B7FA3B29B2866200AD93B1 /* SentryTestUtils-ObjC-BridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryTestUtils-ObjC-BridgingHeader.h"; sourceTree = ""; }; @@ -1943,7 +1934,6 @@ D8B0542D2A7D2C720056BAF6 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; D8B088B429C9E3FF00213258 /* SentryTracerConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryTracerConfiguration.h; path = include/SentryTracerConfiguration.h; sourceTree = ""; }; D8B088B529C9E3FF00213258 /* SentryTracerConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryTracerConfiguration.m; sourceTree = ""; }; - D8B425112B9A0FD6000BFDF3 /* StringExtensionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExtensionTests.swift; sourceTree = ""; }; D8B665BA2B95F54200BD0E7B /* SentryPrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryPrivate.h; path = include/SentryPrivate.h; sourceTree = ""; }; D8B665BB2B95F5A100BD0E7B /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = module.modulemap; path = Sources/Sentry/include/module.modulemap; sourceTree = SOURCE_ROOT; }; D8B76B042808060E000A58C4 /* SentryScreenshotIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryScreenshotIntegrationTests.swift; sourceTree = ""; }; @@ -2413,6 +2403,8 @@ 7BC3936D25B1AB72004F03D3 /* SentryLevelMapper.m */, 63AA76961EB9C1C200D153DE /* SentryLog.h */, 63AA76781EB8D20500D153DE /* SentryLog.m */, + 63FE700920DA4C1000CDBAE8 /* SentryAsyncSafeLog.c */, + 63FE702520DA4C1000CDBAE8 /* SentryAsyncSafeLog.h */, 7BE1E33124F7E3B6009D3AD0 /* SentryMigrateSessionInit.h */, 7BE1E33324F7E3CB009D3AD0 /* SentryMigrateSessionInit.m */, 15E0A8E9240F2C8F00F044E3 /* SentrySerialization.h */, @@ -2660,7 +2652,6 @@ 63FE704D20DA4C1000CDBAE8 /* SentryCrashReportStore.c */, 63FE704A20DA4C1000CDBAE8 /* SentryCrashReportVersion.h */, 63FE704220DA4C1000CDBAE8 /* SentryCrashReportWriter.h */, - 63FE703F20DA4C1000CDBAE8 /* SentryCrashSystemCapabilities.h */, 63FE6FEC20DA4C1000CDBAE8 /* Monitors */, 63FE700520DA4C1000CDBAE8 /* Tools */, ); @@ -2717,8 +2708,6 @@ 63FE702D20DA4C1000CDBAE8 /* SentryCrashJSONCodec.h */, 63FE703C20DA4C1000CDBAE8 /* SentryCrashJSONCodecObjC.h */, 63FE701D20DA4C1000CDBAE8 /* SentryCrashJSONCodecObjC.m */, - 63FE700920DA4C1000CDBAE8 /* SentryCrashLogger.c */, - 63FE702520DA4C1000CDBAE8 /* SentryCrashLogger.h */, 63FE700C20DA4C1000CDBAE8 /* SentryCrashMach.c */, 63FE702320DA4C1000CDBAE8 /* SentryCrashMach.h */, 63FE700820DA4C1000CDBAE8 /* SentryCrashMachineContext_Apple.h */, @@ -2781,7 +2770,6 @@ 63FE71F820DA66EB00CDBAE8 /* SentryCrashDynamicLinker_Tests.m */, 63FE71FC20DA66EB00CDBAE8 /* SentryCrashFileUtils_Tests.m */, 63FE71F920DA66EB00CDBAE8 /* SentryCrashJSONCodec_Tests.m */, - 63FE71E420DA66E800CDBAE8 /* SentryCrashLogger_Tests.m */, 63FE71E720DA66E900CDBAE8 /* SentryCrashMach_Tests.m */, 63FE71E920DA66E900CDBAE8 /* SentryCrashMemory_Tests.m */, 63FE71DA20DA66E700CDBAE8 /* SentryCrashMonitor_AppState_Tests.m */, @@ -3369,7 +3357,6 @@ 8405A517279906EF001B38A1 /* Profiling */ = { isa = PBXGroup; children = ( - 03F84D1327DD414C008FE43F /* SentryAsyncSafeLogging.h */, 03F84D3127DD4191008FE43F /* SentryBacktrace.cpp */, 03F84D1227DD414C008FE43F /* SentryBacktrace.hpp */, 03F84D1827DD414C008FE43F /* SentryCompiler.h */, @@ -3398,8 +3385,6 @@ 84354E0F29BF944900CDBB8B /* SentryProfileTimeseries.h */, 84354E1029BF944900CDBB8B /* SentryProfileTimeseries.mm */, 03BCC38D27E2A377003232C7 /* SentryProfilingConditionals.h */, - 03F84D2927DD416B008FE43F /* SentryProfilingLogging.hpp */, - 03F84D2F27DD4191008FE43F /* SentryProfilingLogging.mm */, 84281C442A57905700EE88F2 /* SentrySample.h */, 84281C452A57905700EE88F2 /* SentrySample.m */, 03F84D3027DD4191008FE43F /* SentrySamplingProfiler.cpp */, @@ -3452,6 +3437,7 @@ 8431F00B29B284F200D8DC56 /* SentryTestUtils */ = { isa = PBXGroup; children = ( + 84AEB4682C2F9673007E46E1 /* ArrayAccesses.swift */, 841325DE2BFED0510029228F /* TestFramesTracker.swift */, 841325C42BF49EC40029228F /* SentryLaunchProfiling+Tests.h */, 7B4C817124D1BC2B0076ACE4 /* SentryFileManager+Test.h */, @@ -3663,7 +3649,6 @@ D84541192A2DC55100E2B11C /* SentryBinaryImageCache+Private.h */, D8292D7C2A39A027009872F7 /* UrlSanitizedTests.swift */, D8F8F5562B835BC600AC5465 /* SentryMsgPackSerializerTests.m */, - D8B425112B9A0FD6000BFDF3 /* StringExtensionTests.swift */, D8AFC0582BDA899A00118BE1 /* RedactRegionTests.swift */, D8F67AEF2BE0D31A00C9197B /* UIImageHelperTests.swift */, D8F67AF22BE10F7600C9197B /* UIRedactBuilderTests.swift */, @@ -3975,7 +3960,6 @@ 63FE718920DA4C1100CDBAE8 /* SentryCrash.h in Headers */, 63AA769A1EB9C1C200D153DE /* SentryLog.h in Headers */, 7B56D73124616CCD00B842DA /* SentryConcurrentRateLimitsDictionary.h in Headers */, - 03F84D2A27DD416B008FE43F /* SentryProfilingLogging.hpp in Headers */, 63FE714D20DA4C1100CDBAE8 /* SentryCrashJSONCodec.h in Headers */, 7BAF3DD4243DD40F008A5414 /* SentryTransportFactory.h in Headers */, 63FE717F20DA4C1100CDBAE8 /* SentryCrashReportFields.h in Headers */, @@ -4077,7 +4061,6 @@ 7D0FCFB22379B915004DD83A /* SentryHub.h in Headers */, 7B7A30C624B48321005A4C6E /* SentryCrashWrapper.h in Headers */, 92F6726B29C8B7B100BFD34D /* SentryUser+Private.h in Headers */, - 63FE717120DA4C1100CDBAE8 /* SentryCrashSystemCapabilities.h in Headers */, 7BE1E33224F7E3B6009D3AD0 /* SentryMigrateSessionInit.h in Headers */, 632F43501F581D5400A18A36 /* SentryCrashExceptionApplication.h in Headers */, 7B85DC1E24EFAFCD007D01D2 /* SentryClient+Private.h in Headers */, @@ -4114,7 +4097,6 @@ D8BD2E6829361A0F00D96C6A /* PrivatesHeader.h in Headers */, 7B98D7CB25FB64EC00C5A389 /* SentryWatchdogTerminationTrackingIntegration.h in Headers */, 63FE710920DA4C1000CDBAE8 /* SentryCrashFileUtils.h in Headers */, - 03F84D1F27DD414C008FE43F /* SentryAsyncSafeLogging.h in Headers */, D865892F29D6ECA7000BE151 /* SentryCrashBinaryImageCache.h in Headers */, 6344DDB41EC309E000D9160D /* SentryCrashReportSink.h in Headers */, 7D427C62237B1D200046BAC8 /* SentrySDK.h in Headers */, @@ -4173,7 +4155,7 @@ 7B5CAF7527F5A67C00ED0DB6 /* SentryNSURLRequestBuilder.h in Headers */, 63FE70ED20DA4C1000CDBAE8 /* SentryCrashMonitor_NSException.h in Headers */, 7BA61CB4247BC3EB00C130A8 /* SentryCrashBinaryImageProvider.h in Headers */, - 63FE713D20DA4C1100CDBAE8 /* SentryCrashLogger.h in Headers */, + 63FE713D20DA4C1100CDBAE8 /* SentryAsyncSafeLog.h in Headers */, 15E0A8E1240C41CE00F044E3 /* SentryEnvelope.h in Headers */, 630435FE1EBCA9D900C4D3FA /* SentryNSURLRequest.h in Headers */, 7BC852392458830A005A70F0 /* SentryEnvelopeItemType.h in Headers */, @@ -4602,7 +4584,6 @@ D8AFC01A2BD7A20B00118BE1 /* SentryViewScreenshotProvider.swift in Sources */, D81988C32BEC189C0020E36C /* SentryRRWebMetaEvent.swift in Sources */, 15E0A8E5240C457D00F044E3 /* SentryEnvelope.m in Sources */, - 03F84D3627DD4191008FE43F /* SentryProfilingLogging.mm in Sources */, 8EC3AE7A25CA23B600E7591A /* SentrySpan.m in Sources */, 6360850E1ED2AFE100E8599E /* SentryBreadcrumb.m in Sources */, 84A8891D28DBD28900C51DFD /* SentryDevice.mm in Sources */, @@ -4747,7 +4728,7 @@ 63FE71A020DA4C1100CDBAE8 /* SentryCrashInstallation.m in Sources */, 63FE713520DA4C1100CDBAE8 /* SentryCrashMemory.c in Sources */, 63FE714520DA4C1100CDBAE8 /* SentryCrashObjC.c in Sources */, - 63FE710520DA4C1000CDBAE8 /* SentryCrashLogger.c in Sources */, + 63FE710520DA4C1000CDBAE8 /* SentryAsyncSafeLog.c in Sources */, 0A2D8D5B289815C0008720F6 /* SentryBaseIntegration.m in Sources */, 62262B912BA1C520004DA3DD /* CounterMetric.swift in Sources */, 639FCF991EBC7B9700778193 /* SentryEvent.m in Sources */, @@ -4974,7 +4955,6 @@ 8F73BC312B02B87E00C3CEF4 /* SentryInstallationTests.swift in Sources */, 7B569E002590EEF600B653FC /* SentryScope+Equality.m in Sources */, D8BFE37929A76666002E73F3 /* SentryTimeToDisplayTrackerTest.swift in Sources */, - D8B425122B9A0FD6000BFDF3 /* StringExtensionTests.swift in Sources */, D84541182A2DC2CD00E2B11C /* SentryBinaryImageCacheTests.swift in Sources */, 7BF536D424BEF255004FA6A2 /* SentryAssertions.swift in Sources */, 7BC6EC14255C415E0059822A /* SentryExceptionTests.swift in Sources */, @@ -5019,7 +4999,6 @@ 7BBD18B62451807600427C76 /* SentryDefaultRateLimitsTests.swift in Sources */, 63FE720620DA66EC00CDBAE8 /* SentryCrashMonitor_AppState_Tests.m in Sources */, 7B4E375B2582313100059C93 /* SentryAttachmentTests.swift in Sources */, - 63FE720F20DA66EC00CDBAE8 /* SentryCrashLogger_Tests.m in Sources */, 63FE721320DA66EC00CDBAE8 /* SentryCrashMonitor_Signal_Tests.m in Sources */, 7BBD18B32451805500427C76 /* SentryRateLimitsParserTests.swift in Sources */, 7B82722B27A3220A00F4BFF4 /* SentryFileIoTrackingUnitTests.swift in Sources */, @@ -5064,6 +5043,7 @@ 84B7FA4229B28CDE00AD93B1 /* TestCurrentDateProvider.swift in Sources */, 62C25C862B075F4900C68CBD /* TestOptions.swift in Sources */, 62FC69362BEDFF18002D3EF2 /* SentryLogExtensions.swift in Sources */, + 84AEB46A2C2F97FC007E46E1 /* ArrayAccesses.swift in Sources */, 84B7FA3F29B28BAD00AD93B1 /* TestTransport.swift in Sources */, 84A5D75B29D5170700388BFA /* TimeInterval+Sentry.swift in Sources */, 62AB8C9E2BF3925700BFC2AC /* WeakReference.swift in Sources */, diff --git a/Sentry.xcodeproj/xcshareddata/xcschemes/Sentry.xcscheme b/Sentry.xcodeproj/xcshareddata/xcschemes/Sentry.xcscheme index dd5d3586eff..efc3f0e8db1 100644 --- a/Sentry.xcodeproj/xcshareddata/xcschemes/Sentry.xcscheme +++ b/Sentry.xcodeproj/xcshareddata/xcschemes/Sentry.xcscheme @@ -103,6 +103,9 @@ + + diff --git a/SentryTestUtils/ArrayAccesses.swift b/SentryTestUtils/ArrayAccesses.swift new file mode 100644 index 00000000000..3b1391b19f6 --- /dev/null +++ b/SentryTestUtils/ArrayAccesses.swift @@ -0,0 +1,10 @@ +import Foundation + +public extension Array { + func element(at index: Int) -> Self.Element? { + guard count >= index else { + return nil + } + return self[index] + } +} diff --git a/Sources/Sentry/Public/SentryOptions.h b/Sources/Sentry/Public/SentryOptions.h index 0f91822dbfd..525448d9e9f 100644 --- a/Sources/Sentry/Public/SentryOptions.h +++ b/Sources/Sentry/Public/SentryOptions.h @@ -71,6 +71,7 @@ NS_SWIFT_NAME(Options) * @c SentryWatchdogTerminationTrackingIntegration would falsely report every crash as watchdog * termination. * @note Default value is @c YES . + * @note Crash reporting is automatically disabled if a debugger is attached. */ @property (nonatomic, assign) BOOL enableCrashHandler; @@ -143,6 +144,7 @@ NS_SWIFT_NAME(Options) * terminates with a crash before the SDK can send the crash event. You can look into @c beforeSend * if you prefer a callback for every event. * @warning It is not guaranteed that this is called on the main thread. + * @note Crash reporting is automatically disabled if a debugger is attached. */ @property (nullable, nonatomic, copy) SentryOnCrashedLastRunCallback onCrashedLastRun; @@ -451,6 +453,7 @@ NS_SWIFT_NAME(Options) * to profile that launch. * @see @c tracesSampler and @c profilesSampler for more information on how they work for this * feature. + * @note Profiling is automatically disabled if a thread sanitizer is attached. */ @property (nonatomic, assign) BOOL enableAppLaunchProfiling; @@ -473,6 +476,7 @@ NS_SWIFT_NAME(Options) * callsites where you use the API or configure launch profiling. Continuous profiling is not * automatically started for performance transactions as was the previous version of profiling. * @warning The new continuous profiling mode is experimental and may still contain bugs. + * @note Profiling is automatically disabled if a thread sanitizer is attached. */ @property (nullable, nonatomic, strong) NSNumber *profilesSampleRate; @@ -484,6 +488,7 @@ NS_SWIFT_NAME(Options) * @note If @c enableAppLaunchProfiling is @c YES , this function will be called during SDK start * with @c SentrySamplingContext.forNextAppLaunch set to @c YES, and the result will be persisted to * disk for use on the next app launch. + * @note Profiling is automatically disabled if a thread sanitizer is attached. */ @property (nullable, nonatomic) SentryTracesSamplerCallback profilesSampler; @@ -495,6 +500,7 @@ NS_SWIFT_NAME(Options) * successfully start a continuous profile. * @returns @c YES if either @c profilesSampleRate > @c 0 and \<= @c 1 , or @c profilesSampler is * set, otherwise @c NO. + * @note Profiling is automatically disabled if a thread sanitizer is attached. */ @property (nonatomic, assign, readonly) BOOL isProfilingEnabled; @@ -505,6 +511,7 @@ NS_SWIFT_NAME(Options) * equivalent of setting @c profilesSampleRate to @c 1.0 If @c profilesSampleRate is set, it will * take precedence over this setting. * @note Default is @c NO. + * @note Profiling is automatically disabled if a thread sanitizer is attached. */ @property (nonatomic, assign) BOOL enableProfiling DEPRECATED_MSG_ATTRIBUTE( "Use profilesSampleRate or profilesSampler instead. This property will be removed in a future " @@ -522,6 +529,7 @@ NS_SWIFT_NAME(Options) * When enabled, the SDK tracks when the application stops responding for a specific amount of * time defined by the @c appHangsTimeoutInterval option. * @note The default is @c YES + * @note ANR tracking is automatically disabled if a debugger is attached. */ @property (nonatomic, assign) BOOL enableAppHangTracking; diff --git a/Sources/Sentry/SentryAsyncSafeLog.c b/Sources/Sentry/SentryAsyncSafeLog.c new file mode 100644 index 00000000000..9a2dbb1a212 --- /dev/null +++ b/Sources/Sentry/SentryAsyncSafeLog.c @@ -0,0 +1,162 @@ +// Adapted from: https://github.com/kstenerud/KSCrash +// +// SentryAsyncSafeLog.c +// +// Created by Karl Stenerud on 11-06-25. +// +// Copyright (c) 2011 Karl Stenerud. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall remain in place +// in this source code. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#include "SentryAsyncSafeLog.h" +#include "SentryCrashDebug.h" +#include "SentryInternalCDefines.h" + +#include +#include +#include +#include +#include +#include + +// Compiler hints for "if" statements +#define likely_if(x) if (__builtin_expect(x, 1)) +#define unlikely_if(x) if (__builtin_expect(x, 0)) + +/** Write a formatted string to the log. + * + * @param fmt The format string, followed by its arguments. + */ +static void writeFmtToLog(const char *fmt, ...); + +/** Write a formatted string to the log using a vararg list. + * + * @param fmt The format string. + * + * @param args The variable arguments. + */ +static void writeFmtArgsToLog(const char *fmt, va_list args); + +static inline const char * +lastPathEntry(const char *const path) +{ + const char *lastFile = strrchr(path, '/'); + return lastFile == 0 ? path : lastFile + 1; +} + +static inline void +writeFmtToLog(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + writeFmtArgsToLog(fmt, args); + va_end(args); +} + +/** The file descriptor where log entries get written. */ +static int g_fd = -1; + +#if SENTRY_ASYNC_SAFE_LOG_ALSO_WRITE_TO_CONSOLE +static bool g_isDebugging; +static bool g_checkedIsDebugging; +#endif // SENTRY_ASYNC_SAFE_LOG_ALSO_WRITE_TO_CONSOLE + +static void +writeToLog(const char *const str) +{ + if (g_fd >= 0) { + int bytesToWrite = (int)strlen(str); + const char *pos = str; + while (bytesToWrite > 0) { + int bytesWritten = (int)write(g_fd, pos, (unsigned)bytesToWrite); + unlikely_if(bytesWritten == -1) { break; } + bytesToWrite -= bytesWritten; + pos += bytesWritten; + } + } + write(STDOUT_FILENO, str, strlen(str)); + +#if SENTRY_ASYNC_SAFE_LOG_ALSO_WRITE_TO_CONSOLE + // if we're debugging, also write the log statements to the console; we only check once for + // performance reasons; if the debugger is attached or detached while running, it will not + // change console-based logging + if (!g_checkedIsDebugging) { + g_checkedIsDebugging = true; + g_isDebugging = sentrycrashdebug_isBeingTraced(); + } + if (g_isDebugging) { + fprintf(stdout, "%s", str); + fflush(stdout); + } +#endif // SENTRY_ASYNC_SAFE_LOG_ALSO_WRITE_TO_CONSOLE +} + +static inline void +writeFmtArgsToLog(const char *fmt, va_list args) +{ + unlikely_if(fmt == NULL) { writeToLog("(null)"); } + else + { + char buffer[SENTRY_ASYNC_SAFE_LOG_C_BUFFER_SIZE]; + vsnprintf(buffer, sizeof(buffer), fmt, args); + writeToLog(buffer); + } +} + +static inline void +setLogFD(int fd) +{ + if (g_fd >= 0 && g_fd != STDOUT_FILENO && g_fd != STDERR_FILENO && g_fd != STDIN_FILENO) { + close(g_fd); + } + g_fd = fd; +} + +int +sentry_asyncLogSetFileName(const char *filename, bool overwrite) +{ + static int fd = -1; + if (filename != NULL) { + int openMask = O_WRONLY | O_CREAT; + if (overwrite) { + openMask |= O_TRUNC; + } + fd = open(filename, openMask, 0644); + unlikely_if(fd < 0) { return 1; } + if (filename != g_logFilename) { + strncpy(g_logFilename, filename, sizeof(g_logFilename)); + } + } + + setLogFD(fd); + return 0; +} + +void +sentry_asyncLogC(const char *const level, const char *const file, const int line, + const char *const function, const char *const fmt, ...) +{ + writeFmtToLog("%s: %s (%u): %s: ", level, lastPathEntry(file), line, function); + va_list args; + va_start(args, fmt); + writeFmtArgsToLog(fmt, args); + va_end(args); + writeToLog("\n"); +} diff --git a/Sources/Sentry/SentryAsyncSafeLog.h b/Sources/Sentry/SentryAsyncSafeLog.h new file mode 100644 index 00000000000..b86167ae6bf --- /dev/null +++ b/Sources/Sentry/SentryAsyncSafeLog.h @@ -0,0 +1,173 @@ +// Adapted from: https://github.com/kstenerud/KSCrash +// +// SentryAsyncSafeLog.h +// +// Created by Karl Stenerud on 11-06-25. +// +// Copyright (c) 2011 Karl Stenerud. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall remain in place +// in this source code. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#ifndef HDR_SENTRY_ASYNC_SAFE_LOG_H +#define HDR_SENTRY_ASYNC_SAFE_LOG_H + +#define SENTRY_ASYNC_SAFE_LOG_C_BUFFER_SIZE 1024 + +/** + * In addition to writing to file, we can also write to the console. This is not safe to do from + * actual async contexts, but can be helpful while running with the debugger attached in certain + * cases. The logger will never write to the console if there is no debugger attached. + * @warning Never commit a change of this definition to 1, or we compromise async-safety in + * production crash reporting. + */ +#define SENTRY_ASYNC_SAFE_LOG_ALSO_WRITE_TO_CONSOLE 0 + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +static char g_logFilename[1024]; + +void sentry_asyncLogC( + const char *level, const char *file, int line, const char *function, const char *fmt, ...); + +#define i_SENTRY_ASYNC_SAFE_LOG sentry_asyncLogC + +#define SENTRY_ASYNC_SAFE_LOG_LEVEL_NONE 0 +#define SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR 10 +#define SENTRY_ASYNC_SAFE_LOG_LEVEL_WARN 20 +#define SENTRY_ASYNC_SAFE_LOG_LEVEL_INFO 30 +#define SENTRY_ASYNC_SAFE_LOG_LEVEL_DEBUG 40 +#define SENTRY_ASYNC_SAFE_LOG_LEVEL_TRACE 50 + +#define SENTRY_ASYNC_SAFE_LOG_LEVEL SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR + +#define a_SENTRY_ASYNC_SAFE_LOG(LEVEL, FMT, ...) \ + i_SENTRY_ASYNC_SAFE_LOG(LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FMT, ##__VA_ARGS__) + +// ============================================================================ +#pragma mark - API - +// ============================================================================ + +/** Set the filename to log to. + * + * @param filename The file to write to (NULL = write to stdout). + * @param overwrite If true, overwrite the log file. + * @return 0 if successful, 1 otherwise. + */ +int sentry_asyncLogSetFileName(const char *filename, bool overwrite); + +/** Tests if the logger would print at the specified level. + * + * @param LEVEL The level to test for. One of: + * SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR, + * SENTRY_ASYNC_SAFE_LOG_LEVEL_WARN, + * SENTRY_ASYNC_SAFE_LOG_LEVEL_INFO, + * SENTRY_ASYNC_SAFE_LOG_LEVEL_DEBUG, + * SENTRY_ASYNC_SAFE_LOG_LEVEL_TRACE, + * + * @return TRUE if the logger would print at the specified level. + */ +#define SENTRY_ASYNC_SAFE_LOG_PRINTS_AT_LEVEL(LEVEL) (SENTRY_ASYNC_SAFE_LOG_LEVEL >= LEVEL) + +/** Log an error. + * Normal version prints out full context. + * + * @param FMT The format specifier, followed by its arguments. + */ +#if SENTRY_ASYNC_SAFE_LOG_PRINTS_AT_LEVEL(SENTRY_ASYNC_SAFE_LOG_LEVEL_ERROR) +# define SENTRY_ASYNC_SAFE_LOG_ERROR(FMT, ...) \ + a_SENTRY_ASYNC_SAFE_LOG("ERROR", FMT, ##__VA_ARGS__) +#else +# define SENTRY_ASYNC_SAFE_LOG_ERROR(FMT, ...) +#endif + +/** Log a warning. + * Normal version prints out full context. + * + * @param FMT The format specifier, followed by its arguments. + */ +#if SENTRY_ASYNC_SAFE_LOG_PRINTS_AT_LEVEL(SENTRY_ASYNC_SAFE_LOG_LEVEL_WARN) +# define SENTRY_ASYNC_SAFE_LOG_WARN(FMT, ...) \ + a_SENTRY_ASYNC_SAFE_LOG("WARN ", FMT, ##__VA_ARGS__) +#else +# define SENTRY_ASYNC_SAFE_LOG_WARN(FMT, ...) +#endif + +/** Log an info message. + * Normal version prints out full context. + * + * @param FMT The format specifier, followed by its arguments. + */ +#if SENTRY_ASYNC_SAFE_LOG_PRINTS_AT_LEVEL(SENTRY_ASYNC_SAFE_LOG_LEVEL_INFO) +# define SENTRY_ASYNC_SAFE_LOG_INFO(FMT, ...) \ + a_SENTRY_ASYNC_SAFE_LOG("INFO ", FMT, ##__VA_ARGS__) +#else +# define SENTRY_ASYNC_SAFE_LOG_INFO(FMT, ...) +#endif + +/** Log a debug message. + * Normal version prints out full context. + * + * @param FMT The format specifier, followed by its arguments. + */ +#if SENTRY_ASYNC_SAFE_LOG_PRINTS_AT_LEVEL(SENTRY_ASYNC_SAFE_LOG_LEVEL_DEBUG) +# define SENTRY_ASYNC_SAFE_LOG_DEBUG(FMT, ...) \ + a_SENTRY_ASYNC_SAFE_LOG("DEBUG", FMT, ##__VA_ARGS__) +#else +# define SENTRY_ASYNC_SAFE_LOG_DEBUG(FMT, ...) +#endif + +/** Log a trace message. + * Normal version prints out full context. + * + * @param FMT The format specifier, followed by its arguments. + */ +#if SENTRY_ASYNC_SAFE_LOG_PRINTS_AT_LEVEL(SENTRY_ASYNC_SAFE_LOG_LEVEL_TRACE) +# define SENTRY_ASYNC_SAFE_LOG_TRACE(FMT, ...) \ + a_SENTRY_ASYNC_SAFE_LOG("TRACE", FMT, ##__VA_ARGS__) +#else +# define SENTRY_ASYNC_SAFE_LOG_TRACE(FMT, ...) +#endif + +/** + * If @c errno is set to a non-zero value after @c statement finishes executing, + * the error value is logged, and the original return value of @c statement is + * returned. + */ +#define SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(statement) \ + ({ \ + errno = 0; \ + const auto __log_rv = (statement); \ + const int __log_errnum = errno; \ + if (__log_errnum != 0) { \ + SENTRY_ASYNC_SAFE_LOG_ERROR("%s failed with code: %d, description: %s", #statement, \ + __log_errnum, strerror(__log_errnum)); \ + } \ + __log_rv; \ + }) + +#ifdef __cplusplus +} +#endif + +#endif // HDR_SENTRY_ASYNC_SAFE_LOG_H diff --git a/Sources/Sentry/SentryBacktrace.cpp b/Sources/Sentry/SentryBacktrace.cpp index 8f12fd37649..c5d5a7a324c 100644 --- a/Sources/Sentry/SentryBacktrace.cpp +++ b/Sources/Sentry/SentryBacktrace.cpp @@ -2,7 +2,7 @@ #if SENTRY_TARGET_PROFILING_SUPPORTED -# include "SentryAsyncSafeLogging.h" +# include "SentryAsyncSafeLog.h" # include "SentryCompiler.h" # include "SentryMachLogging.hpp" # include "SentryStackBounds.hpp" @@ -44,7 +44,7 @@ namespace profiling { std::size_t depth = 0; MachineContext machineContext; if (fillThreadState(targetThread.nativeHandle(), &machineContext) != KERN_SUCCESS) { - SENTRY_LOG_ASYNC_SAFE_ERROR("Failed to fill thread state"); + SENTRY_ASYNC_SAFE_LOG_ERROR("Failed to fill thread state"); return 0; } if (LIKELY(skip == 0)) { diff --git a/Sources/Sentry/SentryFileManager.m b/Sources/Sentry/SentryFileManager.m index f044b1c4dc6..ad9497d2c91 100644 --- a/Sources/Sentry/SentryFileManager.m +++ b/Sources/Sentry/SentryFileManager.m @@ -728,7 +728,6 @@ - (void)createPathsWithOptions:(SentryOptions *)options self.envelopesPath = [self.sentryPath stringByAppendingPathComponent:EnvelopesPathComponent]; } -#if SENTRY_TARGET_PROFILING_SUPPORTED /** * @note This method must be statically accessible because it will be called during app launch, * before any instance of @c SentryFileManager exists, and so wouldn't be able to access this path @@ -752,6 +751,8 @@ - (void)createPathsWithOptions:(SentryOptions *)options return sentryApplicationSupportPath; } +#if SENTRY_TARGET_PROFILING_SUPPORTED + NSURL *_Nullable sentryLaunchConfigFileURL = nil; NSURL *_Nullable launchProfileConfigFileURL(void) diff --git a/Sources/Sentry/SentryLevelHelper.m b/Sources/Sentry/SentryLevelHelper.m index b27ed2365d7..a2acd95b580 100644 --- a/Sources/Sentry/SentryLevelHelper.m +++ b/Sources/Sentry/SentryLevelHelper.m @@ -1,5 +1,6 @@ #import "SentryLevelHelper.h" #import "SentryBreadcrumb+Private.h" +#import "SentryLevelMapper.h" @implementation SentryLevelHelper @@ -8,4 +9,9 @@ + (NSUInteger)breadcrumbLevel:(SentryBreadcrumb *)breadcrumb return breadcrumb.level; } ++ (NSString *_Nonnull)getNameFor:(NSUInteger)level +{ + return nameForSentryLevel(level); +} + @end diff --git a/Sources/Sentry/SentryLog.m b/Sources/Sentry/SentryLog.m index d53d219a57b..9350cb2df21 100644 --- a/Sources/Sentry/SentryLog.m +++ b/Sources/Sentry/SentryLog.m @@ -1,4 +1,6 @@ #import "SentryLog.h" +#import "SentryAsyncSafeLog.h" +#import "SentryFileManager.h" #import "SentryInternalCDefines.h" #import "SentryLevelMapper.h" #import "SentryLogOutput.h" @@ -15,6 +17,26 @@ @implementation SentryLog static SentryLogOutput *logOutput; static NSObject *logConfigureLock; +void +_sentry_initializeAsyncLogFile(void) +{ + const char *asyncLogPath = + [[sentryApplicationSupportPath() stringByAppendingPathComponent:@"async.log"] UTF8String]; + + NSError *error; + if (!createDirectoryIfNotExists(sentryApplicationSupportPath(), &error)) { + SENTRY_LOG_ERROR(@"Failed to initialize directory for async log file: %@", error); + return; + } + + if (SENTRY_LOG_ERRNO( + sentry_asyncLogSetFileName(asyncLogPath, true /* overwrite existing log */)) + != 0) { + SENTRY_LOG_ERROR( + @"Could not open a handle to specified path for async logging %s", asyncLogPath); + }; +} + + (void)configure:(BOOL)debug diagnosticLevel:(SentryLevel)level { static dispatch_once_t onceToken; @@ -23,6 +45,8 @@ + (void)configure:(BOOL)debug diagnosticLevel:(SentryLevel)level isDebug = debug; diagnosticLevel = level; } + + _sentry_initializeAsyncLogFile(); } + (void)logWithMessage:(NSString *)message andLevel:(SentryLevel)level diff --git a/Sources/Sentry/SentryProfilingLogging.mm b/Sources/Sentry/SentryProfilingLogging.mm deleted file mode 100644 index 5886bd141c7..00000000000 --- a/Sources/Sentry/SentryProfilingLogging.mm +++ /dev/null @@ -1,47 +0,0 @@ -#include "SentryProfilingLogging.hpp" - -#if defined(DEBUG) - -# import "SentryLog.h" - -namespace sentry { -namespace profiling { - namespace { - SentryLevel - sentryLevelFromLogLevel(LogLevel level) - { - switch (level) { - case LogLevel::None: - return kSentryLevelNone; - case LogLevel::Debug: - return kSentryLevelDebug; - case LogLevel::Info: - return kSentryLevelInfo; - case LogLevel::Warning: - return kSentryLevelWarning; - case LogLevel::Error: - return kSentryLevelError; - case LogLevel::Fatal: - return kSentryLevelFatal; - } - } - } - - void - log(LogLevel level, const char *fmt, ...) - { - if (fmt == nullptr) { - return; - } - va_list args; - va_start(args, fmt); - const auto fmtStr = [[NSString alloc] initWithUTF8String:fmt]; - const auto msgStr = [[NSString alloc] initWithFormat:fmtStr arguments:args]; - va_end(args); - [SentryLog logWithMessage:msgStr andLevel:sentryLevelFromLogLevel(level)]; - } - -} // namespace profiling -} // namespace sentry - -#endif // defined(DEBUG) diff --git a/Sources/Sentry/SentrySamplingProfiler.cpp b/Sources/Sentry/SentrySamplingProfiler.cpp index 5a86de8131c..ecba14ae855 100644 --- a/Sources/Sentry/SentrySamplingProfiler.cpp +++ b/Sources/Sentry/SentrySamplingProfiler.cpp @@ -2,6 +2,7 @@ #if SENTRY_TARGET_PROFILING_SUPPORTED +# include "SentryAsyncSafeLog.h" # include "SentryBacktrace.hpp" # include "SentryMachLogging.hpp" # include "SentryThreadMetadataCache.hpp" @@ -41,7 +42,7 @@ namespace profiling { void * samplingThreadMain(void *arg) { - SENTRY_PROF_LOG_ERROR_RETURN(pthread_setname_np("io.sentry.SamplingProfiler")); + SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_setname_np("io.sentry.SamplingProfiler")); const auto params = reinterpret_cast(arg); if (params->onThreadStart != nullptr) { params->onThreadStart(); @@ -52,12 +53,12 @@ namespace profiling { pthread_cleanup_push(deleteParams, params); while (true) { pthread_testcancel(); - if (SENTRY_PROF_LOG_MACH_MSG_RETURN(mach_msg(&replyBuf->Head, MACH_RCV_MSG, 0, + if (SENTRY_ASYNC_SAFE_LOG_MACH_MSG_RETURN(mach_msg(&replyBuf->Head, MACH_RCV_MSG, 0, maxSize, params->port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL)) != MACH_MSG_SUCCESS) { break; } - if (SENTRY_PROF_LOG_KERN_RETURN( + if (SENTRY_ASYNC_SAFE_LOG_KERN_RETURN( clock_alarm(params->clock, TIME_RELATIVE, params->delaySpec, params->port)) != KERN_SUCCESS) { break; @@ -82,12 +83,12 @@ namespace profiling { , port_(0) , numSamples_(0) { - if (SENTRY_PROF_LOG_KERN_RETURN( + if (SENTRY_ASYNC_SAFE_LOG_KERN_RETURN( host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &clock_)) != KERN_SUCCESS) { return; } - if (SENTRY_PROF_LOG_KERN_RETURN( + if (SENTRY_ASYNC_SAFE_LOG_KERN_RETURN( mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port_)) != KERN_SUCCESS) { return; @@ -106,7 +107,7 @@ namespace profiling { return; } stopSampling(); - SENTRY_PROF_LOG_KERN_RETURN( + SENTRY_ASYNC_SAFE_LOG_KERN_RETURN( mach_port_mod_refs(mach_task_self(), port_, MACH_PORT_RIGHT_RECEIVE, -1)); } @@ -114,7 +115,7 @@ namespace profiling { SamplingProfiler::startSampling(std::function onThreadStart) { if (!isInitialized_) { - SENTRY_PROF_LOG_WARN( + SENTRY_ASYNC_SAFE_LOG_WARN( "startSampling is no-op because SamplingProfiler failed to initialize"); return; } @@ -125,29 +126,29 @@ namespace profiling { isSampling_ = true; numSamples_ = 0; pthread_attr_t attr; - if (SENTRY_PROF_LOG_ERROR_RETURN(pthread_attr_init(&attr)) != 0) { + if (SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_attr_init(&attr)) != 0) { return; } sched_param param; - if (SENTRY_PROF_LOG_ERROR_RETURN(pthread_attr_getschedparam(&attr, ¶m)) == 0) { + if (SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_attr_getschedparam(&attr, ¶m)) == 0) { // A priority of 50 is higher than user input, according to: // https://chromium.googlesource.com/chromium/src/base/+/master/threading/platform_thread_mac.mm#302 // Run at a higher priority than the main thread so that we can capture main thread // backtraces even when it's busy. param.sched_priority = 50; - SENTRY_PROF_LOG_ERROR_RETURN(pthread_attr_setschedparam(&attr, ¶m)); + SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_attr_setschedparam(&attr, ¶m)); } const auto params = new SamplingThreadParams { port_, clock_, delaySpec_, cache_, callback_, std::ref(numSamples_), std::move(onThreadStart) }; - if (SENTRY_PROF_LOG_ERROR_RETURN( + if (SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN( pthread_create(&thread_, &attr, samplingThreadMain, params)) != 0) { delete params; return; } - SENTRY_PROF_LOG_KERN_RETURN(clock_alarm(clock_, TIME_RELATIVE, delaySpec_, port_)); + SENTRY_ASYNC_SAFE_LOG_KERN_RETURN(clock_alarm(clock_, TIME_RELATIVE, delaySpec_, port_)); } void @@ -160,8 +161,8 @@ namespace profiling { if (!isSampling_) { return; } - SENTRY_PROF_LOG_ERROR_RETURN(pthread_cancel(thread_)); - SENTRY_PROF_LOG_ERROR_RETURN(pthread_join(thread_, NULL)); + SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_cancel(thread_)); + SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_join(thread_, NULL)); isSampling_ = false; } diff --git a/Sources/Sentry/SentryThreadHandle.cpp b/Sources/Sentry/SentryThreadHandle.cpp index b978cf02251..cbf810d40cb 100644 --- a/Sources/Sentry/SentryThreadHandle.cpp +++ b/Sources/Sentry/SentryThreadHandle.cpp @@ -2,8 +2,8 @@ #if SENTRY_TARGET_PROFILING_SUPPORTED +# include "SentryAsyncSafeLog.h" # include "SentryMachLogging.hpp" -# include "SentryProfilingLogging.hpp" # include # include @@ -30,7 +30,7 @@ namespace profiling { // If the ThreadHandle object owns the mach_port (i.e. with a +1 reference count) // the port must be deallocated. if (isOwnedPort_) { - SENTRY_PROF_LOG_KERN_RETURN(mach_port_deallocate(mach_task_self(), handle_)); + SENTRY_ASYNC_SAFE_LOG_KERN_RETURN(mach_port_deallocate(mach_task_self(), handle_)); } } @@ -47,7 +47,7 @@ namespace profiling { std::vector> threads; mach_msg_type_number_t count; thread_act_array_t list; - if (SENTRY_PROF_LOG_KERN_RETURN(task_threads(mach_task_self(), &list, &count)) + if (SENTRY_ASYNC_SAFE_LOG_KERN_RETURN(task_threads(mach_task_self(), &list, &count)) == KERN_SUCCESS) { for (decltype(count) i = 0; i < count; i++) { const auto thread = list[i]; @@ -55,7 +55,7 @@ namespace profiling { new ThreadHandle(thread, true /* isOwnedPort */))); } } - SENTRY_PROF_LOG_KERN_RETURN(vm_deallocate( + SENTRY_ASYNC_SAFE_LOG_KERN_RETURN(vm_deallocate( mach_task_self(), reinterpret_cast(list), sizeof(*list) * count)); return threads; } @@ -67,7 +67,7 @@ namespace profiling { mach_msg_type_number_t count; thread_act_array_t list; auto current = ThreadHandle::current(); - if (SENTRY_PROF_LOG_KERN_RETURN(task_threads(mach_task_self(), &list, &count)) + if (SENTRY_ASYNC_SAFE_LOG_KERN_RETURN(task_threads(mach_task_self(), &list, &count)) == KERN_SUCCESS) { for (decltype(count) i = 0; i < count; i++) { const auto thread = list[i]; @@ -75,11 +75,12 @@ namespace profiling { threads.push_back(std::unique_ptr( new ThreadHandle(thread, true /* isOwnedPort */))); } else { - SENTRY_PROF_LOG_KERN_RETURN(mach_port_deallocate(mach_task_self(), thread)); + SENTRY_ASYNC_SAFE_LOG_KERN_RETURN( + mach_port_deallocate(mach_task_self(), thread)); } } } - SENTRY_PROF_LOG_KERN_RETURN(vm_deallocate( + SENTRY_ASYNC_SAFE_LOG_KERN_RETURN(vm_deallocate( mach_task_self(), reinterpret_cast(list), sizeof(*list) * count)); return std::make_pair(std::move(threads), std::move(current)); } @@ -110,7 +111,8 @@ namespace profiling { return {}; } char name[MAXTHREADNAMESIZE]; - if (SENTRY_PROF_LOG_ERROR_RETURN(pthread_getname_np(handle, name, sizeof(name))) == 0) { + if (SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_getname_np(handle, name, sizeof(name))) + == 0) { return std::string(name); } return {}; @@ -124,7 +126,8 @@ namespace profiling { return -1; } struct sched_param param; - if (SENTRY_PROF_LOG_ERROR_RETURN(pthread_getschedparam(handle, nullptr, ¶m)) == 0) { + if (SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_getschedparam(handle, nullptr, ¶m)) + == 0) { return param.sched_priority; } return -1; @@ -163,7 +166,8 @@ namespace profiling { const auto rv = thread_info( handle_, THREAD_BASIC_INFO, reinterpret_cast(&data), &count); // MACH_SEND_INVALID_DEST is returned when the thread no longer exists - if ((rv != MACH_SEND_INVALID_DEST) && (SENTRY_PROF_LOG_KERN_RETURN(rv) == KERN_SUCCESS)) { + if ((rv != MACH_SEND_INVALID_DEST) + && (SENTRY_ASYNC_SAFE_LOG_KERN_RETURN(rv) == KERN_SUCCESS)) { cpuInfo.userTimeMicros = std::chrono::seconds(data.user_time.seconds) + std::chrono::microseconds(data.user_time.microseconds); cpuInfo.systemTimeMicros = std::chrono::seconds(data.system_time.seconds) @@ -186,7 +190,8 @@ namespace profiling { const auto rv = thread_info( handle_, THREAD_BASIC_INFO, reinterpret_cast(&data), &count); // MACH_SEND_INVALID_DEST is returned when the thread no longer exists - if ((rv != MACH_SEND_INVALID_DEST) && (SENTRY_PROF_LOG_KERN_RETURN(rv) == KERN_SUCCESS)) { + if ((rv != MACH_SEND_INVALID_DEST) + && (SENTRY_ASYNC_SAFE_LOG_KERN_RETURN(rv) == KERN_SUCCESS)) { return ((data.flags & TH_FLAGS_IDLE) == TH_FLAGS_IDLE) || (data.run_state != TH_STATE_RUNNING); } @@ -240,7 +245,8 @@ namespace profiling { if (pthreadHandle_ == nullptr) { // The thread no longer exists; this is not a recoverable failure so there's nothing // more we can do here. - SENTRY_PROF_LOG_DEBUG("Failed to get pthread handle for mach thread %u", handle_); + SENTRY_ASYNC_SAFE_LOG_DEBUG( + "Failed to get pthread handle for mach thread %u", handle_); } } return pthreadHandle_; diff --git a/Sources/Sentry/SentryTime.mm b/Sources/Sentry/SentryTime.mm index d003e68c422..f299e5df638 100644 --- a/Sources/Sentry/SentryTime.mm +++ b/Sources/Sentry/SentryTime.mm @@ -4,6 +4,7 @@ #import #import +#import "SentryAsyncSafeLog.h" #import "SentryMachLogging.hpp" uint64_t @@ -51,7 +52,7 @@ static struct mach_timebase_info info; static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ SENTRY_PROF_LOG_KERN_RETURN(mach_timebase_info(&info)); }); + dispatch_once(&onceToken, ^{ SENTRY_ASYNC_SAFE_LOG_KERN_RETURN(mach_timebase_info(&info)); }); duration *= info.numer; duration /= info.denom; return duration; diff --git a/Sources/Sentry/SentryTransaction.m b/Sources/Sentry/SentryTransaction.m index dff36566dfe..57778f61419 100644 --- a/Sources/Sentry/SentryTransaction.m +++ b/Sources/Sentry/SentryTransaction.m @@ -39,6 +39,12 @@ - (instancetype)initWithTrace:(SentryTracer *)trace children:(NSArray - -// write(2) is async signal safe: -// http://man7.org/linux/man-pages/man7/signal-safety.7.html -#define __SENTRY_LOG_ASYNC_SAFE(fd, str) write(fd, str, sizeof(str) - 1) -#define SENTRY_LOG_ASYNC_SAFE_INFO(str) __SENTRY_LOG_ASYNC_SAFE(STDOUT_FILENO, str "\n") -#define SENTRY_LOG_ASYNC_SAFE_ERROR(str) __SENTRY_LOG_ASYNC_SAFE(STDERR_FILENO, str "\n") diff --git a/Sources/Sentry/include/SentryFileManager.h b/Sources/Sentry/include/SentryFileManager.h index cb774591c79..531e13db156 100644 --- a/Sources/Sentry/include/SentryFileManager.h +++ b/Sources/Sentry/include/SentryFileManager.h @@ -93,6 +93,9 @@ SENTRY_NO_INIT - (void)storeTimezoneOffset:(NSInteger)offset; - (void)deleteTimezoneOffset; +BOOL createDirectoryIfNotExists(NSString *path, NSError **error); +SENTRY_EXTERN NSString *_Nullable sentryApplicationSupportPath(void); + #if SENTRY_TARGET_PROFILING_SUPPORTED /** * @return @c YES if a launch profile config file is present, @c NO otherwise. If a config file is diff --git a/Sources/Sentry/include/SentryInternalCDefines.h b/Sources/Sentry/include/SentryInternalCDefines.h index 67fd7d76cba..4b6144c6b76 100644 --- a/Sources/Sentry/include/SentryInternalCDefines.h +++ b/Sources/Sentry/include/SentryInternalCDefines.h @@ -1,3 +1,5 @@ +#pragma once + typedef unsigned long long bytes; /** @@ -12,3 +14,73 @@ typedef unsigned long long bytes; #else # define SENTRY_DISABLE_THREAD_SANITIZER(message) #endif + +// The following adapted from: https://github.com/kstenerud/KSCrash KSCrashSystemCapabilities.h +// +// Copyright (c) 2012 Karl Stenerud. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall remain in place +// in this source code. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +// + +#include + +#ifndef TARGET_OS_VISION +# define TARGET_OS_VISION 0 +#endif + +#define SENTRY_HOST_IOS TARGET_OS_IOS +#define SENTRY_HOST_TV TARGET_OS_TV +#define SENTRY_HOST_WATCH TARGET_OS_WATCH +#define SENTRY_HOST_VISION TARGET_OS_VISION +#define SENTRY_HOST_MAC \ + (TARGET_OS_MAC && !(TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH || TARGET_OS_VISION)) + +#if SENTRY_HOST_WATCH +# define SENTRY_HAS_NSEXTENSION 1 +#else +# define SENTRY_HAS_NSEXTENSION 0 +#endif + +// Mach APIs are explicitly marked as unavailable in tvOS and watchOS. +// See https://github.com/getsentry/sentry-cocoa/issues/406#issuecomment-1171872518 +#if SENTRY_HOST_IOS || SENTRY_HOST_MAC +# define SENTRY_HAS_MACH 1 +#else +# define SENTRY_HAS_MACH 0 +#endif + +// signal APIs are explicitly marked as unavailable in watchOS. +// See https://github.com/getsentry/sentry-cocoa/issues/406#issuecomment-1171872518 +#if SENTRY_HOST_IOS || SENTRY_HOST_MAC || SENTRY_HOST_TV +# define SENTRY_HAS_SIGNAL 1 +#else +# define SENTRY_HAS_SIGNAL 0 +#endif + +#if SENTRY_HOST_MAC || SENTRY_HOST_IOS +# define SENTRY_HAS_SIGNAL_STACK 1 +#else +# define SENTRY_HAS_SIGNAL_STACK 0 +#endif + +#if SENTRY_HOST_MAC || SENTRY_HOST_IOS || SENTRY_HOST_TV +# define SENTRY_HAS_THREADS_API 1 +#else +# define SENTRY_HAS_THREADS_API 0 +#endif diff --git a/Sources/Sentry/include/SentryLevelHelper.h b/Sources/Sentry/include/SentryLevelHelper.h index e599cfe6298..b617d8b6ad5 100644 --- a/Sources/Sentry/include/SentryLevelHelper.h +++ b/Sources/Sentry/include/SentryLevelHelper.h @@ -11,6 +11,8 @@ NS_ASSUME_NONNULL_BEGIN + (NSUInteger)breadcrumbLevel:(SentryBreadcrumb *)breadcrumb; ++ (NSString *_Nonnull)getNameFor:(NSUInteger)level; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryLog.h b/Sources/Sentry/include/SentryLog.h index 586742800fe..21dce69d0a3 100644 --- a/Sources/Sentry/include/SentryLog.h +++ b/Sources/Sentry/include/SentryLog.h @@ -43,7 +43,7 @@ NS_ASSUME_NONNULL_END #define SENTRY_LOG_ERRNO(statement) \ ({ \ errno = 0; \ - const auto __log_rv = (statement); \ + const int __log_rv = (statement); \ const int __log_errnum = errno; \ if (__log_errnum != 0) { \ SENTRY_LOG_ERROR(@"%s failed with code: %d, description: %s", #statement, \ diff --git a/Sources/Sentry/include/SentryMachLogging.hpp b/Sources/Sentry/include/SentryMachLogging.hpp index 625f2e065de..f1ff8a2d04e 100644 --- a/Sources/Sentry/include/SentryMachLogging.hpp +++ b/Sources/Sentry/include/SentryMachLogging.hpp @@ -1,7 +1,6 @@ #pragma once #include "SentryProfilingConditionals.h" -#include "SentryProfilingLogging.hpp" #include #include @@ -27,22 +26,23 @@ const char *machMessageReturnCodeDescription(mach_msg_return_t mr) noexcept; } // namespace sentry -#define SENTRY_PROF_LOG_KERN_RETURN(statement) \ +#define SENTRY_ASYNC_SAFE_LOG_KERN_RETURN(statement) \ ({ \ const kern_return_t __log_kr = statement; \ if (__log_kr != KERN_SUCCESS) { \ - SENTRY_PROF_LOG_ERROR("%s failed with kern return code: %d, description: %s", \ + SENTRY_ASYNC_SAFE_LOG_ERROR("%s failed with kern return code: %d, description: %s", \ #statement, __log_kr, sentry::kernelReturnCodeDescription(__log_kr)); \ } \ __log_kr; \ }) -#define SENTRY_PROF_LOG_MACH_MSG_RETURN(statement) \ +#define SENTRY_ASYNC_SAFE_LOG_MACH_MSG_RETURN(statement) \ ({ \ const mach_msg_return_t __log_mr = statement; \ if (__log_mr != MACH_MSG_SUCCESS) { \ - SENTRY_PROF_LOG_ERROR("%s failed with mach_msg return code: %d, description: %s", \ - #statement, __log_mr, sentry::machMessageReturnCodeDescription(__log_mr)); \ + SENTRY_ASYNC_SAFE_LOG_ERROR( \ + "%s failed with mach_msg return code: %d, description: %s", #statement, __log_mr, \ + sentry::machMessageReturnCodeDescription(__log_mr)); \ } \ __log_mr; \ }) diff --git a/Sources/Sentry/include/SentryProfilingLogging.hpp b/Sources/Sentry/include/SentryProfilingLogging.hpp deleted file mode 100644 index d4946eec4c1..00000000000 --- a/Sources/Sentry/include/SentryProfilingLogging.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#if defined(DEBUG) - -# include -# include -# include -# include -# include - -namespace sentry { -namespace profiling { - - enum class LogLevel { None, Debug, Info, Warning, Error, Fatal }; - /** - * Exposes a pure C++ interface to the Objective-C Sentry logging API so that - * this can be used from C++ code without having to import Objective-C stuff. - */ - void log(LogLevel level, const char *fmt, ...); - -} // namespace profiling -} // namespace sentry - -# define SENTRY_PROF_LOG_DEBUG(...) \ - sentry::profiling::log(sentry::profiling::LogLevel::Debug, __VA_ARGS__) -# define SENTRY_PROF_LOG_WARN(...) \ - sentry::profiling::log(sentry::profiling::LogLevel::Warning, __VA_ARGS__) -# define SENTRY_PROF_LOG_ERROR(...) \ - sentry::profiling::log(sentry::profiling::LogLevel::Error, __VA_ARGS__) - -#else - -// Don't do anything with these in production until we can get a logging solution in place that -// doesn't use NSLog. We can't use NSLog in these codepaths because it takes a lock, and if the -// profiler's sampling thread is terminated before it can release that lock, then subsequent -// attempts to acquire it can cause a crash. -// See https://github.com/getsentry/sentry-cocoa/issues/3336#issuecomment-1802892052 for more info. -# define SENTRY_PROF_LOG_DEBUG(...) -# define SENTRY_PROF_LOG_WARN(...) -# define SENTRY_PROF_LOG_ERROR(...) - -#endif // defined(DEBUG) - -/** - * Logs the error code returned by executing `statement`, and returns the - * error code (i.e. returns the return value of `statement`). - */ -#define SENTRY_PROF_LOG_ERROR_RETURN(statement) \ - ({ \ - const int __log_errnum = statement; \ - if (__log_errnum != 0) { \ - SENTRY_PROF_LOG_ERROR("%s failed with code: %d, description: %s", #statement, \ - __log_errnum, std::strerror(__log_errnum)); \ - } \ - __log_errnum; \ - }) diff --git a/Sources/SentryCrash/Installations/SentryCrashInstallation.m b/Sources/SentryCrash/Installations/SentryCrashInstallation.m index 956101ab36e..447f9126e49 100644 --- a/Sources/SentryCrash/Installations/SentryCrashInstallation.m +++ b/Sources/SentryCrash/Installations/SentryCrashInstallation.m @@ -26,10 +26,10 @@ // #import "SentryCrashInstallation.h" +#import "SentryAsyncSafeLog.h" #import "SentryCrash.h" #import "SentryCrashInstallation+Private.h" #import "SentryCrashJSONCodecObjC.h" -#import "SentryCrashLogger.h" #import "SentryCrashNSErrorUtil.h" #import "SentryCrashReportFilterBasic.h" #import "SentryDependencyContainer.h" diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor.c b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor.c index c825ffbab96..73bfa37752d 100644 --- a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor.c +++ b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor.c @@ -36,12 +36,12 @@ #include "SentryCrashMonitor_NSException.h" #include "SentryCrashMonitor_Signal.h" #include "SentryCrashMonitor_System.h" -#include "SentryCrashSystemCapabilities.h" #include "SentryCrashThread.h" +#include "SentryInternalCDefines.h" #include -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" // ============================================================================ #pragma mark - Globals - @@ -53,24 +53,22 @@ typedef struct { } Monitor; static Monitor g_monitors[] = { -#if SentryCrashCRASH_HAS_MACH +#if SENTRY_HAS_MACH { .monitorType = SentryCrashMonitorTypeMachException, .getAPI = sentrycrashcm_machexception_getAPI, }, #endif -#if SentryCrashCRASH_HAS_SIGNAL +#if SENTRY_HAS_SIGNAL { .monitorType = SentryCrashMonitorTypeSignal, .getAPI = sentrycrashcm_signal_getAPI, }, #endif -#if SentryCrashCRASH_HAS_OBJC { .monitorType = SentryCrashMonitorTypeNSException, .getAPI = sentrycrashcm_nsexception_getAPI, }, -#endif { .monitorType = SentryCrashMonitorTypeCPPException, .getAPI = sentrycrashcm_cppexception_getAPI, @@ -150,24 +148,19 @@ sentrycrashcm_setActiveMonitors(SentryCrashMonitorType monitorTypes) static bool hasWarned = false; if (!hasWarned) { hasWarned = true; - SentryCrashLOGBASIC_WARN(" ************************ Crash " - "Handler Notice ************************"); - SentryCrashLOGBASIC_WARN(" * App is running in a debugger. " - "Masking out unsafe monitors. *"); - SentryCrashLOGBASIC_WARN(" * This means that most crashes WILL " - "NOT BE RECORDED while debugging! *"); - SentryCrashLOGBASIC_WARN(" " - "*****************************************" - "*****************************"); + SENTRY_ASYNC_SAFE_LOG_WARN("App is running in a debugger. Masking out unsafe monitors. " + "This means that most crashes WILL " + "NOT BE RECORDED while debugging!"); } monitorTypes &= SentryCrashMonitorTypeDebuggerSafe; } if (g_requiresAsyncSafety && (monitorTypes & SentryCrashMonitorTypeAsyncUnsafe)) { - SentryCrashLOG_DEBUG("Async-safe environment detected. Masking out unsafe monitors."); + SENTRY_ASYNC_SAFE_LOG_DEBUG( + "Async-safe environment detected. Masking out unsafe monitors."); monitorTypes &= SentryCrashMonitorTypeAsyncSafe; } - SentryCrashLOG_DEBUG( + SENTRY_ASYNC_SAFE_LOG_DEBUG( "Changing active monitors from 0x%x tp 0x%x.", g_activeMonitors, monitorTypes); SentryCrashMonitorType activeMonitors = SentryCrashMonitorTypeNone; @@ -182,7 +175,7 @@ sentrycrashcm_setActiveMonitors(SentryCrashMonitorType monitorTypes) } } - SentryCrashLOG_DEBUG("Active monitors are now 0x%x.", activeMonitors); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Active monitors are now 0x%x.", activeMonitors); g_activeMonitors = activeMonitors; } @@ -205,7 +198,8 @@ sentrycrashcm_notifyFatalExceptionCaptured(bool isAsyncSafeEnvironment) } g_handlingFatalException = true; if (g_crashedDuringExceptionHandling) { - SentryCrashLOG_INFO("Detected crash in the crash reporter. Uninstalling SentryCrash."); + SENTRY_ASYNC_SAFE_LOG_INFO( + "Detected crash in the crash reporter. Uninstalling SentryCrash."); sentrycrashcm_setActiveMonitors(SentryCrashMonitorTypeNone); } return g_crashedDuringExceptionHandling; @@ -228,7 +222,7 @@ sentrycrashcm_handleException(struct SentryCrash_MonitorContext *context) g_onExceptionEvent(context); if (g_handlingFatalException && !g_crashedDuringExceptionHandling) { - SentryCrashLOG_DEBUG("Exception is fatal. Restoring original handlers."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Exception is fatal. Restoring original handlers."); sentrycrashcm_setActiveMonitors(SentryCrashMonitorTypeNone); } } diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitorContext.h b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitorContext.h index b545ad4cf25..2bd3eac7fbd 100644 --- a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitorContext.h +++ b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitorContext.h @@ -220,9 +220,6 @@ typedef struct SentryCrash_MonitorContext { const char *reason; } ZombieException; - /** Full path to the console log, if any. */ - const char *consoleLogPath; - } SentryCrash_MonitorContext; #ifdef __cplusplus diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_AppState.c b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_AppState.c index da05126495a..63318ba7bf7 100644 --- a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_AppState.c +++ b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_AppState.c @@ -31,7 +31,7 @@ #include "SentryCrashJSONCodec.h" #include "SentryCrashMonitorContext.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #include #include @@ -124,7 +124,7 @@ onIntegerElement(const char *const name, const int64_t value, void *const userDa if (strcmp(name, kKeyFormatVersion) == 0) { if (value != kFormatVersion) { - SentryCrashLOG_ERROR("Expected version 1 but got %" PRId64, value); + SENTRY_ASYNC_SAFE_LOG_ERROR("Expected version 1 but got %" PRId64, value); return SentryCrashJSON_ERROR_INVALID_DATA; } } else if (strcmp(name, kKeyLaunchesSinceLastCrash) == 0) { @@ -229,7 +229,7 @@ loadState(const char *const path) char *data; int length; if (!sentrycrashfu_readEntireFile(path, &data, &length, 50000)) { - SentryCrashLOG_ERROR("%s: Could not load file", path); + SENTRY_ASYNC_SAFE_LOG_ERROR("%s: Could not load file", path); return false; } @@ -252,7 +252,7 @@ loadState(const char *const path) data, (int)length, stringBuffer, sizeof(stringBuffer), &callbacks, &g_state, &errorOffset); free(data); if (result != SentryCrashJSON_OK) { - SentryCrashLOG_ERROR( + SENTRY_ASYNC_SAFE_LOG_ERROR( "%s, offset %d: %s", path, errorOffset, sentrycrashjson_stringForError(result)); return false; } @@ -270,7 +270,8 @@ saveState(const char *const path) { int fd = open(path, O_RDWR | O_CREAT | O_TRUNC, 0644); if (fd < 0) { - SentryCrashLOG_ERROR("Could not open file %s for writing: %s", path, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "Could not open file %s for writing: %s", path, strerror(errno)); return false; } @@ -333,7 +334,7 @@ saveState(const char *const path) done: close(fd); if (result != SentryCrashJSON_OK) { - SentryCrashLOG_ERROR("%s: %s", path, sentrycrashjson_stringForError(result)); + SENTRY_ASYNC_SAFE_LOG_ERROR("%s: %s", path, sentrycrashjson_stringForError(result)); return false; } return true; diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_CPPException.cpp b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_CPPException.cpp index e1beacc0316..633ae7e07c2 100644 --- a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_CPPException.cpp +++ b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_CPPException.cpp @@ -30,7 +30,7 @@ #include "SentryCrashStackCursor_SelfThread.h" #include "SentryCrashThread.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #include #include @@ -123,7 +123,7 @@ sentrycrashcm_cppexception_callOriginalTerminationHandler(void) // Can be NULL as the return value of set_terminate can be a NULL pointer; see: // https://en.cppreference.com/w/cpp/error/set_terminate if (g_originalTerminateHandler != NULL) { - SentryCrashLOG_DEBUG("Calling original terminate handler."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Calling original terminate handler."); g_originalTerminateHandler(); } } @@ -134,7 +134,7 @@ CPPExceptionTerminate(void) thread_act_array_t threads = NULL; mach_msg_type_number_t numThreads = 0; sentrycrashmc_suspendEnvironment(&threads, &numThreads); - SentryCrashLOG_DEBUG("Trapped c++ exception"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Trapped c++ exception"); const char *name = NULL; std::type_info *tinfo = __cxxabiv1::__cxa_current_exception_type(); if (tinfo != NULL) { @@ -152,10 +152,10 @@ CPPExceptionTerminate(void) std::exception_ptr currException = std::current_exception(); if (currException == NULL) { - SentryCrashLOG_DEBUG("Terminate without exception."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Terminate without exception."); sentrycrashsc_initSelfThread(&g_stackCursor, 0); } else { - SentryCrashLOG_DEBUG("Discovering what kind of exception was thrown."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Discovering what kind of exception was thrown."); g_captureNextStackTrace = false; try { throw; @@ -189,7 +189,7 @@ CPPExceptionTerminate(void) SentryCrashMC_NEW_CONTEXT(machineContext); sentrycrashmc_getContextForThread(sentrycrashthread_self(), machineContext, true); - SentryCrashLOG_DEBUG("Filling out context."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Filling out context."); crashContext->crashType = SentryCrashMonitorTypeCPPException; crashContext->eventID = g_eventID; crashContext->registersAreValid = false; @@ -201,8 +201,8 @@ CPPExceptionTerminate(void) sentrycrashcm_handleException(crashContext); } else { - SentryCrashLOG_DEBUG("Detected NSException. Letting the current " - "NSException handler deal with it."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Detected NSException. Letting the current " + "NSException handler deal with it."); } sentrycrashmc_resumeEnvironment(threads, numThreads); diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_MachException.c b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_MachException.c index 77180ad9901..35da9526925 100644 --- a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_MachException.c +++ b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_MachException.c @@ -30,13 +30,12 @@ #include "SentryCrashID.h" #include "SentryCrashMonitorContext.h" #include "SentryCrashStackCursor_MachineContext.h" -#include "SentryCrashSystemCapabilities.h" #include "SentryCrashThread.h" #include "SentryInternalCDefines.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" -#if SentryCrashCRASH_HAS_MACH +#if SENTRY_HAS_MACH # include # include @@ -161,9 +160,9 @@ static char g_secondaryEventID[37]; static void restoreExceptionPorts(void) { - SentryCrashLOG_DEBUG("Restoring original exception ports."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Restoring original exception ports."); if (g_previousExceptionPorts.count == 0) { - SentryCrashLOG_DEBUG("Original exception ports were already restored."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Original exception ports were already restored."); return; } @@ -172,15 +171,15 @@ restoreExceptionPorts(void) // Reinstall old exception ports. for (mach_msg_type_number_t i = 0; i < g_previousExceptionPorts.count; i++) { - SentryCrashLOG_TRACE("Restoring port index %d", i); + SENTRY_ASYNC_SAFE_LOG_TRACE("Restoring port index %d", i); kr = task_set_exception_ports(thisTask, g_previousExceptionPorts.masks[i], g_previousExceptionPorts.ports[i], g_previousExceptionPorts.behaviors[i], g_previousExceptionPorts.flavors[i]); if (kr != KERN_SUCCESS) { - SentryCrashLOG_ERROR("task_set_exception_ports: %s", mach_error_string(kr)); + SENTRY_ASYNC_SAFE_LOG_ERROR("task_set_exception_ports: %s", mach_error_string(kr)); } } - SentryCrashLOG_DEBUG("Exception ports restored."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Exception ports restored."); g_previousExceptionPorts.count = 0; } @@ -252,7 +251,7 @@ machExceptionForSignal(int sigNum) # pragma mark - Reserved threads - // ============================================================================ /** - * We only have reserved threads if SentryCrashCRASH_HAS_MACH. + * We only have reserved threads if SENTRY_HAS_MACH. */ bool @@ -267,7 +266,7 @@ sentrycrashcm_hasReservedThreads(void) return g_primaryMachThread != 0 && g_secondaryMachThread != 0; } -#else // !SentryCrashCRASH_HAS_MACH +#else // !SENTRY_HAS_MACH bool sentrycrashcm_isReservedThread(thread_t thread) { @@ -280,9 +279,9 @@ sentrycrashcm_hasReservedThreads(void) return false; } -#endif // SentryCrashCRASH_HAS_MACH +#endif // SENTRY_HAS_MACH -#if SentryCrashCRASH_HAS_MACH +#if SENTRY_HAS_MACH // ============================================================================ # pragma mark - Handler - @@ -302,13 +301,13 @@ handleExceptions(void *const userData) const char *threadName = (const char *)userData; pthread_setname_np(threadName); if (strcmp(threadName, kThreadSecondary) == 0) { - SentryCrashLOG_DEBUG("This is the secondary thread. Suspending."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("This is the secondary thread. Suspending."); thread_suspend((thread_t)sentrycrashthread_self()); eventID = g_secondaryEventID; } for (;;) { - SentryCrashLOG_DEBUG("Waiting for mach exception"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Waiting for mach exception"); // Wait for a message. kern_return_t kr = mach_msg(&exceptionMessage.header, MACH_RCV_MSG, 0, @@ -318,10 +317,10 @@ handleExceptions(void *const userData) } // Loop and try again on failure. - SentryCrashLOG_ERROR("mach_msg: %s", mach_error_string(kr)); + SENTRY_ASYNC_SAFE_LOG_ERROR("mach_msg: %s", mach_error_string(kr)); } - SentryCrashLOG_DEBUG("Trapped mach exception code 0x%llx, subcode 0x%llx", + SENTRY_ASYNC_SAFE_LOG_DEBUG("Trapped mach exception code 0x%llx, subcode 0x%llx", exceptionMessage.code[0], exceptionMessage.code[1]); if (g_isEnabled) { thread_act_array_t threads = NULL; @@ -330,27 +329,28 @@ handleExceptions(void *const userData) g_isHandlingCrash = true; sentrycrashcm_notifyFatalExceptionCaptured(true); - SentryCrashLOG_DEBUG("Exception handler is installed. Continuing exception handling."); + SENTRY_ASYNC_SAFE_LOG_DEBUG( + "Exception handler is installed. Continuing exception handling."); // Switch to the secondary thread if necessary, or uninstall the handler // to avoid a death loop. if (sentrycrashthread_self() == g_primaryMachThread) { - SentryCrashLOG_DEBUG("This is the primary exception thread. " - "Activating secondary thread."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("This is the primary exception thread. " + "Activating secondary thread."); // TODO: This was put here to avoid a freeze. Does secondary thread // ever fire? restoreExceptionPorts(); if (thread_resume(g_secondaryMachThread) != KERN_SUCCESS) { - SentryCrashLOG_DEBUG("Could not activate secondary thread."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Could not activate secondary thread."); } } else { - SentryCrashLOG_DEBUG("This is the secondary exception thread. " - "Restoring original exception ports."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("This is the secondary exception thread. " + "Restoring original exception ports."); // restoreExceptionPorts(); } // Fill out crash information - SentryCrashLOG_DEBUG("Fetching machine state."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Fetching machine state."); SentryCrashMC_NEW_CONTEXT(machineContext); SentryCrash_MonitorContext *crashContext = &g_monitorContext; crashContext->offendingMachineContext = machineContext; @@ -358,7 +358,7 @@ handleExceptions(void *const userData) if (sentrycrashmc_getContextForThread(exceptionMessage.thread.name, machineContext, true)) { sentrycrashsc_initWithMachineContext( &g_stackCursor, MAX_STACKTRACE_LENGTH, machineContext); - SentryCrashLOG_TRACE("Fault address %p, instruction address %p", + SENTRY_ASYNC_SAFE_LOG_TRACE("Fault address %p, instruction address %p", sentrycrashcpu_faultAddress(machineContext), sentrycrashcpu_instructionAddress(machineContext)); if (exceptionMessage.exception == EXC_BAD_ACCESS) { @@ -368,7 +368,7 @@ handleExceptions(void *const userData) } } - SentryCrashLOG_DEBUG("Filling out context."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Filling out context."); crashContext->crashType = SentryCrashMonitorTypeMachException; crashContext->eventID = eventID; crashContext->registersAreValid = true; @@ -387,12 +387,12 @@ handleExceptions(void *const userData) sentrycrashcm_handleException(crashContext); - SentryCrashLOG_DEBUG("Crash handling complete. Restoring original handlers."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Crash handling complete. Restoring original handlers."); g_isHandlingCrash = false; sentrycrashmc_resumeEnvironment(threads, numThreads); } - SentryCrashLOG_DEBUG("Replying to mach exception message."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Replying to mach exception message."); // Send a reply saying "I didn't handle this exception". replyMessage.header = exceptionMessage.header; replyMessage.NDR = exceptionMessage.NDR; @@ -411,7 +411,7 @@ handleExceptions(void *const userData) static void uninstallExceptionHandler(void) SENTRY_DISABLE_THREAD_SANITIZER("Known data race to fix") { - SentryCrashLOG_DEBUG("Uninstalling mach exception handler."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Uninstalling mach exception handler."); // NOTE: Do not deallocate the exception port. If a secondary crash occurs // it will hang the process. @@ -421,7 +421,7 @@ uninstallExceptionHandler(void) SENTRY_DISABLE_THREAD_SANITIZER("Known data race thread_t thread_self = (thread_t)sentrycrashthread_self(); if (g_primaryPThread != 0 && g_primaryMachThread != thread_self) { - SentryCrashLOG_DEBUG("Canceling primary exception thread."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Canceling primary exception thread."); if (g_isHandlingCrash) { thread_terminate(g_primaryMachThread); } else { @@ -431,7 +431,7 @@ uninstallExceptionHandler(void) SENTRY_DISABLE_THREAD_SANITIZER("Known data race g_primaryPThread = 0; } if (g_secondaryPThread != 0 && g_secondaryMachThread != thread_self) { - SentryCrashLOG_DEBUG("Canceling secondary exception thread."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Canceling secondary exception thread."); if (g_isHandlingCrash) { thread_terminate(g_secondaryMachThread); } else { @@ -442,13 +442,13 @@ uninstallExceptionHandler(void) SENTRY_DISABLE_THREAD_SANITIZER("Known data race } g_exceptionPort = MACH_PORT_NULL; - SentryCrashLOG_DEBUG("Mach exception handlers uninstalled."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Mach exception handlers uninstalled."); } static bool installExceptionHandler(void) { - SentryCrashLOG_DEBUG("Installing mach exception handler."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Installing mach exception handler."); bool attributes_created = false; pthread_attr_t attr; @@ -460,66 +460,66 @@ installExceptionHandler(void) exception_mask_t mask = EXC_MASK_BAD_ACCESS | EXC_MASK_BAD_INSTRUCTION | EXC_MASK_ARITHMETIC | EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT; - SentryCrashLOG_DEBUG("Backing up original exception ports."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Backing up original exception ports."); kr = task_get_exception_ports(thisTask, mask, g_previousExceptionPorts.masks, &g_previousExceptionPorts.count, g_previousExceptionPorts.ports, g_previousExceptionPorts.behaviors, g_previousExceptionPorts.flavors); if (kr != KERN_SUCCESS) { - SentryCrashLOG_ERROR("task_get_exception_ports: %s", mach_error_string(kr)); + SENTRY_ASYNC_SAFE_LOG_ERROR("task_get_exception_ports: %s", mach_error_string(kr)); goto failed; } if (g_exceptionPort == MACH_PORT_NULL) { - SentryCrashLOG_DEBUG("Allocating new port with receive rights."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Allocating new port with receive rights."); kr = mach_port_allocate(thisTask, MACH_PORT_RIGHT_RECEIVE, &g_exceptionPort); if (kr != KERN_SUCCESS) { - SentryCrashLOG_ERROR("mach_port_allocate: %s", mach_error_string(kr)); + SENTRY_ASYNC_SAFE_LOG_ERROR("mach_port_allocate: %s", mach_error_string(kr)); goto failed; } - SentryCrashLOG_DEBUG("Adding send rights to port."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Adding send rights to port."); kr = mach_port_insert_right( thisTask, g_exceptionPort, g_exceptionPort, MACH_MSG_TYPE_MAKE_SEND); if (kr != KERN_SUCCESS) { - SentryCrashLOG_ERROR("mach_port_insert_right: %s", mach_error_string(kr)); + SENTRY_ASYNC_SAFE_LOG_ERROR("mach_port_insert_right: %s", mach_error_string(kr)); goto failed; } } - SentryCrashLOG_DEBUG("Installing port as exception handler."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Installing port as exception handler."); kr = task_set_exception_ports(thisTask, mask, g_exceptionPort, (int)(EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES), THREAD_STATE_NONE); if (kr != KERN_SUCCESS) { - SentryCrashLOG_ERROR("task_set_exception_ports: %s", mach_error_string(kr)); + SENTRY_ASYNC_SAFE_LOG_ERROR("task_set_exception_ports: %s", mach_error_string(kr)); goto failed; } - SentryCrashLOG_DEBUG("Creating secondary exception thread (suspended)."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Creating secondary exception thread (suspended)."); pthread_attr_init(&attr); attributes_created = true; pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); error = pthread_create(&g_secondaryPThread, &attr, &handleExceptions, kThreadSecondary); if (error != 0) { - SentryCrashLOG_ERROR("pthread_create_suspended_np: %s", strerror(error)); + SENTRY_ASYNC_SAFE_LOG_ERROR("pthread_create_suspended_np: %s", strerror(error)); goto failed; } g_secondaryMachThread = pthread_mach_thread_np(g_secondaryPThread); - SentryCrashLOG_DEBUG("Creating primary exception thread."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Creating primary exception thread."); error = pthread_create(&g_primaryPThread, &attr, &handleExceptions, kThreadPrimary); if (error != 0) { - SentryCrashLOG_ERROR("pthread_create: %s", strerror(error)); + SENTRY_ASYNC_SAFE_LOG_ERROR("pthread_create: %s", strerror(error)); goto failed; } pthread_attr_destroy(&attr); g_primaryMachThread = pthread_mach_thread_np(g_primaryPThread); - SentryCrashLOG_DEBUG("Mach exception handler installed."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Mach exception handler installed."); g_isInstalled = true; return true; failed: - SentryCrashLOG_DEBUG("Failed to install mach exception handler."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Failed to install mach exception handler."); if (attributes_created) { pthread_attr_destroy(&attr); } @@ -560,17 +560,17 @@ addContextualInfoToEvent(struct SentryCrash_MonitorContext *eventContext) } } -#endif // SentryCrashCRASH_HAS_MACH +#endif // SENTRY_HAS_MACH SentryCrashMonitorAPI * sentrycrashcm_machexception_getAPI(void) { static SentryCrashMonitorAPI api = { -#if SentryCrashCRASH_HAS_MACH +#if SENTRY_HAS_MACH .setEnabled = setEnabled, .isEnabled = isEnabled, .addContextualInfoToEvent = addContextualInfoToEvent -#endif // SentryCrashCRASH_HAS_MACH +#endif // SENTRY_HAS_MACH }; return &api; } diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_NSException.m b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_NSException.m index b9a3bdd3f67..bfb298d0f58 100644 --- a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_NSException.m +++ b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_NSException.m @@ -33,7 +33,7 @@ #include "SentryCrashThread.h" #import "SentryDependencyContainer.h" -#import "SentryCrashLogger.h" +#import "SentryLog.h" // ============================================================================ #pragma mark - Globals - @@ -50,7 +50,7 @@ #pragma mark - Callbacks - // ============================================================================ -/** Our custom excepetion handler. +/** Our custom exception handler. * Fetch the stack trace from the exception and write a report. * * @param exception The exception that was raised. @@ -59,14 +59,14 @@ static void handleException(NSException *exception) { - SentryCrashLOG_DEBUG(@"Trapped exception %@", exception); + SENTRY_LOG_DEBUG(@"Trapped exception %@", exception); if (g_isEnabled) { thread_act_array_t threads = NULL; mach_msg_type_number_t numThreads = 0; sentrycrashmc_suspendEnvironment(&threads, &numThreads); sentrycrashcm_notifyFatalExceptionCaptured(false); - SentryCrashLOG_DEBUG(@"Filling out context."); + SENTRY_LOG_DEBUG(@"Filling out context."); NSArray *addresses = [exception callStackReturnAddresses]; NSUInteger numFrames = addresses.count; uintptr_t *callstack = malloc(numFrames * sizeof(*callstack)); @@ -96,12 +96,12 @@ crashContext->crashReason = [[exception reason] UTF8String]; crashContext->stackCursor = &cursor; - SentryCrashLOG_DEBUG(@"Calling main crash handler."); + SENTRY_LOG_DEBUG(@"Calling main crash handler."); sentrycrashcm_handleException(crashContext); free(callstack); if (g_previousUncaughtExceptionHandler != NULL) { - SentryCrashLOG_DEBUG(@"Calling original exception handler."); + SENTRY_LOG_DEBUG(@"Calling original exception handler."); g_previousUncaughtExceptionHandler(exception); } } @@ -123,15 +123,15 @@ if (isEnabled != g_isEnabled) { g_isEnabled = isEnabled; if (isEnabled) { - SentryCrashLOG_DEBUG(@"Backing up original handler."); + SENTRY_LOG_DEBUG(@"Backing up original handler."); g_previousUncaughtExceptionHandler = NSGetUncaughtExceptionHandler(); - SentryCrashLOG_DEBUG(@"Setting new handler."); + SENTRY_LOG_DEBUG(@"Setting new handler."); NSSetUncaughtExceptionHandler(&handleUncaughtException); SentryDependencyContainer.sharedInstance.crashReporter.uncaughtExceptionHandler = &handleUncaughtException; } else { - SentryCrashLOG_DEBUG(@"Restoring original handler."); + SENTRY_LOG_DEBUG(@"Restoring original handler."); NSSetUncaughtExceptionHandler(g_previousUncaughtExceptionHandler); } } diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_Signal.c b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_Signal.c index 32146b496bd..7cfeeb3c94a 100644 --- a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_Signal.c +++ b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_Signal.c @@ -31,11 +31,11 @@ #include "SentryCrashMonitorContext.h" #include "SentryCrashSignalInfo.h" #include "SentryCrashStackCursor_MachineContext.h" -#include "SentryCrashSystemCapabilities.h" +#include "SentryInternalCDefines.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" -#if SentryCrashCRASH_HAS_SIGNAL +#if SENTRY_HAS_SIGNAL # include # include @@ -53,7 +53,7 @@ static bool g_isSigtermReportingEnabled = false; static SentryCrash_MonitorContext g_monitorContext; static SentryCrashStackCursor g_stackCursor; -# if SentryCrashCRASH_HAS_SIGNAL_STACK +# if SENTRY_HAS_SIGNAL_STACK /** Our custom signal stack. The signal handler will use this as its stack. */ static stack_t g_signalStack = { 0 }; # endif @@ -82,14 +82,14 @@ static char g_eventID[37]; static void handleSignal(int sigNum, siginfo_t *signalInfo, void *userContext) { - SentryCrashLOG_DEBUG("Trapped signal %d", sigNum); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Trapped signal %d", sigNum); if (g_isEnabled) { thread_act_array_t threads = NULL; mach_msg_type_number_t numThreads = 0; sentrycrashmc_suspendEnvironment(&threads, &numThreads); sentrycrashcm_notifyFatalExceptionCaptured(false); - SentryCrashLOG_DEBUG("Filling out context."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Filling out context."); SentryCrashMC_NEW_CONTEXT(machineContext); sentrycrashmc_getContextForSignal(userContext, machineContext); sentrycrashsc_initWithMachineContext(&g_stackCursor, MAX_STACKTRACE_LENGTH, machineContext); @@ -110,7 +110,7 @@ handleSignal(int sigNum, siginfo_t *signalInfo, void *userContext) sentrycrashmc_resumeEnvironment(threads, numThreads); } - SentryCrashLOG_DEBUG("Re-raising signal for regular handlers to catch."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Re-raising signal for regular handlers to catch."); // This is technically not allowed, but it works in OSX and iOS. raise(sigNum); } @@ -122,25 +122,25 @@ handleSignal(int sigNum, siginfo_t *signalInfo, void *userContext) static bool installSignalHandler(void) { - SentryCrashLOG_DEBUG("Installing signal handler."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Installing signal handler."); -# if SentryCrashCRASH_HAS_SIGNAL_STACK +# if SENTRY_HAS_SIGNAL_STACK if (g_signalStack.ss_size == 0) { - SentryCrashLOG_DEBUG("Allocating signal stack area."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Allocating signal stack area."); g_signalStack.ss_size = SIGSTKSZ; g_signalStack.ss_sp = malloc(g_signalStack.ss_size); if (g_signalStack.ss_sp == NULL) { - SentryCrashLOG_ERROR( + SENTRY_ASYNC_SAFE_LOG_ERROR( "Failed to allocate signal stack area of size %ul", g_signalStack.ss_size); goto failed; } } - SentryCrashLOG_DEBUG("Setting signal stack area."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Setting signal stack area."); if (sigaltstack(&g_signalStack, NULL) != 0) { - SentryCrashLOG_ERROR("signalstack: %s", strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("signalstack: %s", strerror(errno)); goto failed; } # endif @@ -149,14 +149,14 @@ installSignalHandler(void) int fatalSignalsCount = sentrycrashsignal_numFatalSignals(); if (g_previousSignalHandlers == NULL) { - SentryCrashLOG_DEBUG("Allocating memory to store previous signal handlers."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Allocating memory to store previous signal handlers."); g_previousSignalHandlers = malloc(sizeof(*g_previousSignalHandlers) * (unsigned)fatalSignalsCount); } struct sigaction action = { { 0 } }; action.sa_flags = SA_SIGINFO | SA_ONSTACK; -# if SentryCrashCRASH_HOST_APPLE && defined(__LP64__) +# if SENTRY_HOST_APPLE && defined(__LP64__) action.sa_flags |= SA_64REGSET; # endif sigemptyset(&action.sa_mask); @@ -164,11 +164,11 @@ installSignalHandler(void) for (int i = 0; i < fatalSignalsCount; i++) { if (fatalSignals[i] == SIGTERM && !g_isSigtermReportingEnabled) { - SentryCrashLOG_DEBUG("SIGTERM handling disabled. Skipping assigning handler."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("SIGTERM handling disabled. Skipping assigning handler."); continue; } - SentryCrashLOG_DEBUG("Assigning handler for signal %d", fatalSignals[i]); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Assigning handler for signal %d", fatalSignals[i]); if (sigaction(fatalSignals[i], &action, &g_previousSignalHandlers[i]) != 0) { char sigNameBuff[30]; const char *sigName = sentrycrashsignal_signalName(fatalSignals[i]); @@ -176,7 +176,7 @@ installSignalHandler(void) snprintf(sigNameBuff, sizeof(sigNameBuff), "%d", fatalSignals[i]); sigName = sigNameBuff; } - SentryCrashLOG_ERROR("sigaction (%s): %s", sigName, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("sigaction (%s): %s", sigName, strerror(errno)); // Try to reverse the damage for (i--; i >= 0; i--) { sigaction(fatalSignals[i], &g_previousSignalHandlers[i], NULL); @@ -191,36 +191,36 @@ installSignalHandler(void) } } } - SentryCrashLOG_DEBUG("Signal handlers installed."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Signal handlers installed."); return true; failed: - SentryCrashLOG_DEBUG("Failed to install signal handlers."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Failed to install signal handlers."); return false; } static void uninstallSignalHandler(void) { - SentryCrashLOG_DEBUG("Uninstalling signal handlers."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Uninstalling signal handlers."); const int *fatalSignals = sentrycrashsignal_fatalSignals(); int fatalSignalsCount = sentrycrashsignal_numFatalSignals(); for (int i = 0; i < fatalSignalsCount; i++) { if (fatalSignals[i] == SIGTERM && !g_isSigtermReportingEnabled) { - SentryCrashLOG_DEBUG("SIGTERM handling disabled. Skipping restoring handler."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("SIGTERM handling disabled. Skipping restoring handler."); continue; } - SentryCrashLOG_DEBUG("Restoring original handler for signal %d", fatalSignals[i]); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Restoring original handler for signal %d", fatalSignals[i]); sigaction(fatalSignals[i], &g_previousSignalHandlers[i], NULL); } -# if SentryCrashCRASH_HAS_SIGNAL_STACK +# if SENTRY_HAS_SIGNAL_STACK g_signalStack = (stack_t) { 0 }; # endif - SentryCrashLOG_DEBUG("Signal handlers uninstalled."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Signal handlers uninstalled."); } static void @@ -259,7 +259,7 @@ addContextualInfoToEvent(struct SentryCrash_MonitorContext *eventContext) void sentrycrashcm_setEnableSigtermReporting(bool enabled) { -#if SentryCrashCRASH_HAS_SIGNAL +#if SENTRY_HAS_SIGNAL g_isSigtermReportingEnabled = enabled; #endif } @@ -268,7 +268,7 @@ SentryCrashMonitorAPI * sentrycrashcm_signal_getAPI(void) { static SentryCrashMonitorAPI api = { -#if SentryCrashCRASH_HAS_SIGNAL +#if SENTRY_HAS_SIGNAL .setEnabled = setEnabled, .isEnabled = isEnabled, .addContextualInfoToEvent = addContextualInfoToEvent diff --git a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_System.m b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_System.m index 5e7780a3ca5..72ddd80870b 100644 --- a/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_System.m +++ b/Sources/SentryCrash/Recording/Monitors/SentryCrashMonitor_System.m @@ -32,9 +32,9 @@ #import "SentryCrashDynamicLinker.h" #import "SentryCrashMonitorContext.h" #import "SentryCrashSysCtl.h" -#import "SentryCrashSystemCapabilities.h" +#import "SentryInternalCDefines.h" -#import "SentryCrashLogger.h" +#import "SentryLog.h" #import "SentryDefines.h" @@ -177,14 +177,14 @@ const mach_port_t hostPort = mach_host_self(); if ((kr = host_page_size(hostPort, pageSize)) != KERN_SUCCESS) { - SentryCrashLOG_ERROR(@"host_page_size: %s", mach_error_string(kr)); + SENTRY_LOG_ERROR(@"host_page_size: %s", mach_error_string(kr)); return false; } mach_msg_type_number_t hostSize = sizeof(*vmStats) / sizeof(natural_t); kr = host_statistics(hostPort, HOST_VM_INFO, (host_info_t)vmStats, &hostSize); if (kr != KERN_SUCCESS) { - SentryCrashLOG_ERROR(@"host_statistics: %s", mach_error_string(kr)); + SENTRY_LOG_ERROR(@"host_statistics: %s", mach_error_string(kr)); return false; } @@ -376,7 +376,7 @@ static NSString * getReceiptUrlPath(void) { -#if SentryCrashCRASH_HOST_IOS +#if SENTRY_HOST_IOS return [NSBundle mainBundle].appStoreReceiptURL.path; #endif return nil; @@ -509,15 +509,15 @@ NSDictionary *infoDict = [mainBundle infoDictionary]; const struct mach_header *header = _dyld_get_image_header(0); -#if SentryCrashCRASH_HOST_IOS +#if SENTRY_HOST_IOS g_systemData.systemName = "iOS"; -#elif SentryCrashCRASH_HOST_TV +#elif SENTRY_HOST_TV g_systemData.systemName = "tvOS"; -#elif SentryCrashCRASH_HOST_MAC +#elif SENTRY_HOST_MAC g_systemData.systemName = "macOS"; -#elif SentryCrashCRASH_HOST_WATCH +#elif SENTRY_HOST_WATCH g_systemData.systemName = "watchOS"; -#elif SentryCrashCRASH_HOST_VISION +#elif SENTRY_HOST_VISION g_systemData.systemName = "visionOS"; #else g_systemData.systemName = "unknown"; @@ -543,7 +543,7 @@ g_systemData.model = "simulator"; } else { // TODO: combine this into SentryDevice? -#if SentryCrashCRASH_HOST_MAC +#if SENTRY_HOST_MAC // MacOS has the machine in the model field, and no model g_systemData.machine = stringSysctl("hw.model"); #else diff --git a/Sources/SentryCrash/Recording/SentryCrash.m b/Sources/SentryCrash/Recording/SentryCrash.m index 8b299010b9b..6b7194d71d3 100644 --- a/Sources/SentryCrash/Recording/SentryCrash.m +++ b/Sources/SentryCrash/Recording/SentryCrash.m @@ -36,13 +36,13 @@ #import "SentryCrashNSErrorUtil.h" #import "SentryCrashReportFields.h" #import "SentryCrashReportStore.h" -#import "SentryCrashSystemCapabilities.h" #import "SentryDefines.h" #import "SentryDependencyContainer.h" +#import "SentryInternalCDefines.h" #import "SentryNSNotificationCenterWrapper.h" #import -#import "SentryCrashLogger.h" +#import "SentryLog.h" #if SENTRY_HAS_UIKIT # import @@ -122,7 +122,7 @@ - (void)setUserInfo:(NSDictionary *)userInfo options:SentryCrashJSONEncodeOptionSorted error:&error]); if (error != NULL) { - SentryCrashLOG_ERROR(@"Could not serialize user info: %@", error); + SENTRY_LOG_ERROR(@"Could not serialize user info: %@", error); return; } } @@ -217,8 +217,8 @@ - (NSDictionary *)systemInfo - (BOOL)install { if (self.basePath == nil) { - SentryCrashLOG_ERROR(@"Failed to initialize crash handler. Crash " - @"reporting disabled."); + SENTRY_LOG_ERROR(@"Failed to initialize crash handler. Crash " + @"reporting disabled."); return NO; } @@ -257,7 +257,7 @@ - (BOOL)install selector:@selector(applicationWillTerminate) name:UIApplicationWillTerminateNotification]; #endif // SENTRY_HAS_UIKIT -#if SentryCrashCRASH_HAS_NSEXTENSION +#if SENTRY_HAS_NSEXTENSION SentryNSNotificationCenterWrapper *notificationCenter = SentryDependencyContainer.sharedInstance.notificationCenterWrapper; [notificationCenter addObserver:self @@ -272,7 +272,7 @@ - (BOOL)install [notificationCenter addObserver:self selector:@selector(applicationWillEnterForeground) name:NSExtensionHostWillEnterForegroundNotification]; -#endif // SentryCrashCRASH_HAS_NSEXTENSION +#endif // SENTRY_HAS_NSEXTENSION return true; } @@ -294,7 +294,7 @@ - (void)uninstall [notificationCenter removeObserver:self name:UIApplicationWillEnterForegroundNotification]; [notificationCenter removeObserver:self name:UIApplicationWillTerminateNotification]; #endif // SENTRY_HAS_UIKIT -#if SentryCrashCRASH_HAS_NSEXTENSION +#if SENTRY_HAS_NSEXTENSION SentryNSNotificationCenterWrapper *notificationCenter = SentryDependencyContainer.sharedInstance.notificationCenterWrapper; [notificationCenter removeObserver:self name:NSExtensionHostDidBecomeActiveNotification]; @@ -308,13 +308,13 @@ - (void)sendAllReportsWithCompletion:(SentryCrashReportFilterCompletion)onComple { NSArray *reports = [self allReports]; - SentryCrashLOG_INFO(@"Sending %d crash reports", [reports count]); + SENTRY_LOG_INFO(@"Sending %lu crash reports", (unsigned long)[reports count]); [self sendReports:reports onCompletion:^(NSArray *filteredReports, BOOL completed, NSError *error) { - SentryCrashLOG_DEBUG(@"Process finished with completion: %d", completed); + SENTRY_LOG_DEBUG(@"Process finished with completion: %d", completed); if (error != nil) { - SentryCrashLOG_ERROR(@"Failed to send reports: %@", error); + SENTRY_LOG_ERROR(@"Failed to send reports: %@", error); } if ((self.deleteBehaviorAfterSendAll == SentryCrashCDeleteOnSucess && completed) || self.deleteBehaviorAfterSendAll == SentryCrashCDeleteAlways) { @@ -453,11 +453,11 @@ - (NSDictionary *)reportWithIntID:(int64_t)reportID error:&error]; if (error != nil) { - SentryCrashLOG_ERROR( + SENTRY_LOG_ERROR( @"Encountered error loading crash report %" PRIx64 ": %@", reportID, error); } if (crashReport == nil) { - SentryCrashLOG_ERROR(@"Could not load crash report"); + SENTRY_LOG_ERROR(@"Could not load crash report"); return nil; } diff --git a/Sources/SentryCrash/Recording/SentryCrashC.c b/Sources/SentryCrash/Recording/SentryCrashC.c index a46ee91ef0b..c201a944379 100644 --- a/Sources/SentryCrash/Recording/SentryCrashC.c +++ b/Sources/SentryCrash/Recording/SentryCrashC.c @@ -37,9 +37,9 @@ #include "SentryCrashReportFixer.h" #include "SentryCrashReportStore.h" #include "SentryCrashString.h" -#include "SentryCrashSystemCapabilities.h" +#include "SentryInternalCDefines.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #include #include @@ -53,10 +53,6 @@ /** True if SentryCrash has been installed. */ static volatile bool g_installed = 0; -#if SentryCrashLogger_CBufferSize > 0 -static char g_consoleLogPath[SentryCrashFU_MAX_PATH_LENGTH]; -#endif // SentryCrashLogger_CBufferSize > 0 - static SentryCrashMonitorType g_monitoring = SentryCrashMonitorTypeProductionSafeMinimal; static char g_lastCrashReportFilePath[SentryCrashFU_MAX_PATH_LENGTH]; static void (*g_saveScreenShot)(const char *) = 0; @@ -77,13 +73,9 @@ static void (*g_saveViewHierarchy)(const char *) = 0; static void onCrash(struct SentryCrash_MonitorContext *monitorContext) { - SentryCrashLOG_DEBUG("Updating application state to note crash."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Updating application state to note crash."); sentrycrashstate_notifyAppCrash(); -#if SentryCrashLogger_CBufferSize > 0 - monitorContext->consoleLogPath = g_consoleLogPath; -#endif // SentryCrashLogger_CBufferSize > 0 - if (monitorContext->crashedDuringCrashHandling) { sentrycrashreport_writeRecrashReport(monitorContext, g_lastCrashReportFilePath); } else { @@ -123,10 +115,10 @@ onCrash(struct SentryCrash_MonitorContext *monitorContext) SentryCrashMonitorType sentrycrash_install(const char *appName, const char *const installPath) { - SentryCrashLOG_DEBUG("Installing crash reporter."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Installing crash reporter."); if (g_installed) { - SentryCrashLOG_DEBUG("Crash reporter already installed."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Crash reporter already installed."); return g_monitoring; } g_installed = 1; @@ -141,17 +133,12 @@ sentrycrash_install(const char *appName, const char *const installPath) snprintf(path, sizeof(path), "%s/Data/CrashState.json", installPath); sentrycrashstate_initialize(path); -#if SentryCrashLogger_CBufferSize > 0 - snprintf(g_consoleLogPath, sizeof(g_consoleLogPath), "%s/Data/ConsoleLog.txt", installPath); - sentrycrashlog_setLogFilename(g_consoleLogPath, true); -#endif // SentryCrashLogger_CBufferSize > 0 - sentrycrashccd_init(60); sentrycrashcm_setEventCallback(onCrash); SentryCrashMonitorType monitors = sentrycrash_setMonitoring(g_monitoring); - SentryCrashLOG_DEBUG("Installation complete."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Installation complete."); return monitors; } @@ -252,19 +239,19 @@ char * sentrycrash_readReport(int64_t reportID) { if (reportID <= 0) { - SentryCrashLOG_ERROR("Report ID was %" PRIx64, reportID); + SENTRY_ASYNC_SAFE_LOG_ERROR("Report ID was %" PRIx64, reportID); return NULL; } char *rawReport = sentrycrashcrs_readReport(reportID); if (rawReport == NULL) { - SentryCrashLOG_ERROR("Failed to load report ID %" PRIx64, reportID); + SENTRY_ASYNC_SAFE_LOG_ERROR("Failed to load report ID %" PRIx64, reportID); return NULL; } char *fixedReport = sentrycrashcrf_fixupCrashReport(rawReport); if (fixedReport == NULL) { - SentryCrashLOG_ERROR("Failed to fixup report ID %" PRIx64, reportID); + SENTRY_ASYNC_SAFE_LOG_ERROR("Failed to fixup report ID %" PRIx64, reportID); } free(rawReport); diff --git a/Sources/SentryCrash/Recording/SentryCrashCachedData.c b/Sources/SentryCrash/Recording/SentryCrashCachedData.c index df4c9b5becf..b08133480af 100644 --- a/Sources/SentryCrash/Recording/SentryCrashCachedData.c +++ b/Sources/SentryCrash/Recording/SentryCrashCachedData.c @@ -26,7 +26,7 @@ #include "SentryCrashCachedData.h" #include "SentryInternalCDefines.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #include #include @@ -67,7 +67,7 @@ updateThreadList(void) SENTRY_DISABLE_THREAD_SANITIZER("Known data race to fix") thread_act_array_t threads; kern_return_t kr; if ((kr = task_threads(thisTask, &threads, &allThreadsCount)) != KERN_SUCCESS) { - SentryCrashLOG_ERROR("task_threads: %s", mach_error_string(kr)); + SENTRY_ASYNC_SAFE_LOG_ERROR("task_threads: %s", mach_error_string(kr)); return; } @@ -163,7 +163,7 @@ sentrycrashccd_init(int pollingIntervalInSeconds) int error = pthread_create( &g_cacheThread, &attr, &monitorCachedData, "SentryCrash Cached Data Monitor"); if (error != 0) { - SentryCrashLOG_ERROR("pthread_create_suspended_np: %s", strerror(error)); + SENTRY_ASYNC_SAFE_LOG_ERROR("pthread_create_suspended_np: %s", strerror(error)); } pthread_attr_destroy(&attr); } diff --git a/Sources/SentryCrash/Recording/SentryCrashReport.c b/Sources/SentryCrash/Recording/SentryCrashReport.c index 9c15aa2695a..70afaf60653 100644 --- a/Sources/SentryCrash/Recording/SentryCrashReport.c +++ b/Sources/SentryCrash/Recording/SentryCrashReport.c @@ -43,12 +43,12 @@ #include "SentryCrashStackCursor_Backtrace.h" #include "SentryCrashStackCursor_MachineContext.h" #include "SentryCrashString.h" -#include "SentryCrashSystemCapabilities.h" #include "SentryCrashThread.h" #include "SentryCrashUUIDConversion.h" +#include "SentryInternalCDefines.h" #include "SentryScopeSyncC.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #include #include @@ -151,12 +151,12 @@ addTextFileElement( { const int fd = open(filePath, O_RDONLY); if (fd < 0) { - SentryCrashLOG_ERROR("Could not open file %s: %s", filePath, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not open file %s: %s", filePath, strerror(errno)); return; } if (sentrycrashjson_beginStringElement(getJsonContext(writer), key) != SentryCrashJSON_OK) { - SentryCrashLOG_ERROR("Could not start string element"); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not start string element"); goto done; } @@ -166,7 +166,7 @@ addTextFileElement( bytesRead = (int)read(fd, buffer, sizeof(buffer))) { if (sentrycrashjson_appendStringElement(getJsonContext(writer), buffer, bytesRead) != SentryCrashJSON_OK) { - SentryCrashLOG_ERROR("Could not append string element"); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not append string element"); goto done; } } @@ -583,7 +583,8 @@ writeUnknownObjectContents(const SentryCrashReportWriter *const writer, const ch writeMemoryContents(writer, ivar->name, (uintptr_t)pointer, limit); break; default: - SentryCrashLOG_DEBUG("%s: Unknown ivar type [%s]", ivar->name, ivar->type); + SENTRY_ASYNC_SAFE_LOG_DEBUG( + "%s: Unknown ivar type [%s]", ivar->name, ivar->type); } } } @@ -608,7 +609,6 @@ isRestrictedClass(const char *name) static bool writeObjCObject(const SentryCrashReportWriter *const writer, const uintptr_t address, int *limit) { -#if SentryCrashCRASH_HAS_OBJC const void *object = (const void *)address; switch (sentrycrashobjc_objectType(object)) { case SentryCrashObjCTypeClass: @@ -662,7 +662,6 @@ writeObjCObject(const SentryCrashReportWriter *const writer, const uintptr_t add case SentryCrashObjCTypeUnknown: break; } -#endif return false; } @@ -709,13 +708,11 @@ isValidPointer(const uintptr_t address) return false; } -#if SentryCrashCRASH_HAS_OBJC if (sentrycrashobjc_isTaggedPointer((const void *)address)) { if (!sentrycrashobjc_isValidTaggedPointer((const void *)address)) { return false; } } -#endif return true; } @@ -729,11 +726,9 @@ isNotableAddress(const uintptr_t address) const void *object = (const void *)address; -#if SentryCrashCRASH_HAS_OBJC if (sentrycrashobjc_objectType(object) != SentryCrashObjCTypeUnknown) { return true; } -#endif if (isValidString(object)) { return true; @@ -1075,7 +1070,7 @@ writeThread(const SentryCrashReportWriter *const writer, const char *const key, { bool isCrashedThread = sentrycrashmc_isCrashedContext(machineContext); SentryCrashThread thread = sentrycrashmc_getThreadFromContext(machineContext); - SentryCrashLOG_DEBUG( + SENTRY_ASYNC_SAFE_LOG_DEBUG( "Writing thread %x (index %d). is crashed: %d", thread, threadIndex, isCrashedThread); SentryCrashStackCursor stackCursor; @@ -1137,7 +1132,7 @@ writeAllThreads(const SentryCrashReportWriter *const writer, const char *const k // Fetch info for all threads. writer->beginArray(writer, key); { - SentryCrashLOG_DEBUG("Writing %d threads.", threadCount); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Writing %d threads.", threadCount); for (int i = 0; i < threadCount; i++) { SentryCrashThread thread = sentrycrashmc_getThreadAtIndex(context, i); if (thread == offendingThread) { @@ -1247,7 +1242,7 @@ writeError(const SentryCrashReportWriter *const writer, const char *const key, { writer->beginObject(writer, key); { -#if SentryCrashCRASH_HOST_APPLE +#if SENTRY_HOST_APPLE writer->beginObject(writer, SentryCrashField_Mach); { const char *machExceptionName = sentrycrashmach_exceptionName(crash->mach.type); @@ -1328,7 +1323,7 @@ writeError(const SentryCrashReportWriter *const writer, const char *const key, case SentryCrashMonitorTypeSystem: case SentryCrashMonitorTypeApplicationState: - SentryCrashLOG_ERROR( + SENTRY_ASYNC_SAFE_LOG_ERROR( "Crash monitor type 0x%x shouldn't be able to cause events!", crash->crashType); break; } @@ -1420,7 +1415,7 @@ writeReportInfo(const SentryCrashReportWriter *const writer, const char *const k { writer->beginObject(writer, key); { - writer->addStringElement(writer, SentryCrashField_Version, SentryCrashCRASH_REPORT_VERSION); + writer->addStringElement(writer, SentryCrashField_Version, SENTRY_REPORT_VERSION); writer->addStringElement(writer, SentryCrashField_ID, reportID); writer->addStringElement(writer, SentryCrashField_ProcessName, processName); writer->addIntegerElement(writer, SentryCrashField_Timestamp, time(NULL)); @@ -1481,10 +1476,11 @@ sentrycrashreport_writeRecrashReport( static char tempPath[SentryCrashFU_MAX_PATH_LENGTH]; strncpy(tempPath, path, sizeof(tempPath) - 10); strncpy(tempPath + strlen(tempPath) - 5, ".old", 5); - SentryCrashLOG_INFO("Writing recrash report to %s", path); + SENTRY_ASYNC_SAFE_LOG_INFO("Writing recrash report to %s", path); if (rename(path, tempPath) < 0) { - SentryCrashLOG_ERROR("Could not rename %s to %s: %s", path, tempPath, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "Could not rename %s to %s: %s", path, tempPath, strerror(errno)); } if (!sentrycrashfu_openBufferedWriter( &bufferedWriter, path, writeBuffer, sizeof(writeBuffer))) { @@ -1506,7 +1502,7 @@ sentrycrashreport_writeRecrashReport( writeRecrash(writer, SentryCrashField_RecrashReport, tempPath); sentrycrashfu_flushBufferedWriter(&bufferedWriter); if (remove(tempPath) < 0) { - SentryCrashLOG_ERROR("Could not remove %s: %s", tempPath, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not remove %s: %s", tempPath, strerror(errno)); } writeReportInfo(writer, SentryCrashField_Report, SentryCrashReportType_Minimal, monitorContext->eventID, monitorContext->System.processName); @@ -1596,10 +1592,7 @@ writeDebugInfo(const SentryCrashReportWriter *const writer, const char *const ke { writer->beginObject(writer, key); { - if (monitorContext->consoleLogPath != NULL) { - addTextLinesFromFile( - writer, SentryCrashField_ConsoleLog, monitorContext->consoleLogPath); - } + addTextLinesFromFile(writer, SentryCrashField_ConsoleLog, g_logFilename); } writer->endContainer(writer); } @@ -1668,7 +1661,7 @@ void sentrycrashreport_writeStandardReport( const SentryCrash_MonitorContext *const monitorContext, const char *const path) { - SentryCrashLOG_INFO("Writing crash report to %s", path); + SENTRY_ASYNC_SAFE_LOG_INFO("Writing crash report to %s", path); char writeBuffer[1024]; SentryCrashBufferedWriter bufferedWriter; @@ -1737,7 +1730,7 @@ void sentrycrashreport_setUserInfoJSON(const char *const userInfoJSON) { static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; - SentryCrashLOG_TRACE("set userInfoJSON to %p", userInfoJSON); + SENTRY_ASYNC_SAFE_LOG_TRACE("set userInfoJSON to %p", userInfoJSON); pthread_mutex_lock(&mutex); if (g_userInfoJSON != NULL) { @@ -1769,7 +1762,7 @@ sentrycrashreport_setDoNotIntrospectClasses(const char **doNotIntrospectClasses, newClassesLength = length; newClasses = malloc(sizeof(*newClasses) * (unsigned)newClassesLength); if (newClasses == NULL) { - SentryCrashLOG_ERROR("Could not allocate memory"); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not allocate memory"); return; } diff --git a/Sources/SentryCrash/Recording/SentryCrashReportFixer.c b/Sources/SentryCrash/Recording/SentryCrashReportFixer.c index feccd2b3e1c..0315f7a8bb2 100644 --- a/Sources/SentryCrash/Recording/SentryCrashReportFixer.c +++ b/Sources/SentryCrash/Recording/SentryCrashReportFixer.c @@ -25,11 +25,11 @@ // THE SOFTWARE. // +#include "SentryAsyncSafeLog.h" #include "SentryCrashDate.h" #include "SentryCrashJSONCodec.h" -#include "SentryCrashLogger.h" #include "SentryCrashReportFields.h" -#include "SentryCrashSystemCapabilities.h" +#include "SentryInternalCDefines.h" #include #include @@ -245,7 +245,8 @@ sentrycrashcrf_fixupCrashReport(const char *crashReport) int stringBufferLength = SentryCrashMAX_STRINGBUFFERSIZE; char *stringBuffer = malloc((unsigned)stringBufferLength); if (stringBuffer == NULL) { - SentryCrashLOG_ERROR("Failed to allocate string buffer of size %ul", stringBufferLength); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "Failed to allocate string buffer of size %ul", stringBufferLength); return NULL; } int crashReportLength = (int)strlen(crashReport); @@ -253,7 +254,7 @@ sentrycrashcrf_fixupCrashReport(const char *crashReport) char *fixedReport = malloc((unsigned)fixedReportLength); if (fixedReport == NULL) { free(stringBuffer); - SentryCrashLOG_ERROR( + SENTRY_ASYNC_SAFE_LOG_ERROR( "Failed to allocate fixed report buffer of size %ld", fixedReportLength); return NULL; } @@ -273,7 +274,8 @@ sentrycrashcrf_fixupCrashReport(const char *crashReport) *fixupContext.outputPtr = '\0'; free(stringBuffer); if (result != SentryCrashJSON_OK) { - SentryCrashLOG_ERROR("Could not decode report: %s", sentrycrashjson_stringForError(result)); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "Could not decode report: %s", sentrycrashjson_stringForError(result)); free(fixedReport); return NULL; } diff --git a/Sources/SentryCrash/Recording/SentryCrashReportStore.c b/Sources/SentryCrash/Recording/SentryCrashReportStore.c index f7bba6bb23b..d06ec7c4a07 100644 --- a/Sources/SentryCrash/Recording/SentryCrashReportStore.c +++ b/Sources/SentryCrash/Recording/SentryCrashReportStore.c @@ -26,8 +26,8 @@ // #include "SentryCrashReportStore.h" +#include "SentryAsyncSafeLog.h" #include "SentryCrashFileUtils.h" -#include "SentryCrashLogger.h" #include #include @@ -103,7 +103,7 @@ getReportCount(void) int count = 0; DIR *dir = opendir(g_reportsPath); if (dir == NULL) { - SentryCrashLOG_ERROR("Could not open directory %s", g_reportsPath); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not open directory %s", g_reportsPath); goto done; } struct dirent *ent; @@ -126,7 +126,7 @@ getReportIDs(int64_t *reportIDs, int count) int index = 0; DIR *dir = opendir(g_reportsPath); if (dir == NULL) { - SentryCrashLOG_ERROR("Could not open directory %s", g_reportsPath); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not open directory %s", g_reportsPath); goto done; } @@ -257,16 +257,17 @@ sentrycrashcrs_addUserReport(const char *report, int reportLength) int fd = open(crashReportPath, O_WRONLY | O_CREAT, 0644); if (fd < 0) { - SentryCrashLOG_ERROR("Could not open file %s: %s", crashReportPath, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not open file %s: %s", crashReportPath, strerror(errno)); goto done; } int bytesWritten = (int)write(fd, report, (unsigned)reportLength); if (bytesWritten < 0) { - SentryCrashLOG_ERROR("Could not write to file %s: %s", crashReportPath, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "Could not write to file %s: %s", crashReportPath, strerror(errno)); goto done; } else if (bytesWritten < reportLength) { - SentryCrashLOG_ERROR("Expected to write %d bytes to file %s, but only wrote %d", + SENTRY_ASYNC_SAFE_LOG_ERROR("Expected to write %d bytes to file %s, but only wrote %d", crashReportPath, reportLength, bytesWritten); } diff --git a/Sources/SentryCrash/Recording/SentryCrashReportVersion.h b/Sources/SentryCrash/Recording/SentryCrashReportVersion.h index 4f7e8fe4b8d..ae06cac41c1 100644 --- a/Sources/SentryCrash/Recording/SentryCrashReportVersion.h +++ b/Sources/SentryCrash/Recording/SentryCrashReportVersion.h @@ -28,6 +28,6 @@ #ifndef HDR_SentryCrashReportVersion_h #define HDR_SentryCrashReportVersion_h -#define SentryCrashCRASH_REPORT_VERSION "3.2.0" +#define SENTRY_REPORT_VERSION "3.2.0" #endif /* HDR_SentryCrashReportVersion_h */ diff --git a/Sources/SentryCrash/Recording/SentryCrashSystemCapabilities.h b/Sources/SentryCrash/Recording/SentryCrashSystemCapabilities.h deleted file mode 100644 index 14442ad3304..00000000000 --- a/Sources/SentryCrash/Recording/SentryCrashSystemCapabilities.h +++ /dev/null @@ -1,126 +0,0 @@ -// Adapted from: https://github.com/kstenerud/KSCrash -// -// SentryCrashSystemCapabilities.h -// -// Copyright (c) 2012 Karl Stenerud. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall remain in place -// in this source code. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -#ifndef HDR_SentryCrashSystemCapabilities_h -#define HDR_SentryCrashSystemCapabilities_h - -#ifdef __APPLE__ -# include -# define SentryCrashCRASH_HOST_APPLE 1 -#endif - -#ifdef __ANDROID__ -# define SentryCrashCRASH_HOST_ANDROID 1 -#endif - -#ifndef TARGET_OS_VISION -# define TARGET_OS_VISION 0 -#endif - -#define SentryCrashCRASH_HOST_IOS (SentryCrashCRASH_HOST_APPLE && TARGET_OS_IOS) -#define SentryCrashCRASH_HOST_TV (SentryCrashCRASH_HOST_APPLE && TARGET_OS_TV) -#define SentryCrashCRASH_HOST_WATCH (SentryCrashCRASH_HOST_APPLE && TARGET_OS_WATCH) -#define SentryCrashCRASH_HOST_VISION (SentryCrashCRASH_HOST_APPLE && TARGET_OS_VISION) -#define SentryCrashCRASH_HOST_MAC \ - (SentryCrashCRASH_HOST_APPLE && TARGET_OS_MAC \ - && !(TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH || TARGET_OS_VISION)) - -#if SentryCrashCRASH_HOST_APPLE -# define SentryCrashCRASH_CAN_GET_MAC_ADDRESS 1 -#else -# define SentryCrashCRASH_CAN_GET_MAC_ADDRESS 0 -#endif - -#if SentryCrashCRASH_HOST_APPLE -# define SentryCrashCRASH_HAS_OBJC 1 -# define SentryCrashCRASH_HAS_SWIFT 1 -#else -# define SentryCrashCRASH_HAS_OBJC 0 -# define SentryCrashCRASH_HAS_SWIFT 0 -#endif - -#if SentryCrashCRASH_HOST_APPLE -# define SentryCrashCRASH_HAS_KINFO_PROC 1 -#else -# define SentryCrashCRASH_HAS_KINFO_PROC 0 -#endif - -#if SentryCrashCRASH_HOST_APPLE -# define SentryCrashCRASH_HAS_STRNSTR 1 -#else -# define SentryCrashCRASH_HAS_STRNSTR 0 -#endif - -#if SentryCrashCRASH_HOST_WATCH -# define SentryCrashCRASH_HAS_NSEXTENSION 1 -#else -# define SentryCrashCRASH_HAS_NSEXTENSION 0 -#endif - -#if SentryCrashCRASH_HOST_IOS || SentryCrashCRASH_HOST_MAC || SentryCrashCRASH_HOST_TV -# define SentryCrashCRASH_HAS_ALERTVIEW 1 -#else -# define SentryCrashCRASH_HAS_ALERTVIEW 0 -#endif - -#if SentryCrashCRASH_HOST_MAC -# define SentryCrashCRASH_HAS_NSALERT 1 -#else -# define SentryCrashCRASH_HAS_NSALERT 0 -#endif - -#if SentryCrashCRASH_HOST_IOS || SentryCrashCRASH_HOST_MAC -# define SentryCrashCRASH_HAS_MACH 1 -#else -# define SentryCrashCRASH_HAS_MACH 0 -#endif - -// WatchOS signal is broken as of 3.1 -#if SentryCrashCRASH_HOST_ANDROID || SentryCrashCRASH_HOST_IOS || SentryCrashCRASH_HOST_MAC \ - || SentryCrashCRASH_HOST_TV -# define SentryCrashCRASH_HAS_SIGNAL 1 -#else -# define SentryCrashCRASH_HAS_SIGNAL 0 -#endif - -#if SentryCrashCRASH_HOST_ANDROID || SentryCrashCRASH_HOST_MAC || SentryCrashCRASH_HOST_IOS -# define SentryCrashCRASH_HAS_SIGNAL_STACK 1 -#else -# define SentryCrashCRASH_HAS_SIGNAL_STACK 0 -#endif - -#if SentryCrashCRASH_HOST_MAC || SentryCrashCRASH_HOST_IOS || SentryCrashCRASH_HOST_TV -# define SentryCrashCRASH_HAS_THREADS_API 1 -#else -# define SentryCrashCRASH_HAS_THREADS_API 0 -#endif - -#if SentryCrashCRASH_HOST_MAC || SentryCrashCRASH_HOST_IOS || SentryCrashCRASH_HOST_TV -# define SentryCrashCRASH_HAS_REACHABILITY 1 -#else -# define SentryCrashCRASH_HAS_REACHABILITY 0 -#endif - -#endif // HDR_SentryCrashSystemCapabilities_h diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashCPU.c b/Sources/SentryCrash/Recording/Tools/SentryCrashCPU.c index f7a3f0139e4..eae080cbb46 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashCPU.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashCPU.c @@ -27,12 +27,12 @@ #include "SentryCrashCPU.h" -#include "SentryCrashSystemCapabilities.h" +#include "SentryInternalCDefines.h" #include #include -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" const char * sentrycrashcpu_currentArch(void) @@ -44,18 +44,18 @@ sentrycrashcpu_currentArch(void) return NULL; } -#if SentryCrashCRASH_HAS_THREADS_API +#if SENTRY_HAS_THREADS_API bool sentrycrashcpu_i_fillState(const thread_t thread, const thread_state_t state, const thread_state_flavor_t flavor, const mach_msg_type_number_t stateCount) { - SentryCrashLOG_TRACE("Filling thread state with flavor %x.", flavor); + SENTRY_ASYNC_SAFE_LOG_TRACE("Filling thread state with flavor %x.", flavor); mach_msg_type_number_t stateCountBuff = stateCount; kern_return_t kr; kr = thread_get_state(thread, flavor, state, &stateCountBuff); if (kr != KERN_SUCCESS) { - SentryCrashLOG_ERROR("thread_get_state: %s", mach_error_string(kr)); + SENTRY_ASYNC_SAFE_LOG_ERROR("thread_get_state: %s", mach_error_string(kr)); return false; } return true; diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_arm.c b/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_arm.c index 1b307232d13..0e6626ed29f 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_arm.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_arm.c @@ -33,7 +33,7 @@ # include "SentryCrashMachineContext_Apple.h" # include -# include "SentryCrashLogger.h" +# include "SentryAsyncSafeLog.h" static const char *g_registerNames[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "ip", "sp", "lr", "pc", "cpsr" }; @@ -112,7 +112,7 @@ sentrycrashcpu_registerValue(const SentryCrashMachineContext *const context, con return context->machineContext.__ss.__cpsr; } - SentryCrashLOG_ERROR("Invalid register number: %d", regNumber); + SENTRY_ASYNC_SAFE_LOG_ERROR("Invalid register number: %d", regNumber); return 0; } @@ -128,7 +128,7 @@ sentrycrashcpu_exceptionRegisterName(const int regNumber) if (regNumber < sentrycrashcpu_numExceptionRegisters()) { return g_exceptionRegisterNames[regNumber]; } - SentryCrashLOG_ERROR("Invalid register number: %d", regNumber); + SENTRY_ASYNC_SAFE_LOG_ERROR("Invalid register number: %d", regNumber); return NULL; } @@ -145,7 +145,7 @@ sentrycrashcpu_exceptionRegisterValue( return context->machineContext.__es.__far; } - SentryCrashLOG_ERROR("Invalid register number: %d", regNumber); + SENTRY_ASYNC_SAFE_LOG_ERROR("Invalid register number: %d", regNumber); return 0; } diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_arm64.c b/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_arm64.c index 3eef530df70..d6f5ef4cbd9 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_arm64.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_arm64.c @@ -33,7 +33,7 @@ # include "SentryCrashMachineContext_Apple.h" # include -# include "SentryCrashLogger.h" +# include "SentryAsyncSafeLog.h" # define KSPACStrippingMask_ARM64e 0x0000000fffffffff @@ -133,7 +133,7 @@ sentrycrashcpu_registerValue(const SentryCrashMachineContext *const context, con return context->machineContext.__ss.__cpsr; } - SentryCrashLOG_ERROR("Invalid register number: %d", regNumber); + SENTRY_ASYNC_SAFE_LOG_ERROR("Invalid register number: %d", regNumber); return 0; } @@ -149,7 +149,7 @@ sentrycrashcpu_exceptionRegisterName(const int regNumber) if (regNumber < sentrycrashcpu_numExceptionRegisters()) { return g_exceptionRegisterNames[regNumber]; } - SentryCrashLOG_ERROR("Invalid register number: %d", regNumber); + SENTRY_ASYNC_SAFE_LOG_ERROR("Invalid register number: %d", regNumber); return NULL; } @@ -166,7 +166,7 @@ sentrycrashcpu_exceptionRegisterValue( return context->machineContext.__es.__far; } - SentryCrashLOG_ERROR("Invalid register number: %d", regNumber); + SENTRY_ASYNC_SAFE_LOG_ERROR("Invalid register number: %d", regNumber); return 0; } diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_x86_32.c b/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_x86_32.c index 96a1cf7b355..c3e2496da8a 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_x86_32.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_x86_32.c @@ -33,7 +33,7 @@ # include "SentryCrashMachineContext_Apple.h" # include -# include "SentryCrashLogger.h" +# include "SentryAsyncSafeLog.h" static const char *g_registerNames[] = { "eax", @@ -148,7 +148,7 @@ sentrycrashcpu_registerValue(const SentryCrashMachineContext *const context, con return context->machineContext.__ss.__gs; } - SentryCrashLOG_ERROR("Invalid register number: %d", regNumber); + SENTRY_ASYNC_SAFE_LOG_ERROR("Invalid register number: %d", regNumber); return 0; } @@ -164,7 +164,7 @@ sentrycrashcpu_exceptionRegisterName(const int regNumber) if (regNumber < sentrycrashcpu_numExceptionRegisters()) { return g_exceptionRegisterNames[regNumber]; } - SentryCrashLOG_ERROR("Invalid register number: %d", regNumber); + SENTRY_ASYNC_SAFE_LOG_ERROR("Invalid register number: %d", regNumber); return NULL; } @@ -181,7 +181,7 @@ sentrycrashcpu_exceptionRegisterValue( return context->machineContext.__es.__faultvaddr; } - SentryCrashLOG_ERROR("Invalid register number: %d", regNumber); + SENTRY_ASYNC_SAFE_LOG_ERROR("Invalid register number: %d", regNumber); return 0; } diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_x86_64.c b/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_x86_64.c index 8e8fbff798a..08a294fa840 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_x86_64.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashCPU_x86_64.c @@ -34,7 +34,7 @@ # include -# include "SentryCrashLogger.h" +# include "SentryAsyncSafeLog.h" static const char *g_registerNames[] = { "rax", "rbx", "rcx", "rdx", "rdi", "rsi", "rbp", "rsp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "rip", "rflags", "cs", "fs", "gs" }; @@ -143,7 +143,7 @@ sentrycrashcpu_registerValue(const SentryCrashMachineContext *const context, con return context->machineContext.__ss.__gs; } - SentryCrashLOG_ERROR("Invalid register number: %d", regNumber); + SENTRY_ASYNC_SAFE_LOG_ERROR("Invalid register number: %d", regNumber); return 0; } @@ -159,7 +159,7 @@ sentrycrashcpu_exceptionRegisterName(const int regNumber) if (regNumber < sentrycrashcpu_numExceptionRegisters()) { return g_exceptionRegisterNames[regNumber]; } - SentryCrashLOG_ERROR("Invalid register number: %d", regNumber); + SENTRY_ASYNC_SAFE_LOG_ERROR("Invalid register number: %d", regNumber); return NULL; } @@ -176,7 +176,7 @@ sentrycrashcpu_exceptionRegisterValue( return context->machineContext.__es.__faultvaddr; } - SentryCrashLOG_ERROR("Invalid register number: %d", regNumber); + SENTRY_ASYNC_SAFE_LOG_ERROR("Invalid register number: %d", regNumber); return 0; } diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashDebug.c b/Sources/SentryCrash/Recording/Tools/SentryCrashDebug.c index 270c638aaab..06265e08512 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashDebug.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashDebug.c @@ -27,7 +27,7 @@ #include "SentryCrashDebug.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #include #include @@ -52,7 +52,7 @@ sentrycrashdebug_isBeingTraced(void) int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid() }; if (sysctl(mib, sizeof(mib) / sizeof(*mib), &procInfo, &structSize, NULL, 0) != 0) { - SentryCrashLOG_ERROR("sysctl: %s", strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("sysctl: %s", strerror(errno)); return false; } diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashDynamicLinker.c b/Sources/SentryCrash/Recording/Tools/SentryCrashDynamicLinker.c index 682131019d4..17cb6543372 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashDynamicLinker.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashDynamicLinker.c @@ -33,7 +33,7 @@ #include #include -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #include "SentryCrashMemory.h" #include "SentryCrashPlatformSpecificDefines.h" @@ -303,33 +303,33 @@ getCrashInfo(const struct mach_header *header, SentryCrashBinaryImage *buffer) return; } - SentryCrashLOG_TRACE("Found crash info section in binary: %s", buffer->name); + SENTRY_ASYNC_SAFE_LOG_TRACE("Found crash info section in binary: %s", buffer->name); const unsigned int minimalSize = offsetof(crash_info_t, reserved); // Include message and message2 if (size < minimalSize) { - SentryCrashLOG_TRACE("Skipped reading crash info: section is too small"); + SENTRY_ASYNC_SAFE_LOG_TRACE("Skipped reading crash info: section is too small"); return; } if (!sentrycrashmem_isMemoryReadable(crashInfo, minimalSize)) { - SentryCrashLOG_TRACE("Skipped reading crash info: section memory is not readable"); + SENTRY_ASYNC_SAFE_LOG_TRACE("Skipped reading crash info: section memory is not readable"); return; } if (crashInfo->version != 4 && crashInfo->version != 5) { - SentryCrashLOG_TRACE( + SENTRY_ASYNC_SAFE_LOG_TRACE( "Skipped reading crash info: invalid version '%d'", crashInfo->version); return; } if (crashInfo->message == NULL && crashInfo->message2 == NULL) { - SentryCrashLOG_TRACE("Skipped reading crash info: both messages are null"); + SENTRY_ASYNC_SAFE_LOG_TRACE("Skipped reading crash info: both messages are null"); return; } if (isValidCrashInfoMessage(crashInfo->message)) { - SentryCrashLOG_TRACE("Found first message: %s", crashInfo->message); + SENTRY_ASYNC_SAFE_LOG_TRACE("Found first message: %s", crashInfo->message); buffer->crashInfoMessage = crashInfo->message; } if (isValidCrashInfoMessage(crashInfo->message2)) { - SentryCrashLOG_TRACE("Found second message: %s", crashInfo->message2); + SENTRY_ASYNC_SAFE_LOG_TRACE("Found second message: %s", crashInfo->message2); buffer->crashInfoMessage2 = crashInfo->message2; } } diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashFileUtils.c b/Sources/SentryCrash/Recording/Tools/SentryCrashFileUtils.c index ac9a619e23f..09e583ad45b 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashFileUtils.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashFileUtils.c @@ -27,7 +27,7 @@ #include "SentryCrashFileUtils.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #include #include @@ -73,7 +73,7 @@ dirContentsCount(const char *path) int count = 0; DIR *dir = opendir(path); if (dir == NULL) { - SentryCrashLOG_ERROR("Error reading directory %s: %s", path, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Error reading directory %s: %s", path, strerror(errno)); return 0; } @@ -96,7 +96,7 @@ dirContents(const char *path, char ***entries, int *count) } dir = opendir(path); if (dir == NULL) { - SentryCrashLOG_ERROR("Error reading directory %s: %s", path, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Error reading directory %s: %s", path, strerror(errno)); goto done; } @@ -106,7 +106,7 @@ dirContents(const char *path, char ***entries, int *count) int index = 0; while ((ent = readdir(dir))) { if (index >= entryCount) { - SentryCrashLOG_ERROR("Contents of %s have been mutated", path); + SENTRY_ASYNC_SAFE_LOG_ERROR("Contents of %s have been mutated", path); goto done; } entryList[index] = strdup(ent->d_name); @@ -144,7 +144,7 @@ deletePathContents(const char *path, bool deleteTopLevelPathAlso) { struct stat statStruct = { 0 }; if (stat(path, &statStruct) != 0) { - SentryCrashLOG_ERROR("Could not stat %s: %s", path, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not stat %s: %s", path, strerror(errno)); return false; } if (S_ISDIR(statStruct.st_mode)) { @@ -174,7 +174,7 @@ deletePathContents(const char *path, bool deleteTopLevelPathAlso) } else if (S_ISREG(statStruct.st_mode)) { sentrycrashfu_removeFile(path, false); } else { - SentryCrashLOG_ERROR("Could not delete %s: Not a regular file.", path); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not delete %s: Not a regular file.", path); return false; } return true; @@ -202,7 +202,7 @@ sentrycrashfu_writeBytesToFD(const int fd, const char *const bytes, int length) while (length > 0) { int bytesWritten = (int)write(fd, pos, (unsigned)length); if (bytesWritten == -1) { - SentryCrashLOG_ERROR("Could not write to fd %d: %s", fd, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not write to fd %d: %s", fd, strerror(errno)); return false; } length -= bytesWritten; @@ -218,7 +218,7 @@ sentrycrashfu_readBytesFromFD(const int fd, char *const bytes, int length) while (length > 0) { int bytesRead = (int)read(fd, pos, (unsigned)length); if (bytesRead == -1) { - SentryCrashLOG_ERROR("Could not write to fd %d: %s", fd, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not write to fd %d: %s", fd, strerror(errno)); return false; } length -= bytesRead; @@ -238,13 +238,13 @@ sentrycrashfu_readEntireFile(const char *const path, char **data, int *length, i struct stat st; if (stat(path, &st) < 0) { - SentryCrashLOG_ERROR("Could not stat %s: %s", path, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not stat %s: %s", path, strerror(errno)); goto done; } fd = open(path, O_RDONLY); if (fd < 0) { - SentryCrashLOG_ERROR("Could not open %s: %s", path, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not open %s: %s", path, strerror(errno)); goto done; } @@ -252,7 +252,7 @@ sentrycrashfu_readEntireFile(const char *const path, char **data, int *length, i bytesToRead = (int)st.st_size; } else if (bytesToRead > 0) { if (lseek(fd, -bytesToRead, SEEK_END) < 0) { - SentryCrashLOG_ERROR( + SENTRY_ASYNC_SAFE_LOG_ERROR( "Could not seek to %d from end of %s: %s", -bytesToRead, path, strerror(errno)); goto done; } @@ -260,7 +260,7 @@ sentrycrashfu_readEntireFile(const char *const path, char **data, int *length, i mem = malloc((unsigned)bytesToRead + 1); if (mem == NULL) { - SentryCrashLOG_ERROR("Out of memory"); + SENTRY_ASYNC_SAFE_LOG_ERROR("Out of memory"); goto done; } @@ -298,7 +298,7 @@ sentrycrashfu_writeStringToFD(const int fd, const char *const string) while (bytesToWrite > 0) { int bytesWritten = (int)write(fd, pos, (unsigned)bytesToWrite); if (bytesWritten == -1) { - SentryCrashLOG_ERROR("Could not write to fd %d: %s", fd, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not write to fd %d: %s", fd, strerror(errno)); return false; } bytesToWrite -= bytesWritten; @@ -342,7 +342,7 @@ sentrycrashfu_readLineFromFD(const int fd, char *const buffer, const int maxLeng for (ch = buffer; ch < end; ch++) { int bytesRead = (int)read(fd, ch, 1); if (bytesRead < 0) { - SentryCrashLOG_ERROR("Could not read from fd %d: %s", fd, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not read from fd %d: %s", fd, strerror(errno)); return -1; } else if (bytesRead == 0 || *ch == '\n') { break; @@ -361,7 +361,7 @@ sentrycrashfu_makePath(const char *absolutePath) if (*ptr == '/') { *ptr = '\0'; if (mkdir(pathCopy, S_IRWXU) < 0 && errno != EEXIST) { - SentryCrashLOG_ERROR( + SENTRY_ASYNC_SAFE_LOG_ERROR( "Could not create directory %s: %s", pathCopy, strerror(errno)); goto done; } @@ -369,7 +369,7 @@ sentrycrashfu_makePath(const char *absolutePath) } } if (mkdir(pathCopy, S_IRWXU) < 0 && errno != EEXIST) { - SentryCrashLOG_ERROR("Could not create directory %s: %s", pathCopy, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not create directory %s: %s", pathCopy, strerror(errno)); goto done; } isSuccessful = true; @@ -384,7 +384,7 @@ sentrycrashfu_removeFile(const char *path, bool mustExist) { if (remove(path) < 0) { if (mustExist || errno != ENOENT) { - SentryCrashLOG_ERROR("Could not delete %s: %s", path, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not delete %s: %s", path, strerror(errno)); } return false; } @@ -410,7 +410,8 @@ sentrycrashfu_openBufferedWriter(SentryCrashBufferedWriter *writer, const char * writer->position = 0; writer->fd = open(path, O_RDWR | O_CREAT | O_EXCL, 0644); if (writer->fd < 0) { - SentryCrashLOG_ERROR("Could not open crash report file %s: %s", path, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "Could not open crash report file %s: %s", path, strerror(errno)); return false; } return true; @@ -474,7 +475,7 @@ fillReadBuffer(SentryCrashBufferedReader *reader) } int bytesRead = (int)read(reader->fd, reader->buffer + reader->dataEndPos, (size_t)bytesToRead); if (bytesRead < 0) { - SentryCrashLOG_ERROR("Could not read: %s", strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not read: %s", strerror(errno)); return false; } else { reader->dataEndPos += bytesRead; @@ -564,7 +565,7 @@ sentrycrashfu_openBufferedReader(SentryCrashBufferedReader *reader, const char * reader->dataEndPos = 0; reader->fd = open(path, O_RDONLY); if (reader->fd < 0) { - SentryCrashLOG_ERROR("Could not open file %s: %s", path, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR("Could not open file %s: %s", path, strerror(errno)); return false; } fillReadBuffer(reader); diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashJSONCodec.c b/Sources/SentryCrash/Recording/Tools/SentryCrashJSONCodec.c index 8f9f8197b7d..9bdc5d11019 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashJSONCodec.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashJSONCodec.c @@ -41,16 +41,16 @@ #pragma mark - Configuration - // ============================================================================ -/** Set to 1 if you're also compiling SentryCrashLogger and want to use it here +/** Set to 1 if you're also compiling SentryAsyncSafeLog and want to use it here */ #ifndef SentryCrashJSONCODEC_UseKSLogger # define SentryCrashJSONCODEC_UseKSLogger 1 #endif #if SentryCrashJSONCODEC_UseKSLogger -# include "SentryCrashLogger.h" +# include "SentryAsyncSafeLog.h" #else -# define SentryCrashLOG_DEBUG(FMT, ...) +# define SENTRY_ASYNC_SAFE_LOG_DEBUG(FMT, ...) #endif /** The work buffer size to use when escaping string values. @@ -164,7 +164,7 @@ appendEscapedString( default: unlikely_if((unsigned char)*src < ' ') { - SentryCrashLOG_DEBUG("Invalid character 0x%02x in string: %s", *src, string); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Invalid character 0x%02x in string: %s", *src, string); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } *dst++ = *src; @@ -264,7 +264,7 @@ sentrycrashjson_beginElement(SentryCrashJSONEncodeContext *const context, const if (context->isObject[context->containerLevel]) { unlikely_if(name == NULL) { - SentryCrashLOG_DEBUG("Name was null inside an object"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Name was null inside an object"); return SentryCrashJSON_ERROR_INVALID_DATA; } unlikely_if((result = addQuotedEscapedString(context, name, (int)strlen(name))) @@ -917,7 +917,7 @@ writeUTF8(unsigned int character, char **dst) } // If we get here, the character cannot be converted to valid UTF-8. - SentryCrashLOG_DEBUG("Invalid unicode: 0x%04x", character); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Invalid unicode: 0x%04x", character); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } @@ -927,7 +927,7 @@ decodeString(SentryCrashJSONDecodeContext *context, char *dstBuffer, int dstBuff *dstBuffer = '\0'; unlikely_if(*context->bufferPtr != '\"') { - SentryCrashLOG_DEBUG("Expected '\"' but got '%c'", *context->bufferPtr); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Expected '\"' but got '%c'", *context->bufferPtr); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } @@ -943,14 +943,14 @@ decodeString(SentryCrashJSONDecodeContext *context, char *dstBuffer, int dstBuff } unlikely_if(src >= context->bufferEnd) { - SentryCrashLOG_DEBUG("Premature end of data"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Premature end of data"); return SentryCrashJSON_ERROR_INCOMPLETE; } const char *srcEnd = src; src = context->bufferPtr + 1; int length = (int)(srcEnd - src); if (length >= dstBufferLength) { - SentryCrashLOG_DEBUG("String is too long"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("String is too long"); return SentryCrashJSON_ERROR_DATA_TOO_LONG; } @@ -999,14 +999,14 @@ decodeString(SentryCrashJSONDecodeContext *context, char *dstBuffer, int dstBuff case 'u': { unlikely_if(src + 5 > srcEnd) { - SentryCrashLOG_DEBUG("Premature end of data"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Premature end of data"); return SentryCrashJSON_ERROR_INCOMPLETE; } unsigned int accum = g_hexConversion[src[1]] << 12 | g_hexConversion[src[2]] << 8 | g_hexConversion[src[3]] << 4 | g_hexConversion[src[4]]; unlikely_if(accum > 0xffff) { - SentryCrashLOG_DEBUG( + SENTRY_ASYNC_SAFE_LOG_DEBUG( "Invalid unicode sequence: %c%c%c%c", src[1], src[2], src[3], src[4]); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } @@ -1014,7 +1014,7 @@ decodeString(SentryCrashJSONDecodeContext *context, char *dstBuffer, int dstBuff // UTF-16 Trail surrogate on its own. unlikely_if(accum >= 0xdc00 && accum <= 0xdfff) { - SentryCrashLOG_DEBUG("Unexpected trail surrogate: 0x%04x", accum); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Unexpected trail surrogate: 0x%04x", accum); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } @@ -1024,12 +1024,13 @@ decodeString(SentryCrashJSONDecodeContext *context, char *dstBuffer, int dstBuff // Fetch trail surrogate. unlikely_if(src + 11 > srcEnd) { - SentryCrashLOG_DEBUG("Premature end of data"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Premature end of data"); return SentryCrashJSON_ERROR_INCOMPLETE; } unlikely_if(src[5] != '\\' || src[6] != 'u') { - SentryCrashLOG_DEBUG("Expected \"\\u\" but got: \"%c%c\"", src[5], src[6]); + SENTRY_ASYNC_SAFE_LOG_DEBUG( + "Expected \"\\u\" but got: \"%c%c\"", src[5], src[6]); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } src += 6; @@ -1038,7 +1039,7 @@ decodeString(SentryCrashJSONDecodeContext *context, char *dstBuffer, int dstBuff | g_hexConversion[src[4]]; unlikely_if(accum2 < 0xdc00 || accum2 > 0xdfff) { - SentryCrashLOG_DEBUG("Invalid trail surrogate: 0x%04x", accum2); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Invalid trail surrogate: 0x%04x", accum2); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } // And combine 20 bit result. @@ -1051,7 +1052,7 @@ decodeString(SentryCrashJSONDecodeContext *context, char *dstBuffer, int dstBuff continue; } default: - SentryCrashLOG_DEBUG("Invalid control character '%c'", *src); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Invalid control character '%c'", *src); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } } @@ -1067,7 +1068,7 @@ decodeElement(const char *const name, SentryCrashJSONDecodeContext *context) SKIP_WHITESPACE(context); unlikely_if(context->bufferPtr >= context->bufferEnd) { - SentryCrashLOG_DEBUG("Premature end of data"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Premature end of data"); return SentryCrashJSON_ERROR_INCOMPLETE; } @@ -1093,7 +1094,7 @@ decodeElement(const char *const name, SentryCrashJSONDecodeContext *context) unlikely_if(context->bufferPtr >= context->bufferEnd) { break; } likely_if(*context->bufferPtr == ',') { context->bufferPtr++; } } - SentryCrashLOG_DEBUG("Premature end of data"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Premature end of data"); return SentryCrashJSON_ERROR_INCOMPLETE; } case '{': { @@ -1114,7 +1115,7 @@ decodeElement(const char *const name, SentryCrashJSONDecodeContext *context) unlikely_if(context->bufferPtr >= context->bufferEnd) { break; } unlikely_if(*context->bufferPtr != ':') { - SentryCrashLOG_DEBUG("Expected ':' but got '%c'", *context->bufferPtr); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Expected ':' but got '%c'", *context->bufferPtr); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } context->bufferPtr++; @@ -1125,7 +1126,7 @@ decodeElement(const char *const name, SentryCrashJSONDecodeContext *context) unlikely_if(context->bufferPtr >= context->bufferEnd) { break; } likely_if(*context->bufferPtr == ',') { context->bufferPtr++; } } - SentryCrashLOG_DEBUG("Premature end of data"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Premature end of data"); return SentryCrashJSON_ERROR_INCOMPLETE; } case '\"': { @@ -1138,14 +1139,15 @@ decodeElement(const char *const name, SentryCrashJSONDecodeContext *context) case 'f': { unlikely_if(context->bufferEnd - context->bufferPtr < 5) { - SentryCrashLOG_DEBUG("Premature end of data"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Premature end of data"); return SentryCrashJSON_ERROR_INCOMPLETE; } unlikely_if(!(context->bufferPtr[1] == 'a' && context->bufferPtr[2] == 'l' && context->bufferPtr[3] == 's' && context->bufferPtr[4] == 'e')) { - SentryCrashLOG_DEBUG("Expected \"false\" but got \"f%c%c%c%c\"", context->bufferPtr[1], - context->bufferPtr[2], context->bufferPtr[3], context->bufferPtr[4]); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Expected \"false\" but got \"f%c%c%c%c\"", + context->bufferPtr[1], context->bufferPtr[2], context->bufferPtr[3], + context->bufferPtr[4]); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } context->bufferPtr += 5; @@ -1154,14 +1156,14 @@ decodeElement(const char *const name, SentryCrashJSONDecodeContext *context) case 't': { unlikely_if(context->bufferEnd - context->bufferPtr < 4) { - SentryCrashLOG_DEBUG("Premature end of data"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Premature end of data"); return SentryCrashJSON_ERROR_INCOMPLETE; } unlikely_if(!(context->bufferPtr[1] == 'r' && context->bufferPtr[2] == 'u' && context->bufferPtr[3] == 'e')) { - SentryCrashLOG_DEBUG("Expected \"true\" but got \"t%c%c%c\"", context->bufferPtr[1], - context->bufferPtr[2], context->bufferPtr[3]); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Expected \"true\" but got \"t%c%c%c\"", + context->bufferPtr[1], context->bufferPtr[2], context->bufferPtr[3]); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } context->bufferPtr += 4; @@ -1170,14 +1172,14 @@ decodeElement(const char *const name, SentryCrashJSONDecodeContext *context) case 'n': { unlikely_if(context->bufferEnd - context->bufferPtr < 4) { - SentryCrashLOG_DEBUG("Premature end of data"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Premature end of data"); return SentryCrashJSON_ERROR_INCOMPLETE; } unlikely_if(!(context->bufferPtr[1] == 'u' && context->bufferPtr[2] == 'l' && context->bufferPtr[3] == 'l')) { - SentryCrashLOG_DEBUG("Expected \"null\" but got \"n%c%c%c\"", context->bufferPtr[1], - context->bufferPtr[2], context->bufferPtr[3]); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Expected \"null\" but got \"n%c%c%c\"", + context->bufferPtr[1], context->bufferPtr[2], context->bufferPtr[3]); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } context->bufferPtr += 4; @@ -1188,7 +1190,7 @@ decodeElement(const char *const name, SentryCrashJSONDecodeContext *context) context->bufferPtr++; unlikely_if(!isdigit(*context->bufferPtr)) { - SentryCrashLOG_DEBUG("Not a digit: '%c'", *context->bufferPtr); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Not a digit: '%c'", *context->bufferPtr); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } // Fall through @@ -1218,7 +1220,7 @@ decodeElement(const char *const name, SentryCrashJSONDecodeContext *context) unlikely_if(context->bufferPtr >= context->bufferEnd) { - SentryCrashLOG_DEBUG("Premature end of data"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Premature end of data"); return SentryCrashJSON_ERROR_INCOMPLETE; } @@ -1241,7 +1243,7 @@ decodeElement(const char *const name, SentryCrashJSONDecodeContext *context) unlikely_if(context->bufferPtr >= context->bufferEnd) { - SentryCrashLOG_DEBUG("Premature end of data"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Premature end of data"); return SentryCrashJSON_ERROR_INCOMPLETE; } @@ -1251,7 +1253,7 @@ decodeElement(const char *const name, SentryCrashJSONDecodeContext *context) double value; int len = (int)(context->bufferPtr - start); if (len >= context->stringBufferLength) { - SentryCrashLOG_DEBUG("Number is too long."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Number is too long."); return SentryCrashJSON_ERROR_DATA_TOO_LONG; } strncpy(context->stringBuffer, start, len); @@ -1263,7 +1265,7 @@ decodeElement(const char *const name, SentryCrashJSONDecodeContext *context) return context->callbacks->onFloatingPointElement(name, value, context->userData); } } - SentryCrashLOG_DEBUG("Invalid character '%c'", *context->bufferPtr); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Invalid character '%c'", *context->bufferPtr); return SentryCrashJSON_ERROR_INVALID_CHARACTER; } @@ -1335,7 +1337,7 @@ updateDecoder_readFile(struct JSONFromFileContext *context) unlikely_if(bytesRead < fillLength) { if (bytesRead < 0) { - SentryCrashLOG_ERROR( + SENTRY_ASYNC_SAFE_LOG_ERROR( "Error reading file %s: %s", context->sourceFilename, strerror(errno)); } context->isEOF = true; diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashLogger.c b/Sources/SentryCrash/Recording/Tools/SentryCrashLogger.c deleted file mode 100644 index a24237f3807..00000000000 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashLogger.c +++ /dev/null @@ -1,282 +0,0 @@ -// Adapted from: https://github.com/kstenerud/KSCrash -// -// SentryCrashLogger.c -// -// Created by Karl Stenerud on 11-06-25. -// -// Copyright (c) 2011 Karl Stenerud. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall remain in place -// in this source code. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -#include "SentryCrashLogger.h" -#include "SentryCrashSystemCapabilities.h" - -// =========================================================================== -#pragma mark - Common - -// =========================================================================== - -#include -#include -#include -#include -#include -#include - -// Compiler hints for "if" statements -#define likely_if(x) if (__builtin_expect(x, 1)) -#define unlikely_if(x) if (__builtin_expect(x, 0)) - -/** Where console logs will be written */ -static char g_logFilename[1024]; - -/** Write a formatted string to the log. - * - * @param fmt The format string, followed by its arguments. - */ -static void writeFmtToLog(const char *fmt, ...); - -/** Write a formatted string to the log using a vararg list. - * - * @param fmt The format string. - * - * @param args The variable arguments. - */ -static void writeFmtArgsToLog(const char *fmt, va_list args); - -/** Flush the log stream. - */ -static void flushLog(void); - -static inline const char * -lastPathEntry(const char *const path) -{ - const char *lastFile = strrchr(path, '/'); - return lastFile == 0 ? path : lastFile + 1; -} - -static inline void -writeFmtToLog(const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - writeFmtArgsToLog(fmt, args); - va_end(args); -} - -#if SentryCrashLogger_CBufferSize > 0 - -/** The file descriptor where log entries get written. */ -static int g_fd = -1; - -static void -writeToLog(const char *const str) -{ - if (g_fd >= 0) { - int bytesToWrite = (int)strlen(str); - const char *pos = str; - while (bytesToWrite > 0) { - int bytesWritten = (int)write(g_fd, pos, (unsigned)bytesToWrite); - unlikely_if(bytesWritten == -1) { break; } - bytesToWrite -= bytesWritten; - pos += bytesWritten; - } - } - write(STDOUT_FILENO, str, strlen(str)); -} - -static inline void -writeFmtArgsToLog(const char *fmt, va_list args) -{ - unlikely_if(fmt == NULL) { writeToLog("(null)"); } - else - { - char buffer[SentryCrashLogger_CBufferSize]; - vsnprintf(buffer, sizeof(buffer), fmt, args); - writeToLog(buffer); - } -} - -static inline void -flushLog(void) -{ - // Nothing to do. -} - -static inline void -setLogFD(int fd) -{ - if (g_fd >= 0 && g_fd != STDOUT_FILENO && g_fd != STDERR_FILENO && g_fd != STDIN_FILENO) { - close(g_fd); - } - g_fd = fd; -} - -bool -sentrycrashlog_setLogFilename(const char *filename, bool overwrite) -{ - static int fd = -1; - if (filename != NULL) { - int openMask = O_WRONLY | O_CREAT; - if (overwrite) { - openMask |= O_TRUNC; - } - fd = open(filename, openMask, 0644); - unlikely_if(fd < 0) - { - writeFmtToLog("SentryCrashLogger: Could not open %s: %s", filename, strerror(errno)); - return false; - } - if (filename != g_logFilename) { - strncpy(g_logFilename, filename, sizeof(g_logFilename)); - } - } - - setLogFD(fd); - return true; -} - -#else // if SentryCrashLogger_CBufferSize <= 0 - -static FILE *g_file = NULL; - -static inline void -setLogFD(FILE *file) -{ - if (g_file != NULL && g_file != stdout && g_file != stderr && g_file != stdin) { - fclose(g_file); - } - g_file = file; -} - -void -writeToLog(const char *const str) -{ - if (g_file != NULL) { - fprintf(g_file, "%s", str); - } - fprintf(stdout, "%s", str); -} - -static inline void -writeFmtArgsToLog(const char *fmt, va_list args) -{ - unlikely_if(g_file == NULL) { g_file = stdout; } - - if (fmt == NULL) { - writeToLog("(null)"); - } else { - vfprintf(g_file, fmt, args); - } -} - -static inline void -flushLog(void) -{ - fflush(g_file); -} - -#endif // if SentryCrashLogger_CBufferSize <= 0 - -// =========================================================================== -#pragma mark - C - -// =========================================================================== - -void -i_sentrycrashlog_logCBasic(const char *const fmt, ...) -{ - va_list args; - va_start(args, fmt); - writeFmtArgsToLog(fmt, args); - va_end(args); - writeToLog("\n"); - flushLog(); -} - -void -i_sentrycrashlog_logC(const char *const level, const char *const file, const int line, - const char *const function, const char *const fmt, ...) -{ - writeFmtToLog("%s: %s (%u): %s: ", level, lastPathEntry(file), line, function); - va_list args; - va_start(args, fmt); - writeFmtArgsToLog(fmt, args); - va_end(args); - writeToLog("\n"); - flushLog(); -} - -// =========================================================================== -#pragma mark - Objective-C - -// =========================================================================== - -#if SentryCrashCRASH_HAS_OBJC -# include - -void -i_sentrycrashlog_logObjCBasic(CFStringRef fmt, ...) -{ - if (fmt == NULL) { - writeToLog("(null)"); - return; - } - - va_list args; - va_start(args, fmt); - CFStringRef entry = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, args); - va_end(args); - - int bufferLength = (int)CFStringGetLength(entry) * 4 + 1; - char *stringBuffer = malloc((unsigned)bufferLength); - if (stringBuffer != NULL - && CFStringGetCString(entry, stringBuffer, (CFIndex)bufferLength, kCFStringEncodingUTF8)) { - writeToLog(stringBuffer); - } else { - writeToLog("Could not convert log string to UTF-8. No logging performed."); - } - writeToLog("\n"); - - if (stringBuffer != NULL) { - free(stringBuffer); - } - CFRelease(entry); -} - -void -i_sentrycrashlog_logObjC(const char *const level, const char *const file, const int line, - const char *const function, CFStringRef fmt, ...) -{ - CFStringRef logFmt = NULL; - if (fmt == NULL) { - logFmt = CFStringCreateWithCString(NULL, "%s: %s (%u): %s: (null)", kCFStringEncodingUTF8); - i_sentrycrashlog_logObjCBasic(logFmt, level, lastPathEntry(file), line, function); - } else { - va_list args; - va_start(args, fmt); - CFStringRef entry = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, args); - va_end(args); - - logFmt = CFStringCreateWithCString(NULL, "%s: %s (%u): %s: %@", kCFStringEncodingUTF8); - i_sentrycrashlog_logObjCBasic(logFmt, level, lastPathEntry(file), line, function, entry); - - CFRelease(entry); - } - CFRelease(logFmt); -} -#endif // SentryCrashCRASH_HAS_OBJC diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashLogger.h b/Sources/SentryCrash/Recording/Tools/SentryCrashLogger.h deleted file mode 100644 index 38a92d1e385..00000000000 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashLogger.h +++ /dev/null @@ -1,387 +0,0 @@ -// Adapted from: https://github.com/kstenerud/KSCrash -// -// SentryCrashLogger.h -// -// Created by Karl Stenerud on 11-06-25. -// -// Copyright (c) 2011 Karl Stenerud. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall remain in place -// in this source code. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -/** - * SentryCrashLogger - * ======== - * - * Prints log entries to the console consisting of: - * - Level (Error, Warn, Info, Debug, Trace) - * - File - * - Line - * - Function - * - Message - * - * Allows setting the minimum logging level in the preprocessor. - * - * Works in C or Objective-C contexts, with or without ARC, using CLANG or GCC. - * - * - * ===== - * USAGE - * ===== - * - * Set the log level in your "Preprocessor Macros" build setting. You may choose - * TRACE, DEBUG, INFO, WARN, ERROR. If nothing is set, it defaults to ERROR. - * - * Example: SentryCrashLogger_Level=WARN - * - * Anything below the level specified for SentryCrashLogger_Level will not be - * compiled or printed. - * - * - * Next, include the header file: - * - * #include "SentryCrashLogger.h" - * - * - * Next, call the logger functions from your code (using objective-c strings - * in objective-C files and regular strings in regular C files): - * - * Code: - * SentryCrashLOG_ERROR(@"Some error message"); - * - * Prints: - * 2011-07-16 05:41:01.379 TestApp[4439:f803] ERROR: SomeClass.m (21): - * -[SomeFunction]: Some error message - * - * Code: - * SentryCrashLOG_INFO(@"Info about %@", someObject); - * - * Prints: - * 2011-07-16 05:44:05.239 TestApp[4473:f803] INFO : SomeClass.m (20): - * -[SomeFunction]: Info about - * - * - * The "BASIC" versions of the macros behave exactly like NSLog() or printf(), - * except they respect the SentryCrashLogger_Level setting: - * - * Code: - * SentryCrashLOGBASIC_ERROR(@"A basic log entry"); - * - * Prints: - * 2011-07-16 05:44:05.916 TestApp[4473:f803] A basic log entry - * - * - * NOTE: In C files, use "" instead of @"" in the format field. Logging calls - * in C files do not print the NSLog preamble: - * - * Objective-C version: - * SentryCrashLOG_ERROR(@"Some error message"); - * - * 2011-07-16 05:41:01.379 TestApp[4439:f803] ERROR: SomeClass.m (21): - * -[SomeFunction]: Some error message - * - * C version: - * SentryCrashLOG_ERROR("Some error message"); - * - * ERROR: SomeClass.c (21): SomeFunction(): Some error message - * - * - * ============= - * LOCAL LOGGING - * ============= - * - * You can control logging messages at the local file level using the - * "SentryCrashLogger_LocalLevel" define. Note that it must be defined BEFORE - * including SentryCrashLogger.h - * - * The SentryCrashLOG_XX() and SentryCrashLOGBASIC_XX() macros will print out - * based on the LOWER of SentryCrashLogger_Level and - * SentryCrashLogger_LocalLevel, so if SentryCrashLogger_Level is DEBUG and - * SentryCrashLogger_LocalLevel is TRACE, it will print all the way down to the - * trace level for the local file where SentryCrashLogger_LocalLevel was - * defined, and to the debug level everywhere else. - * - * Example: - * - * // SentryCrashLogger_LocalLevel, if defined, MUST come BEFORE including - * SentryCrashLogger.h #define SentryCrashLogger_LocalLevel TRACE #import - * "SentryCrashLogger.h" - * - * - * =============== - * IMPORTANT NOTES - * =============== - * - * The C logger changes its behavior depending on the value of the preprocessor - * define @c SentryCrashLogger_CBufferSize. - * - * If @c SentryCrashLogger_CBufferSize is > 0, the C logger will behave in an - * async-safe manner, calling write() instead of printf(). Any log messages that - * exceed the length specified by SentryCrashLogger_CBufferSize will be - * truncated. - * - * If @c SentryCrashLogger_CBufferSize == 0, the C logger will use printf(), and - * there will be no limit on the log message length. - * - * @c SentryCrashLogger_CBufferSize can only be set as a preprocessor define, and - * will default to 1024 if not specified during compilation. - */ - -/** The buffer size to use when writing log entries. - * - * If this value is > 0, any log entries that expand beyond this length will - * be truncated. - * If this value = 0, the logging system will dynamically allocate memory - * and never truncate. However, the log functions won't be async-safe. - * - * Unless you're logging from within signal handlers, it's safe to set it to 0. - */ -#ifndef SentryCrashLogger_CBufferSize -#define SentryCrashLogger_CBufferSize 1024 -#endif - -// ============================================================================ -#pragma mark - (internal) - -// ============================================================================ - -#ifndef HDR_SentryCrashLogger_h -#define HDR_SentryCrashLogger_h - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -#ifdef __OBJC__ - -# import - -void i_sentrycrashlog_logObjC( - const char *level, const char *file, int line, const char *function, CFStringRef fmt, ...); - -void i_sentrycrashlog_logObjCBasic(CFStringRef fmt, ...); - -# define i_SentryCrashLOG_FULL(LEVEL, FILE, LINE, FUNCTION, FMT, ...) \ - i_sentrycrashlog_logObjC( \ - LEVEL, FILE, LINE, FUNCTION, (__bridge CFStringRef)FMT, ##__VA_ARGS__) -# define i_SentryCrashLOG_BASIC(FMT, ...) \ - i_sentrycrashlog_logObjCBasic((__bridge CFStringRef)FMT, ##__VA_ARGS__) - -#else // __OBJC__ - -void i_sentrycrashlog_logC( - const char *level, const char *file, int line, const char *function, const char *fmt, ...); - -void i_sentrycrashlog_logCBasic(const char *fmt, ...); - -# define i_SentryCrashLOG_FULL i_sentrycrashlog_logC -# define i_SentryCrashLOG_BASIC i_sentrycrashlog_logCBasic - -#endif // __OBJC__ - -/* Back up any existing defines by the same name */ -#ifdef SentryCrash_NONE -# define SentryCrashLOG_BAK_NONE SentryCrash_NONE -# undef SentryCrash_NONE -#endif -#ifdef ERROR -# define SentryCrashLOG_BAK_ERROR ERROR -# undef ERROR -#endif -#ifdef WARN -# define SentryCrashLOG_BAK_WARN WARN -# undef WARN -#endif -#ifdef INFO -# define SentryCrashLOG_BAK_INFO INFO -# undef INFO -#endif -#ifdef DEBUG -# define SentryCrashLOG_BAK_DEBUG DEBUG -# undef DEBUG -#endif -#ifdef TRACE -# define SentryCrashLOG_BAK_TRACE TRACE -# undef TRACE -#endif - -#define SentryCrashLogger_Level_None 0 -#define SentryCrashLogger_Level_Error 10 -#define SentryCrashLogger_Level_Warn 20 -#define SentryCrashLogger_Level_Info 30 -#define SentryCrashLogger_Level_Debug 40 -#define SentryCrashLogger_Level_Trace 50 - -#define SentryCrash_NONE SentryCrashLogger_Level_None -#define ERROR SentryCrashLogger_Level_Error -#define WARN SentryCrashLogger_Level_Warn -#define INFO SentryCrashLogger_Level_Info -#define DEBUG SentryCrashLogger_Level_Debug -#define TRACE SentryCrashLogger_Level_Trace - -#ifndef SentryCrashLogger_Level -# define SentryCrashLogger_Level SentryCrashLogger_Level_Error -#endif - -#ifndef SentryCrashLogger_LocalLevel -# define SentryCrashLogger_LocalLevel SentryCrashLogger_Level_None -#endif - -#define a_SentryCrashLOG_FULL(LEVEL, FMT, ...) \ - i_SentryCrashLOG_FULL(LEVEL, __FILE__, __LINE__, __PRETTY_FUNCTION__, FMT, ##__VA_ARGS__) - -// ============================================================================ -#pragma mark - API - -// ============================================================================ - -/** Set the filename to log to. - * - * @param filename The file to write to (NULL = write to stdout). - * - * @param overwrite If true, overwrite the log file. - */ -bool sentrycrashlog_setLogFilename(const char *filename, bool overwrite); - -/** Clear the log file. */ -bool sentrycrashlog_clearLogFile(void); - -/** Tests if the logger would print at the specified level. - * - * @param LEVEL The level to test for. One of: - * SentryCrashLogger_Level_Error, - * SentryCrashLogger_Level_Warn, - * SentryCrashLogger_Level_Info, - * SentryCrashLogger_Level_Debug, - * SentryCrashLogger_Level_Trace, - * - * @return TRUE if the logger would print at the specified level. - */ -#define SentryCrashLOG_PRINTS_AT_LEVEL(LEVEL) \ - (SentryCrashLogger_Level >= LEVEL || SentryCrashLogger_LocalLevel >= LEVEL) - -/** Log a message regardless of the log settings. - * Normal version prints out full context. Basic version prints directly. - * - * @param FMT The format specifier, followed by its arguments. - */ -#define SentryCrashLOG_ALWAYS(FMT, ...) a_SentryCrashLOG_FULL("FORCE", FMT, ##__VA_ARGS__) -#define SentryCrashLOGBASIC_ALWAYS(FMT, ...) i_SentryCrashLOG_BASIC(FMT, ##__VA_ARGS__) - -/** Log an error. - * Normal version prints out full context. Basic version prints directly. - * - * @param FMT The format specifier, followed by its arguments. - */ -#if SentryCrashLOG_PRINTS_AT_LEVEL(SentryCrashLogger_Level_Error) -# define SentryCrashLOG_ERROR(FMT, ...) a_SentryCrashLOG_FULL("ERROR", FMT, ##__VA_ARGS__) -# define SentryCrashLOGBASIC_ERROR(FMT, ...) i_SentryCrashLOG_BASIC(FMT, ##__VA_ARGS__) -#else -# define SentryCrashLOG_ERROR(FMT, ...) -# define SentryCrashLOGBASIC_ERROR(FMT, ...) -#endif - -/** Log a warning. - * Normal version prints out full context. Basic version prints directly. - * - * @param FMT The format specifier, followed by its arguments. - */ -#if SentryCrashLOG_PRINTS_AT_LEVEL(SentryCrashLogger_Level_Warn) -# define SentryCrashLOG_WARN(FMT, ...) a_SentryCrashLOG_FULL("WARN ", FMT, ##__VA_ARGS__) -# define SentryCrashLOGBASIC_WARN(FMT, ...) i_SentryCrashLOG_BASIC(FMT, ##__VA_ARGS__) -#else -# define SentryCrashLOG_WARN(FMT, ...) -# define SentryCrashLOGBASIC_WARN(FMT, ...) -#endif - -/** Log an info message. - * Normal version prints out full context. Basic version prints directly. - * - * @param FMT The format specifier, followed by its arguments. - */ -#if SentryCrashLOG_PRINTS_AT_LEVEL(SentryCrashLogger_Level_Info) -# define SentryCrashLOG_INFO(FMT, ...) a_SentryCrashLOG_FULL("INFO ", FMT, ##__VA_ARGS__) -# define SentryCrashLOGBASIC_INFO(FMT, ...) i_SentryCrashLOG_BASIC(FMT, ##__VA_ARGS__) -#else -# define SentryCrashLOG_INFO(FMT, ...) -# define SentryCrashLOGBASIC_INFO(FMT, ...) -#endif - -/** Log a debug message. - * Normal version prints out full context. Basic version prints directly. - * - * @param FMT The format specifier, followed by its arguments. - */ -#if SentryCrashLOG_PRINTS_AT_LEVEL(SentryCrashLogger_Level_Debug) -# define SentryCrashLOG_DEBUG(FMT, ...) a_SentryCrashLOG_FULL("DEBUG", FMT, ##__VA_ARGS__) -# define SentryCrashLOGBASIC_DEBUG(FMT, ...) i_SentryCrashLOG_BASIC(FMT, ##__VA_ARGS__) -#else -# define SentryCrashLOG_DEBUG(FMT, ...) -# define SentryCrashLOGBASIC_DEBUG(FMT, ...) -#endif - -/** Log a trace message. - * Normal version prints out full context. Basic version prints directly. - * - * @param FMT The format specifier, followed by its arguments. - */ -#if SentryCrashLOG_PRINTS_AT_LEVEL(SentryCrashLogger_Level_Trace) -# define SentryCrashLOG_TRACE(FMT, ...) a_SentryCrashLOG_FULL("TRACE", FMT, ##__VA_ARGS__) -# define SentryCrashLOGBASIC_TRACE(FMT, ...) i_SentryCrashLOG_BASIC(FMT, ##__VA_ARGS__) -#else -# define SentryCrashLOG_TRACE(FMT, ...) -# define SentryCrashLOGBASIC_TRACE(FMT, ...) -#endif - -// ============================================================================ -#pragma mark - (internal) - -// ============================================================================ - -/* Put everything back to the way we found it. */ -#undef ERROR -#ifdef SentryCrashLOG_BAK_ERROR -# define ERROR SentryCrashLOG_BAK_ERROR -# undef SentryCrashLOG_BAK_ERROR -#endif -#undef WARNING -#ifdef SentryCrashLOG_BAK_WARN -# define WARNING SentryCrashLOG_BAK_WARN -# undef SentryCrashLOG_BAK_WARN -#endif -#undef INFO -#ifdef SentryCrashLOG_BAK_INFO -# define INFO SentryCrashLOG_BAK_INFO -# undef SentryCrashLOG_BAK_INFO -#endif -#undef DEBUG -#ifdef SentryCrashLOG_BAK_DEBUG -# define DEBUG SentryCrashLOG_BAK_DEBUG -# undef SentryCrashLOG_BAK_DEBUG -#endif -#undef TRACE -#ifdef SentryCrashLOG_BAK_TRACE -# define TRACE SentryCrashLOG_BAK_TRACE -# undef SentryCrashLOG_BAK_TRACE -#endif - -#ifdef __cplusplus -} -#endif - -#endif // HDR_SentryCrashLogger_h diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashMachineContext.c b/Sources/SentryCrash/Recording/Tools/SentryCrashMachineContext.c index 67afc49d028..222aa41bc3f 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashMachineContext.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashMachineContext.c @@ -31,11 +31,11 @@ #include "SentryCrashMachineContext_Apple.h" #include "SentryCrashMonitor_MachException.h" #include "SentryCrashStackCursor_MachineContext.h" -#include "SentryCrashSystemCapabilities.h" +#include "SentryInternalCDefines.h" #include -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #ifdef __arm64__ # define UC_MCONTEXT uc_mcontext64 @@ -60,20 +60,20 @@ static inline bool getThreadList(SentryCrashMachineContext *context) { const task_t thisTask = mach_task_self(); - SentryCrashLOG_DEBUG("Getting thread list"); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Getting thread list"); kern_return_t kr; thread_act_array_t threads; mach_msg_type_number_t actualThreadCount; if ((kr = task_threads(thisTask, &threads, &actualThreadCount)) != KERN_SUCCESS) { - SentryCrashLOG_ERROR("task_threads: %s", mach_error_string(kr)); + SENTRY_ASYNC_SAFE_LOG_ERROR("task_threads: %s", mach_error_string(kr)); return false; } - SentryCrashLOG_TRACE("Got %d threads", context->threadCount); + SENTRY_ASYNC_SAFE_LOG_TRACE("Got %d threads", context->threadCount); int threadCount = (int)actualThreadCount; int maxThreadCount = sizeof(context->allThreads) / sizeof(context->allThreads[0]); if (threadCount > maxThreadCount) { - SentryCrashLOG_ERROR( + SENTRY_ASYNC_SAFE_LOG_ERROR( "Thread count %d is higher than maximum of %d", threadCount, maxThreadCount); threadCount = maxThreadCount; } @@ -106,7 +106,7 @@ bool sentrycrashmc_getContextForThread( SentryCrashThread thread, SentryCrashMachineContext *destinationContext, bool isCrashedContext) { - SentryCrashLOG_DEBUG("Fill thread 0x%x context into %p. is crashed = %d", thread, + SENTRY_ASYNC_SAFE_LOG_DEBUG("Fill thread 0x%x context into %p. is crashed = %d", thread, destinationContext, isCrashedContext); memset(destinationContext, 0, sizeof(*destinationContext)); destinationContext->thisThread = (thread_t)thread; @@ -120,7 +120,7 @@ sentrycrashmc_getContextForThread( destinationContext->isStackOverflow = isStackOverflow(destinationContext); getThreadList(destinationContext); } - SentryCrashLOG_TRACE("Context retrieved."); + SENTRY_ASYNC_SAFE_LOG_TRACE("Context retrieved."); return true; } @@ -128,7 +128,7 @@ bool sentrycrashmc_getContextForSignal( void *signalUserContext, SentryCrashMachineContext *destinationContext) { - SentryCrashLOG_DEBUG( + SENTRY_ASYNC_SAFE_LOG_DEBUG( "Get context from signal user context and put into %p.", destinationContext); _STRUCT_MCONTEXT *sourceContext = ((SignalUserContext *)signalUserContext)->UC_MCONTEXT; memcpy(&destinationContext->machineContext, sourceContext, @@ -138,7 +138,7 @@ sentrycrashmc_getContextForSignal( destinationContext->isSignalContext = true; destinationContext->isStackOverflow = isStackOverflow(destinationContext); getThreadList(destinationContext); - SentryCrashLOG_TRACE("Context retrieved."); + SENTRY_ASYNC_SAFE_LOG_TRACE("Context retrieved."); return true; } @@ -154,20 +154,20 @@ void sentrycrashmc_suspendEnvironment_upToMaxSupportedThreads(thread_act_array_t *suspendedThreads, mach_msg_type_number_t *numSuspendedThreads, mach_msg_type_number_t maxSupportedThreads) { -#if SentryCrashCRASH_HAS_THREADS_API - SentryCrashLOG_DEBUG("Suspending environment."); +#if SENTRY_HAS_THREADS_API + SENTRY_ASYNC_SAFE_LOG_DEBUG("Suspending environment."); kern_return_t kr; const task_t thisTask = mach_task_self(); const thread_t thisThread = (thread_t)sentrycrashthread_self(); if ((kr = task_threads(thisTask, suspendedThreads, numSuspendedThreads)) != KERN_SUCCESS) { - SentryCrashLOG_ERROR("task_threads: %s", mach_error_string(kr)); + SENTRY_ASYNC_SAFE_LOG_ERROR("task_threads: %s", mach_error_string(kr)); return; } if (*numSuspendedThreads > maxSupportedThreads) { *numSuspendedThreads = 0; - SentryCrashLOG_DEBUG("Too many threads to suspend. Aborting operation."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Too many threads to suspend. Aborting operation."); return; } @@ -176,12 +176,13 @@ sentrycrashmc_suspendEnvironment_upToMaxSupportedThreads(thread_act_array_t *sus if (thread != thisThread && !sentrycrashcm_isReservedThread(thread)) { if ((kr = thread_suspend(thread)) != KERN_SUCCESS) { // Record the error and keep going. - SentryCrashLOG_ERROR("thread_suspend (%08x): %s", thread, mach_error_string(kr)); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "thread_suspend (%08x): %s", thread, mach_error_string(kr)); } } } - SentryCrashLOG_DEBUG("Suspend complete."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Suspend complete."); #endif } @@ -189,14 +190,14 @@ void sentrycrashmc_resumeEnvironment( __unused thread_act_array_t threads, __unused mach_msg_type_number_t numThreads) { -#if SentryCrashCRASH_HAS_THREADS_API - SentryCrashLOG_DEBUG("Resuming environment."); +#if SENTRY_HAS_THREADS_API + SENTRY_ASYNC_SAFE_LOG_DEBUG("Resuming environment."); kern_return_t kr; const task_t thisTask = mach_task_self(); const thread_t thisThread = (thread_t)sentrycrashthread_self(); if (threads == NULL || numThreads == 0) { - SentryCrashLOG_ERROR("we should call sentrycrashmc_suspendEnvironment() first"); + SENTRY_ASYNC_SAFE_LOG_ERROR("we should call sentrycrashmc_suspendEnvironment() first"); return; } @@ -205,7 +206,8 @@ sentrycrashmc_resumeEnvironment( if (thread != thisThread && !sentrycrashcm_isReservedThread(thread)) { if ((kr = thread_resume(thread)) != KERN_SUCCESS) { // Record the error and keep going. - SentryCrashLOG_ERROR("thread_resume (%08x): %s", thread, mach_error_string(kr)); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "thread_resume (%08x): %s", thread, mach_error_string(kr)); } } } @@ -215,7 +217,7 @@ sentrycrashmc_resumeEnvironment( } vm_deallocate(thisTask, (vm_address_t)threads, sizeof(thread_t) * numThreads); - SentryCrashLOG_DEBUG("Resume complete."); + SENTRY_ASYNC_SAFE_LOG_DEBUG("Resume complete."); #endif } @@ -235,9 +237,9 @@ int sentrycrashmc_indexOfThread( const SentryCrashMachineContext *const context, SentryCrashThread thread) { - SentryCrashLOG_TRACE("check thread vs %d threads", context->threadCount); + SENTRY_ASYNC_SAFE_LOG_TRACE("check thread vs %d threads", context->threadCount); for (int i = 0; i < (int)context->threadCount; i++) { - SentryCrashLOG_TRACE("%d: %x vs %x", i, thread, context->allThreads[i]); + SENTRY_ASYNC_SAFE_LOG_TRACE("%d: %x vs %x", i, thread, context->allThreads[i]); if (context->allThreads[i] == thread) { return i; } diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashMemory.c b/Sources/SentryCrash/Recording/Tools/SentryCrashMemory.c index 4a0addd0cb2..f5ca6a8434f 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashMemory.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashMemory.c @@ -27,7 +27,7 @@ #include "SentryCrashMemory.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #include <_types/_uint8_t.h> #include diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashObjC.c b/Sources/SentryCrash/Recording/Tools/SentryCrashObjC.c index ee1ef1ffdd6..bf9f4a4dc06 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashObjC.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashObjC.c @@ -31,7 +31,7 @@ #include "SentryCrashMemory.h" #include "SentryCrashString.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #if __IPHONE_OS_VERSION_MAX_ALLOWED > 70000 # include diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor.c b/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor.c index 03dbfd1e4d1..1e34e690ef6 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor.c @@ -28,14 +28,15 @@ #include "SentryCrashSymbolicator.h" #include -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" static bool g_advanceCursor(__unused SentryCrashStackCursor *cursor) { - SentryCrashLOG_WARN("No stack cursor has been set. For C++, this means that hooking " - "__cxa_throw() failed for some reason. Embedded frameworks can cause " - "this: https://github.com/getsentry/SentryCrash/issues/205"); + SENTRY_ASYNC_SAFE_LOG_WARN( + "No stack cursor has been set. For C++, this means that hooking " + "__cxa_throw() failed for some reason. Embedded frameworks can cause " + "this: https://github.com/getsentry/SentryCrash/issues/205"); return false; } diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor_Backtrace.c b/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor_Backtrace.c index 27c222184ef..2f76dfb356f 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor_Backtrace.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor_Backtrace.c @@ -26,7 +26,7 @@ #include "SentryCrashStackCursor_Backtrace.h" #include "SentryCrashCPU.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" static bool advanceCursor(SentryCrashStackCursor *cursor) diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor_MachineContext.c b/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor_MachineContext.c index 9a53dba5cb1..2607482bc51 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor_MachineContext.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor_MachineContext.c @@ -30,7 +30,7 @@ #include -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" /** Represents an entry in a frame list. * This is modeled after the various i386/x64 frame walkers in the xnu source, diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor_SelfThread.m b/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor_SelfThread.m index cfca87ee0fe..38bab5ab081 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor_SelfThread.m +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashStackCursor_SelfThread.m @@ -28,7 +28,7 @@ #import "SentryLog.h" #include -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #define MAX_BACKTRACE_LENGTH \ (SentryCrashSC_CONTEXT_SIZE \ diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashString.c b/Sources/SentryCrash/Recording/Tools/SentryCrashString.c index 3252ffe4ed0..80f950da706 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashString.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashString.c @@ -26,7 +26,7 @@ // #include "SentryCrashString.h" -#include "SentryCrashSystemCapabilities.h" +#include "SentryInternalCDefines.h" #include #include @@ -445,13 +445,8 @@ sentrycrashstring_extractHexValue(const char *string, int stringLength, uint64_t const unsigned char *current = (const unsigned char *)string; const unsigned char *const end = current + stringLength; for (;;) { -#if SentryCrashCRASH_HAS_STRNSTR current = (const unsigned char *)strnstr( (const char *)current, "0x", (unsigned)(end - current)); -#else - current = (const unsigned char *)strstr((const char *)current, "0x"); - unlikely_if(current >= end) { return false; } -#endif unlikely_if(!current) { return false; } current += 2; diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashSysCtl.c b/Sources/SentryCrash/Recording/Tools/SentryCrashSysCtl.c index 79ff6467530..9609f93fbac 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashSysCtl.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashSysCtl.c @@ -27,7 +27,7 @@ #include "SentryCrashSysCtl.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #include #include @@ -38,13 +38,14 @@ #define CHECK_SYSCTL_NAME(TYPE, CALL) \ if (0 != (CALL)) { \ - SentryCrashLOG_ERROR("Could not get %s value for %s: %s", #CALL, name, strerror(errno)); \ + SENTRY_ASYNC_SAFE_LOG_ERROR( \ + "Could not get %s value for %s: %s", #CALL, name, strerror(errno)); \ return 0; \ } #define CHECK_SYSCTL_CMD(TYPE, CALL) \ if (0 != (CALL)) { \ - SentryCrashLOG_ERROR( \ + SENTRY_ASYNC_SAFE_LOG_ERROR( \ "Could not get %s value for %d,%d: %s", #CALL, major_cmd, minor_cmd, strerror(errno)); \ return 0; \ } @@ -171,7 +172,7 @@ sentrycrashsysctl_timeval(const int major_cmd, const int minor_cmd) size_t size = sizeof(value); if (0 != sysctl(cmd, sizeof(cmd) / sizeof(*cmd), &value, &size, NULL, 0)) { - SentryCrashLOG_ERROR( + SENTRY_ASYNC_SAFE_LOG_ERROR( "Could not get timeval value for %d,%d: %s", major_cmd, minor_cmd, strerror(errno)); } @@ -185,7 +186,8 @@ sentrycrashsysctl_timevalForName(const char *const name) size_t size = sizeof(value); if (0 != sysctlbyname(name, &value, &size, NULL, 0)) { - SentryCrashLOG_ERROR("Could not get timeval value for %s: %s", name, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "Could not get timeval value for %s: %s", name, strerror(errno)); } return value; @@ -204,7 +206,8 @@ sentrycrashsysctl_currentProcessStartTime(void) struct kinfo_proc kp; size_t kpSize = sizeof(kp); if (0 != sysctl(mib, 4, &kp, &kpSize, NULL, 0)) { - SentryCrashLOG_ERROR("Could not get current process start time: %s", strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "Could not get current process start time: %s", strerror(errno)); } else { value = kp.kp_proc.p_un.__p_starttime; } @@ -219,7 +222,8 @@ sentrycrashsysctl_getProcessInfo(const int pid, struct kinfo_proc *const procInf size_t size = sizeof(*procInfo); if (0 != sysctl(cmd, sizeof(cmd) / sizeof(*cmd), procInfo, &size, NULL, 0)) { - SentryCrashLOG_ERROR("Could not get the name for process %d: %s", pid, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "Could not get the name for process %d: %s", pid, strerror(errno)); return false; } return true; @@ -233,24 +237,27 @@ sentrycrashsysctl_getMacAddress(const char *const name, char *const macAddressBu int mib[6] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, (int)if_nametoindex(name) }; if (mib[5] == 0) { - SentryCrashLOG_ERROR("Could not get interface index for %s: %s", name, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "Could not get interface index for %s: %s", name, strerror(errno)); return false; } size_t length; if (sysctl(mib, 6, NULL, &length, NULL, 0) != 0) { - SentryCrashLOG_ERROR("Could not get interface data for %s: %s", name, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "Could not get interface data for %s: %s", name, strerror(errno)); return false; } void *ifBuffer = malloc(length); if (ifBuffer == NULL) { - SentryCrashLOG_ERROR("Out of memory"); + SENTRY_ASYNC_SAFE_LOG_ERROR("Out of memory"); return false; } if (sysctl(mib, 6, ifBuffer, &length, NULL, 0) != 0) { - SentryCrashLOG_ERROR("Could not get interface data for %s: %s", name, strerror(errno)); + SENTRY_ASYNC_SAFE_LOG_ERROR( + "Could not get interface data for %s: %s", name, strerror(errno)); free(ifBuffer); return false; } diff --git a/Sources/SentryCrash/Recording/Tools/SentryCrashThread.c b/Sources/SentryCrash/Recording/Tools/SentryCrashThread.c index 8e4c3d20329..b5d84351582 100644 --- a/Sources/SentryCrash/Recording/Tools/SentryCrashThread.c +++ b/Sources/SentryCrash/Recording/Tools/SentryCrashThread.c @@ -28,9 +28,9 @@ #include "SentryCrashThread.h" #include "SentryCrashMemory.h" -#include "SentryCrashSystemCapabilities.h" +#include "SentryInternalCDefines.h" -#include "SentryCrashLogger.h" +#include "SentryAsyncSafeLog.h" #include #include diff --git a/Sources/SentryCrash/Reporting/Filters/SentryCrashReportFilterBasic.m b/Sources/SentryCrash/Reporting/Filters/SentryCrashReportFilterBasic.m index 03d7dadff63..94a65fea39f 100644 --- a/Sources/SentryCrash/Reporting/Filters/SentryCrashReportFilterBasic.m +++ b/Sources/SentryCrash/Reporting/Filters/SentryCrashReportFilterBasic.m @@ -30,7 +30,7 @@ #import "SentryCrashVarArgs.h" #import "SentryDictionaryDeepSearch.h" -#import "SentryCrashLogger.h" +#import "SentryLog.h" @implementation SentryCrashReportFilterPassthrough @@ -77,7 +77,7 @@ + (SentryCrashVA_Block)argBlockWithFilters:(NSMutableArray *)filters andKeys:(NS SentryCrashVA_Block block = ^(id entry) { if (isKey) { if (entry == nil) { - SentryCrashLOG_ERROR(@"key entry was nil"); + SENTRY_LOG_ERROR(@"key entry was nil"); } else { [keys addObject:entry]; } @@ -86,7 +86,7 @@ + (SentryCrashVA_Block)argBlockWithFilters:(NSMutableArray *)filters andKeys:(NS entry = [SentryCrashReportFilterPipeline filterWithFilters:entry, nil]; } if (![entry conformsToProtocol:@protocol(SentryCrashReportFilter)]) { - SentryCrashLOG_ERROR(@"Not a filter: %@", entry); + SENTRY_LOG_ERROR(@"Not a filter: %@", entry); // Cause next key entry to fail as well. return; } else { diff --git a/Sources/Swift/Extensions/StringExtensions.swift b/Sources/Swift/Extensions/StringExtensions.swift index fa8854e1512..c9a754c6e2a 100644 --- a/Sources/Swift/Extensions/StringExtensions.swift +++ b/Sources/Swift/Extensions/StringExtensions.swift @@ -1,43 +1,6 @@ import Foundation extension String { - /// Retrieve a character at a specific index in the string. - subscript (value: Int) -> Character { - return self[index(startIndex, offsetBy: value)] - } - - /// Retrieve a substring within a countable range of indices. - subscript (range: CountableRange) -> Substring { - let start = index(startIndex, offsetBy: range.lowerBound) - let end = index(startIndex, offsetBy: range.upperBound) - return self[start..) -> Substring { - let start = index(startIndex, offsetBy: range.lowerBound) - let end = index(startIndex, offsetBy: range.upperBound) - return self[start...end] - } - - /// Retrieve a substring up to a specified index. - subscript (range: PartialRangeThrough) -> Substring { - let end = index(startIndex, offsetBy: range.upperBound) - return self[startIndex...end] - } - - /// Retrieve a substring from a specified index to the end of the string. - subscript (range: CountablePartialRangeFrom) -> Substring { - let start = index(startIndex, offsetBy: range.lowerBound) - return self[start..) -> Substring { - let end = index(startIndex, offsetBy: range.upperBound) - return self[startIndex.. String { var result = "" diff --git a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebBreadcrumbEvent.swift b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebBreadcrumbEvent.swift index 0b7fa8cf469..d68f5717b3f 100644 --- a/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebBreadcrumbEvent.swift +++ b/Sources/Swift/Integrations/SessionReplay/RRWeb/SentryRRWebBreadcrumbEvent.swift @@ -4,8 +4,8 @@ import Foundation class SentryRRWebBreadcrumbEvent: SentryRRWebCustomEvent { init(timestamp: Date, category: String, message: String? = nil, level: SentryLevel = .none, data: [String: Any]? = nil) { - var payload: [String: Any] = ["type": "default", "category": category, "level": level.rawValue, "timestamp": timestamp.timeIntervalSince1970 ] - + var payload: [String: Any] = ["type": "default", "category": category, "level": SentryLevelHelper.getNameFor(level.rawValue), "timestamp": timestamp.timeIntervalSince1970 ] + if let message = message { payload["message"] = message } diff --git a/Sources/Swift/Protocol/SentryId.swift b/Sources/Swift/Protocol/SentryId.swift index 3ba459019d2..48ebc2586f0 100644 --- a/Sources/Swift/Protocol/SentryId.swift +++ b/Sources/Swift/Protocol/SentryId.swift @@ -46,8 +46,13 @@ public class SentryId: NSObject { } if uuidString.count == 32 { - let dashedUUID = "\(uuidString[0..<8])-\(uuidString[8..<12])-\(uuidString[12..<16])-\(uuidString[16..<20])-\(uuidString[20...])" - if let id = UUID(uuidString: dashedUUID) { + let dashedUUID = uuidString.enumerated().reduce(into: [Character]()) { partialResult, next in + if next.offset == 8 || next.offset == 12 || next.offset == 16 || next.offset == 20 { + partialResult.append("-") + } + partialResult.append(next.element) + } + if let id = UUID(uuidString: String(dashedUUID)) { self.id = id return } diff --git a/Tests/SentryProfilerTests/SentryContinuousProfilerTests.swift b/Tests/SentryProfilerTests/SentryContinuousProfilerTests.swift index 89a1180c40e..98f5af5a836 100644 --- a/Tests/SentryProfilerTests/SentryContinuousProfilerTests.swift +++ b/Tests/SentryProfilerTests/SentryContinuousProfilerTests.swift @@ -178,7 +178,7 @@ private extension SentryContinuousProfilerTests { let debugMeta = try XCTUnwrap(profile["debug_meta"] as? [String: Any]) let images = try XCTUnwrap(debugMeta["images"] as? [[String: Any]]) XCTAssertFalse(images.isEmpty) - let firstImage = images[0] + let firstImage = try XCTUnwrap(images.first) XCTAssertFalse(try XCTUnwrap(firstImage["code_file"] as? String).isEmpty) XCTAssertFalse(try XCTUnwrap(firstImage["debug_id"] as? String).isEmpty) XCTAssertFalse(try XCTUnwrap(firstImage["image_addr"] as? String).isEmpty) @@ -196,8 +196,8 @@ private extension SentryContinuousProfilerTests { let frames = try XCTUnwrap(sampledProfile["frames"] as? [[String: Any]]) XCTAssertFalse(frames.isEmpty) - XCTAssertFalse(try XCTUnwrap(frames[0]["instruction_addr"] as? String).isEmpty) - XCTAssertFalse(try XCTUnwrap(frames[0]["function"] as? String).isEmpty) + XCTAssertFalse(try XCTUnwrap(frames.first?["instruction_addr"] as? String).isEmpty) + XCTAssertFalse(try XCTUnwrap(frames.first?["function"] as? String).isEmpty) let stacks = try XCTUnwrap(sampledProfile["stacks"] as? [[Int]]) var foundAtLeastOneNonEmptySample = false @@ -285,10 +285,10 @@ private extension SentryContinuousProfilerTests { XCTAssertEqual(values.count, readingsPerBatch - (expectOneLessEnergyReading ? 1 : 0), "Wrong number of values under \(key); (expectOneLessEnergyReading: \(expectOneLessEnergyReading))") if let expectedValue = expectedValue { - let actualValue = try XCTUnwrap(values[1]["value"] as? T) + let actualValue = try XCTUnwrap(try XCTUnwrap(values.element(at: 1))["value"] as? T) XCTAssertEqual(actualValue, expectedValue, "Wrong value for \(key)") - let timestamp = try XCTUnwrap(values[0]["timestamp"] as? TimeInterval) + let timestamp = try XCTUnwrap(values.first?["timestamp"] as? TimeInterval) try assertTimestampOccursWithinTransaction(timestamp: timestamp, chunkStartTime: chunkStartTime, chunkEndTime: chunkEndTime) let actualUnits = try XCTUnwrap(metricContainer["unit"] as? String) diff --git a/Tests/SentryProfilerTests/SentryThreadMetadataCacheTests.mm b/Tests/SentryProfilerTests/SentryThreadMetadataCacheTests.mm index d4daa8e5ef5..65106a7c9a5 100644 --- a/Tests/SentryProfilerTests/SentryThreadMetadataCacheTests.mm +++ b/Tests/SentryProfilerTests/SentryThreadMetadataCacheTests.mm @@ -1,3 +1,4 @@ +#import "SentryAsyncSafeLog.h" #import "SentryProfilingConditionals.h" #if SENTRY_TARGET_PROFILING_SUPPORTED @@ -19,7 +20,7 @@ @interface SentryThreadMetadataCacheTests : XCTestCase void * threadSpin(void *name) { - SENTRY_PROF_LOG_ERROR_RETURN(pthread_setname_np(reinterpret_cast(name))); + SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_setname_np(reinterpret_cast(name))); if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, nullptr) != 0) { return nullptr; } @@ -42,9 +43,9 @@ - (void)testRetrievesThreadMetadata XCTAssertEqual(pthread_create(&thread, nullptr, threadSpin, reinterpret_cast(name)), 0); int policy; sched_param param; - if (SENTRY_PROF_LOG_ERROR_RETURN(pthread_getschedparam(thread, &policy, ¶m)) == 0) { + if (SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_getschedparam(thread, &policy, ¶m)) == 0) { param.sched_priority = 50; - SENTRY_PROF_LOG_ERROR_RETURN(pthread_setschedparam(thread, policy, ¶m)); + SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_setschedparam(thread, policy, ¶m)); } // give the other thread a little time to spawn, otherwise its name comes back as an empty @@ -69,9 +70,9 @@ - (void)testReturnsCachedThreadMetadata XCTAssertEqual(pthread_create(&thread, nullptr, threadSpin, reinterpret_cast(name)), 0); int policy; sched_param param; - if (SENTRY_PROF_LOG_ERROR_RETURN(pthread_getschedparam(thread, &policy, ¶m)) == 0) { + if (SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_getschedparam(thread, &policy, ¶m)) == 0) { param.sched_priority = 50; - SENTRY_PROF_LOG_ERROR_RETURN(pthread_setschedparam(thread, policy, ¶m)); + SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_setschedparam(thread, policy, ¶m)); } // give the other thread a little time to spawn, otherwise its metadata doesn't come back as @@ -82,9 +83,9 @@ - (void)testReturnsCachedThreadMetadata ThreadHandle handle(pthread_mach_thread_np(thread)); XCTAssertEqual(cache->metadataForThread(handle).priority, 50); - if (SENTRY_PROF_LOG_ERROR_RETURN(pthread_getschedparam(thread, &policy, ¶m)) == 0) { + if (SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_getschedparam(thread, &policy, ¶m)) == 0) { param.sched_priority = 100; - SENTRY_PROF_LOG_ERROR_RETURN(pthread_setschedparam(thread, policy, ¶m)); + SENTRY_ASYNC_SAFE_LOG_ERRNO_RETURN(pthread_setschedparam(thread, policy, ¶m)); } XCTAssertEqual(cache->metadataForThread(handle).priority, 50); diff --git a/Tests/SentryProfilerTests/SentryTraceProfilerTests.swift b/Tests/SentryProfilerTests/SentryTraceProfilerTests.swift index b35e1a73b0d..24e89e6f4a6 100644 --- a/Tests/SentryProfilerTests/SentryTraceProfilerTests.swift +++ b/Tests/SentryProfilerTests/SentryTraceProfilerTests.swift @@ -464,10 +464,10 @@ private extension SentryTraceProfilerTests { XCTAssertEqual(values.count, numberOfReadings, "Wrong number of values under \(key)") if let expectedValue = expectedValue { - let actualValue = try XCTUnwrap(values[1]["value"] as? T) + let actualValue = try XCTUnwrap(values.element(at: 1)?["value"] as? T) XCTAssertEqual(actualValue, expectedValue, "Wrong value for \(key)") - let timestamp = try XCTUnwrap(values[0]["elapsed_since_start_ns"] as? NSString) + let timestamp = try XCTUnwrap(values.first?["elapsed_since_start_ns"] as? NSString) try assertTimestampOccursWithinTransaction(timestamp: timestamp, transaction: transaction) let actualUnits = try XCTUnwrap(metricContainer["unit"] as? String) @@ -527,7 +527,7 @@ private extension SentryTraceProfilerTests { let debugMeta = try XCTUnwrap(profile["debug_meta"] as? [String: Any]) let images = try XCTUnwrap(debugMeta["images"] as? [[String: Any]]) XCTAssertFalse(images.isEmpty) - let firstImage = images[0] + let firstImage = try XCTUnwrap(images.first) XCTAssertFalse(try XCTUnwrap(firstImage["code_file"] as? String).isEmpty) XCTAssertFalse(try XCTUnwrap(firstImage["debug_id"] as? String).isEmpty) XCTAssertFalse(try XCTUnwrap(firstImage["image_addr"] as? String).isEmpty) @@ -555,8 +555,8 @@ private extension SentryTraceProfilerTests { let frames = try XCTUnwrap(sampledProfile["frames"] as? [[String: Any]]) XCTAssertFalse(frames.isEmpty) - XCTAssertFalse(try XCTUnwrap(frames[0]["instruction_addr"] as? String).isEmpty) - XCTAssertFalse(try XCTUnwrap(frames[0]["function"] as? String).isEmpty) + XCTAssertFalse(try XCTUnwrap(frames.first?["instruction_addr"] as? String).isEmpty) + XCTAssertFalse(try XCTUnwrap(frames.first?["function"] as? String).isEmpty) let stacks = try XCTUnwrap(sampledProfile["stacks"] as? [[Int]]) var foundAtLeastOneNonEmptySample = false diff --git a/Tests/SentryTests/Helper/SentryFileManagerTests.swift b/Tests/SentryTests/Helper/SentryFileManagerTests.swift index b170ad2af82..fc673a69e14 100644 --- a/Tests/SentryTests/Helper/SentryFileManagerTests.swift +++ b/Tests/SentryTests/Helper/SentryFileManagerTests.swift @@ -131,7 +131,7 @@ class SentryFileManagerTests: XCTestCase { let envelopes = sut.getAllEnvelopes() XCTAssertEqual(1, envelopes.count) - let actualData = envelopes[0].contents + let actualData = try XCTUnwrap(envelopes.first).contents XCTAssertEqual(expectedData, actualData as Data) } @@ -337,7 +337,7 @@ class SentryFileManagerTests: XCTestCase { XCTAssertEqual(maxCacheItems, UInt(events.count)) } - func testMigrateSessionInit_SessionUpdateIsLast() { + func testMigrateSessionInit_SessionUpdateIsLast() throws { sut.store(fixture.sessionEnvelope) // just some other session sut.store(SentryEnvelope(session: SentrySession(releaseName: "1.0.0", distinctId: "some-id"))) @@ -346,22 +346,22 @@ class SentryFileManagerTests: XCTestCase { } sut.store(fixture.sessionUpdateEnvelope) - assertSessionInitMoved(sut.getAllEnvelopes().last!) + try assertSessionInitMoved(sut.getAllEnvelopes().last!) assertSessionEnvelopesStored(count: 2) } - func testMigrateSessionInit_SessionUpdateIsSecond() { + func testMigrateSessionInit_SessionUpdateIsSecond() throws { sut.store(fixture.sessionEnvelope) sut.store(fixture.sessionUpdateEnvelope) for _ in 0...(fixture.maxCacheItems - 2) { sut.store(TestConstants.envelope) } - assertSessionInitMoved(sut.getAllEnvelopes().first!) + try assertSessionInitMoved(sut.getAllEnvelopes().first!) assertSessionEnvelopesStored(count: 1) } - func testMigrateSessionInit_IsInMiddle() { + func testMigrateSessionInit_IsInMiddle() throws { sut.store(fixture.sessionEnvelope) for _ in 0...10 { sut.store(TestConstants.envelope) @@ -371,11 +371,11 @@ class SentryFileManagerTests: XCTestCase { sut.store(TestConstants.envelope) } - assertSessionInitMoved(sut.getAllEnvelopes()[10]) + try assertSessionInitMoved(sut.getAllEnvelopes()[10]) assertSessionEnvelopesStored(count: 1) } - func testMigrateSessionInit_MovesInitFlagOnlyToFirstSessionUpdate() { + func testMigrateSessionInit_MovesInitFlagOnlyToFirstSessionUpdate() throws { sut.store(fixture.sessionEnvelope) for _ in 0...10 { sut.store(TestConstants.envelope) @@ -387,9 +387,9 @@ class SentryFileManagerTests: XCTestCase { sut.store(TestConstants.envelope) } - assertSessionInitMoved(sut.getAllEnvelopes()[10]) - assertSessionInitNotMoved(sut.getAllEnvelopes()[11]) - assertSessionInitNotMoved(sut.getAllEnvelopes()[12]) + try assertSessionInitMoved(sut.getAllEnvelopes()[10]) + try assertSessionInitNotMoved(sut.getAllEnvelopes()[11]) + try assertSessionInitNotMoved(sut.getAllEnvelopes()[12]) assertSessionEnvelopesStored(count: 3) } @@ -403,7 +403,7 @@ class SentryFileManagerTests: XCTestCase { assertSessionEnvelopesStored(count: 0) } - func testMigrateSessionInit_FailToLoadEnvelope() { + func testMigrateSessionInit_FailToLoadEnvelope() throws { sut.store(fixture.sessionEnvelope) for _ in 0...(fixture.maxCacheItems - 3) { @@ -418,7 +418,7 @@ class SentryFileManagerTests: XCTestCase { sut.store(fixture.sessionUpdateEnvelope) - assertSessionInitMoved(sut.getAllEnvelopes().last!) + try assertSessionInitMoved(sut.getAllEnvelopes().last!) } func testMigrateSessionInit_DoesNotCallEnvelopeItemDeleted() { @@ -452,7 +452,7 @@ class SentryFileManagerTests: XCTestCase { let actualEnvelope = SentrySerialization.envelope(with: sut.getOldestEnvelope()?.contents ?? Data()) - XCTAssertEqual(fixture.eventIds[11], actualEnvelope?.header.eventId) + XCTAssertEqual(try XCTUnwrap(fixture.eventIds.element(at: 11)), actualEnvelope?.header.eventId) } func testGetOldestEnvelope_WhenNoEnvelopes() { @@ -909,21 +909,21 @@ private extension SentryFileManagerTests { "Folder for events should be deleted on init: \(sut.eventsPath)") } - func assertSessionInitMoved(_ actualSessionFileContents: SentryFileContents) { + func assertSessionInitMoved(_ actualSessionFileContents: SentryFileContents) throws { let actualSessionEnvelope = SentrySerialization.envelope(with: actualSessionFileContents.contents) XCTAssertEqual(2, actualSessionEnvelope?.items.count) - let actualSession = SentrySerialization.session(with: actualSessionEnvelope?.items[1].data ?? Data()) + let actualSession = SentrySerialization.session(with: try XCTUnwrap(actualSessionEnvelope?.items.element(at: 1)).data) XCTAssertNotNil(actualSession) XCTAssertEqual(fixture.expectedSessionUpdate, actualSession) } - func assertSessionInitNotMoved(_ actualSessionFileContents: SentryFileContents) { + func assertSessionInitNotMoved(_ actualSessionFileContents: SentryFileContents) throws { let actualSessionEnvelope = SentrySerialization.envelope(with: actualSessionFileContents.contents) XCTAssertEqual(2, actualSessionEnvelope?.items.count) - let actualSession = SentrySerialization.session(with: actualSessionEnvelope?.items[0].data ?? Data()) + let actualSession = SentrySerialization.session(with: try XCTUnwrap(actualSessionEnvelope?.items.first).data) XCTAssertNotNil(actualSession) XCTAssertEqual(fixture.sessionUpdate, actualSession) diff --git a/Tests/SentryTests/Helper/SentrySerializationTests.swift b/Tests/SentryTests/Helper/SentrySerializationTests.swift index 8a9529769e9..1df061b3453 100644 --- a/Tests/SentryTests/Helper/SentrySerializationTests.swift +++ b/Tests/SentryTests/Helper/SentrySerializationTests.swift @@ -7,7 +7,7 @@ class SentrySerializationTests: XCTestCase { static var invalidData = "hi".data(using: .utf8)! static var traceContext = SentryTraceContext(trace: SentryId(), publicKey: "PUBLIC_KEY", releaseName: "RELEASE_NAME", environment: "TEST", transaction: "transaction", userSegment: "some segment", sampleRate: "0.25", sampled: "true", replayId: nil) } - + func testSerializationFailsWithInvalidJSONObject() { let json: [String: Any] = [ "valid object": "hi, i'm a valid object", @@ -16,11 +16,11 @@ class SentrySerializationTests: XCTestCase { let data = SentrySerialization.data(withJSONObject: json) XCTAssertNil(data) } - - func testSentryEnvelopeSerializer_WithSingleEvent() { + + func testSentryEnvelopeSerializer_WithSingleEvent() throws { // Arrange let event = Event() - + let item = SentryEnvelopeItem(event: event) let envelope = SentryEnvelope(id: event.eventId, singleItem: item) envelope.header.sentAt = Date(timeIntervalSince1970: 9_001) @@ -28,142 +28,135 @@ class SentrySerializationTests: XCTestCase { // Sanity check XCTAssertEqual(event.eventId, envelope.header.eventId) XCTAssertEqual(1, envelope.items.count) - XCTAssertEqual("event", envelope.items[0].header.type) - - assertEnvelopeSerialization(envelope: envelope) { deserializedEnvelope in - XCTAssertEqual(envelope.header.eventId, deserializedEnvelope.header.eventId) - assertDefaultSdkInfoSet(deserializedEnvelope: deserializedEnvelope) - XCTAssertEqual(1, deserializedEnvelope.items.count) - XCTAssertEqual("event", envelope.items[0].header.type) - XCTAssertEqual(envelope.items[0].header.length, deserializedEnvelope.items[0].header.length) - XCTAssertEqual(envelope.items[0].data, deserializedEnvelope.items[0].data) - XCTAssertNil(deserializedEnvelope.header.traceContext) - XCTAssertEqual(Date(timeIntervalSince1970: 9_001), deserializedEnvelope.header.sentAt) - } + XCTAssertEqual("event", try XCTUnwrap(envelope.items.first).header.type) + + let deserializedEnvelope = try XCTUnwrap(SentrySerialization.envelope(with: serializeEnvelope(envelope: envelope))) + XCTAssertEqual(envelope.header.eventId, deserializedEnvelope.header.eventId) + assertDefaultSdkInfoSet(deserializedEnvelope: deserializedEnvelope) + XCTAssertEqual(1, deserializedEnvelope.items.count) + XCTAssertEqual("event", try XCTUnwrap(envelope.items.first).header.type) + XCTAssertEqual(try XCTUnwrap(envelope.items.first).header.length, try XCTUnwrap(deserializedEnvelope.items.first).header.length) + XCTAssertEqual(try XCTUnwrap(envelope.items.first).data, try XCTUnwrap(deserializedEnvelope.items.first).data) + XCTAssertNil(deserializedEnvelope.header.traceContext) + XCTAssertEqual(Date(timeIntervalSince1970: 9_001), deserializedEnvelope.header.sentAt) } - - func testSentryEnvelopeSerializer_WithManyItems() { + + func testSentryEnvelopeSerializer_WithManyItems() throws { // Arrange let itemsCount = 15 var items: [SentryEnvelopeItem] = [] for i in 0.. SentryEnvelopeItem { let itemData = Data() let itemHeader = SentryEnvelopeItemHeader(type: "attachment", length: UInt(itemData.count)) return SentryEnvelopeItem(header: itemHeader, data: itemData) } - - private func assertEnvelopeSerialization( - envelope: SentryEnvelope, - assert: (SentryEnvelope) -> Void - ) { - let serializedEnvelope = serializeEnvelope(envelope: envelope) - - if let deserializedEnvelope = SentrySerialization.envelope(with: serializedEnvelope) { - assert(deserializedEnvelope) - } else { - XCTFail("Could not deserialize envelope.") - } - } - + private func assertDefaultSdkInfoSet(deserializedEnvelope: SentryEnvelope) { let sdkInfo = SentrySdkInfo(name: SentryMeta.sdkName, andVersion: SentryMeta.versionString) XCTAssertEqual(sdkInfo, deserializedEnvelope.header.sdkInfo) diff --git a/Tests/SentryTests/Integrations/ANR/SentryANRTrackingIntegrationTests.swift b/Tests/SentryTests/Integrations/ANR/SentryANRTrackingIntegrationTests.swift index 8f43a2c9a1b..7d31b26d7ec 100644 --- a/Tests/SentryTests/Integrations/ANR/SentryANRTrackingIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/ANR/SentryANRTrackingIntegrationTests.swift @@ -64,13 +64,13 @@ class SentryANRTrackingIntegrationTests: SentrySDKIntegrationTestsBase { XCTAssertFalse(result) } - func testANRDetected_EventCaptured() { + func testANRDetected_EventCaptured() throws { givenInitializedTracker() setUpThreadInspector() Dynamic(sut).anrDetected() - assertEventWithScopeCaptured { event, _, _ in + try assertEventWithScopeCaptured { event, _, _ in XCTAssertNotNil(event) guard let ex = event?.exceptions?.first else { XCTFail("ANR Exception not found") @@ -83,7 +83,7 @@ class SentryANRTrackingIntegrationTests: SentrySDKIntegrationTestsBase { XCTAssertNotNil(ex.stacktrace) XCTAssertEqual(ex.stacktrace?.frames.first?.function, "main") XCTAssertEqual(ex.stacktrace?.snapshot?.boolValue, true) - XCTAssertEqual(event?.threads?[0].current?.boolValue, true) + XCTAssertEqual(try XCTUnwrap(event?.threads?.first).current?.boolValue, true) XCTAssertEqual(event?.isAppHangEvent, true) guard let threads = event?.threads else { @@ -111,7 +111,7 @@ class SentryANRTrackingIntegrationTests: SentrySDKIntegrationTestsBase { assertNoEventCaptured() } - func testANRDetected_DetectingPausedResumed_EventCaptured() { + func testANRDetected_DetectingPausedResumed_EventCaptured() throws { givenInitializedTracker() setUpThreadInspector() sut.pauseAppHangTracking() @@ -119,7 +119,7 @@ class SentryANRTrackingIntegrationTests: SentrySDKIntegrationTestsBase { Dynamic(sut).anrDetected() - assertEventWithScopeCaptured { event, _, _ in + try assertEventWithScopeCaptured { event, _, _ in XCTAssertNotNil(event) guard let ex = event?.exceptions?.first else { XCTFail("ANR Exception not found") diff --git a/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift b/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift index 985bbc03210..8459645cd8c 100644 --- a/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift @@ -81,7 +81,7 @@ class SentryBreadcrumbTrackerTests: XCTestCase { XCTAssertEqual(payloadData["state"] as? String, "cellular") } - func testSwizzlingStarted_ViewControllerAppears_AddsUILifeCycleBreadcrumb() { + func testSwizzlingStarted_ViewControllerAppears_AddsUILifeCycleBreadcrumb() throws { let testReachability = TestSentryReachability() // We already test the network breadcrumbs in a test above. Using the `TestReachability` @@ -122,7 +122,7 @@ class SentryBreadcrumbTrackerTests: XCTestCase { return } - let lifeCycleCrumb = crumbs[1] + let lifeCycleCrumb = try XCTUnwrap(crumbs.element(at: 1)) XCTAssertEqual("navigation", lifeCycleCrumb.type) XCTAssertEqual("ui.lifecycle", lifeCycleCrumb.category) XCTAssertEqual("false", lifeCycleCrumb.data?["beingPresented"] as? String) @@ -136,7 +136,7 @@ class SentryBreadcrumbTrackerTests: XCTestCase { func testNavigationBreadcrumbForSessionReplay() throws { //Call the previous test to create the breadcrumb into the delegate - testSwizzlingStarted_ViewControllerAppears_AddsUILifeCycleBreadcrumb() + try testSwizzlingStarted_ViewControllerAppears_AddsUILifeCycleBreadcrumb() let sut = SentrySRDefaultBreadcrumbConverter() diff --git a/Tests/SentryTests/Integrations/MetricKit/SentryMXCallStackTreeTests.swift b/Tests/SentryTests/Integrations/MetricKit/SentryMXCallStackTreeTests.swift index 6bde794a652..a1a457aa801 100644 --- a/Tests/SentryTests/Integrations/MetricKit/SentryMXCallStackTreeTests.swift +++ b/Tests/SentryTests/Integrations/MetricKit/SentryMXCallStackTreeTests.swift @@ -41,7 +41,7 @@ final class SentryMXCallStackTreeTests: XCTestCase { // Only validate some properties as this only validates that we can // decode a real payload XCTAssertEqual(16, callStackTree.callStacks.count) - XCTAssertEqual(27, callStackTree.callStacks[0].flattenedRootFrames.count) + XCTAssertEqual(27, try XCTUnwrap(callStackTree.callStacks.first).flattenedRootFrames.count) } func testDecodeCallStackTree_GarbagePayload() throws { @@ -63,31 +63,31 @@ final class SentryMXCallStackTreeTests: XCTestCase { XCTAssertEqual(framesAmount, callStack.flattenedRootFrames.count) - let firstFrame = try XCTUnwrap(callStack.flattenedRootFrames[0]) + let firstFrame = try XCTUnwrap(callStack.flattenedRootFrames.first) XCTAssertEqual(UUID(uuidString: "9E8D8DE6-EEC1-3199-8720-9ED68EE3F967"), firstFrame.binaryUUID) XCTAssertEqual(414_732, firstFrame.offsetIntoBinaryTextSegment) XCTAssertEqual(1, firstFrame.sampleCount) XCTAssertEqual("Sentry", firstFrame.binaryName) XCTAssertEqual(4_312_798_220, firstFrame.address) - XCTAssertEqual(subFrameCount[0], firstFrame.subFrames?.count) + XCTAssertEqual(try XCTUnwrap(subFrameCount.first), firstFrame.subFrames?.count) - let secondFrame = try XCTUnwrap(callStack.flattenedRootFrames[1]) + let secondFrame = try XCTUnwrap(try XCTUnwrap(callStack.flattenedRootFrames.element(at: 1))) XCTAssertEqual(UUID(uuidString: "CA12CAFA-91BA-3E1C-BE9C-E34DB96FE7DF"), secondFrame.binaryUUID) XCTAssertEqual(46_380, secondFrame.offsetIntoBinaryTextSegment) XCTAssertEqual(1, secondFrame.sampleCount) XCTAssertEqual("iOS-Swift", secondFrame.binaryName) XCTAssertEqual(4_310_988_076, secondFrame.address) - XCTAssertEqual(subFrameCount[1], secondFrame.subFrames?.count) + XCTAssertEqual(try XCTUnwrap(subFrameCount.element(at: 1)), secondFrame.subFrames?.count) - let thirdFrame = try XCTUnwrap(callStack.flattenedRootFrames[2]) + let thirdFrame = try XCTUnwrap(try XCTUnwrap(callStack.flattenedRootFrames.element(at: 2))) XCTAssertEqual(UUID(uuidString: "CA12CAFA-91BA-3E1C-BE9C-E34DB96FE7DF"), thirdFrame.binaryUUID) XCTAssertEqual(46_370, thirdFrame.offsetIntoBinaryTextSegment) XCTAssertEqual(1, thirdFrame.sampleCount) XCTAssertEqual("iOS-Swift", thirdFrame.binaryName) XCTAssertEqual(4_310_988_026, thirdFrame.address) - XCTAssertEqual(subFrameCount[2], thirdFrame.subFrames?.count ?? 0) + XCTAssertEqual(try XCTUnwrap(subFrameCount.element(at: 2)), thirdFrame.subFrames?.count ?? 0) - XCTAssertEqual(try XCTUnwrap(firstFrame.subFrames?[0]), secondFrame) + XCTAssertEqual(try XCTUnwrap(firstFrame.subFrames?.first), secondFrame) } } diff --git a/Tests/SentryTests/Integrations/MetricKit/SentryMetricKitIntegrationTests.swift b/Tests/SentryTests/Integrations/MetricKit/SentryMetricKitIntegrationTests.swift index 34296098302..866f09c8dd9 100644 --- a/Tests/SentryTests/Integrations/MetricKit/SentryMetricKitIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/MetricKit/SentryMetricKitIntegrationTests.swift @@ -96,7 +96,7 @@ final class SentryMetricKitIntegrationTests: SentrySDKIntegrationTestsBase { let diagnostic = MXCrashDiagnostic() mxDelegate.didReceiveCrashDiagnostic(diagnostic, callStackTree: callStackTreePerThread, timeStampBegin: timeStampBegin, timeStampEnd: timeStampEnd) - assertEventWithScopeCaptured { _, scope, _ in + try assertEventWithScopeCaptured { _, scope, _ in let diagnosticAttachment = scope?.attachments.first { $0.filename == "MXDiagnosticPayload.json" } XCTAssertEqual(diagnosticAttachment?.data, diagnostic.jsonRepresentation()) @@ -114,7 +114,7 @@ final class SentryMetricKitIntegrationTests: SentrySDKIntegrationTestsBase { let diagnostic = MXCrashDiagnostic() mxDelegate.didReceiveCrashDiagnostic(diagnostic, callStackTree: callStackTreePerThread, timeStampBegin: timeStampBegin, timeStampEnd: timeStampEnd) - assertEventWithScopeCaptured { _, scope, _ in + try assertEventWithScopeCaptured { _, scope, _ in let diagnosticAttachment = scope?.attachments.first { $0.filename == "MXDiagnosticPayload.json" } XCTAssertNil(diagnosticAttachment) @@ -134,7 +134,7 @@ final class SentryMetricKitIntegrationTests: SentrySDKIntegrationTestsBase { let mxDelegate = sut as SentryMXManagerDelegate mxDelegate.didReceiveCrashDiagnostic(MXCrashDiagnostic(), callStackTree: callStackTreePerThread, timeStampBegin: timeStampBegin, timeStampEnd: timeStampEnd) - assertEventWithScopeCaptured { event, _, _ in + try assertEventWithScopeCaptured { event, _, _ in let stacktrace = try! XCTUnwrap( event?.threads?.first?.stacktrace) let inAppFramesCount = stacktrace.frames.filter { $0.inApp as? Bool ?? false }.count @@ -193,8 +193,8 @@ final class SentryMetricKitIntegrationTests: SentrySDKIntegrationTestsBase { let invocations = client.captureEventWithScopeInvocations.invocations XCTAssertEqual(2, client.captureEventWithScopeInvocations.count) - try assertEvent(event: invocations[0].event) - try assertEvent(event: invocations[1].event) + try assertEvent(event: try XCTUnwrap(invocations.first).event) + try assertEvent(event: try XCTUnwrap(invocations.element(at: 1)).event) func assertEvent(event: Event) throws { let sentryFrames = try XCTUnwrap(event.threads?.first?.stacktrace?.frames, "Event has no frames.") @@ -254,7 +254,7 @@ final class SentryMetricKitIntegrationTests: SentrySDKIntegrationTestsBase { } private func assertPerThread(exceptionType: String, exceptionValue: String, exceptionMechanism: String, handled: Bool = true) throws { - assertEventWithScopeCaptured { event, scope, _ in + try assertEventWithScopeCaptured { event, scope, _ in XCTAssertEqual(1, scope?.attachments.count) XCTAssertEqual(callStackTreePerThread.callStacks.count, event?.threads?.count) @@ -287,14 +287,14 @@ final class SentryMetricKitIntegrationTests: SentrySDKIntegrationTestsBase { let invocations = client.captureEventWithScopeInvocations.invocations XCTAssertEqual(4, client.captureEventWithScopeInvocations.count, "Client expected to capture 2 events.") - let firstEvent = invocations[0].event - let secondEvent = invocations[1].event - let thirdEvent = invocations[2].event - let fourthEvent = invocations[3].event + let firstEvent = try XCTUnwrap(invocations.first).event + let secondEvent = try XCTUnwrap(invocations.element(at: 1)).event + let thirdEvent = try XCTUnwrap(invocations.element(at: 2)).event + let fourthEvent = try XCTUnwrap(invocations.element(at: 3)).event - invocations.map { $0.event }.forEach { - XCTAssertEqual(timeStampBegin, $0.timestamp) - XCTAssertEqual(false, $0.threads?[0].crashed) + for event in invocations.map({ $0.event }) { + XCTAssertEqual(timeStampBegin, event.timestamp) + XCTAssertEqual(false, try XCTUnwrap(event.threads?.first).crashed) } let allFrames = try XCTUnwrap(callStackTreeNotPerThread.callStacks.first?.flattenedRootFrames, "CallStackTree has no call stack.") @@ -357,15 +357,15 @@ final class SentryMetricKitIntegrationTests: SentrySDKIntegrationTestsBase { return } - XCTAssertEqual("macho", debugMeta[0].type) - XCTAssertEqual("9E8D8DE6-EEC1-3199-8720-9ED68EE3F967", debugMeta[0].debugID) - XCTAssertEqual("0x000000010109c000", debugMeta[0].imageAddress) - XCTAssertEqual("Sentry", debugMeta[0].codeFile) + XCTAssertEqual("macho", try XCTUnwrap(debugMeta.first).type) + XCTAssertEqual("9E8D8DE6-EEC1-3199-8720-9ED68EE3F967", try XCTUnwrap(debugMeta.first).debugID) + XCTAssertEqual("0x000000010109c000", try XCTUnwrap(debugMeta.first).imageAddress) + XCTAssertEqual("Sentry", try XCTUnwrap(debugMeta.first).codeFile) - XCTAssertEqual("macho", debugMeta[1].type) - XCTAssertEqual("CA12CAFA-91BA-3E1C-BE9C-E34DB96FE7DF", debugMeta[1].debugID) - XCTAssertEqual("0x0000000100f3c000", debugMeta[1].imageAddress) - XCTAssertEqual("iOS-Swift", debugMeta[1].codeFile) + XCTAssertEqual("macho", try XCTUnwrap(debugMeta.element(at: 1)).type) + XCTAssertEqual("CA12CAFA-91BA-3E1C-BE9C-E34DB96FE7DF", try XCTUnwrap(debugMeta.element(at: 1)).debugID) + XCTAssertEqual("0x0000000100f3c000", try XCTUnwrap(debugMeta.element(at: 1)).imageAddress) + XCTAssertEqual("iOS-Swift", try XCTUnwrap(debugMeta.element(at: 1)).codeFile) } private func assertFrame(mxFrame: SentryMXFrame, sentryFrame: Frame) { diff --git a/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackerTest.swift b/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackerTest.swift index 08eb7922e08..bce1efd382e 100644 --- a/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackerTest.swift +++ b/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackerTest.swift @@ -186,7 +186,7 @@ class SentryCoreDataTrackerTests: XCTestCase { XCTAssertEqual(transaction.children.count, 1) - guard let operations = transaction.children[0].data["operations"] as? [String: Any?] else { + guard let operations = try XCTUnwrap(transaction.children.first).data["operations"] as? [String: Any?] else { XCTFail("Transaction has no `operations` extra") return } @@ -236,7 +236,7 @@ class SentryCoreDataTrackerTests: XCTestCase { } XCTAssertEqual(transaction.children.count, 1) - XCTAssertEqual(transaction.children[0].status, .internalError) + XCTAssertEqual(try XCTUnwrap(transaction.children.first).status, .internalError) } func test_Request_with_Error_is_nil() throws { @@ -252,7 +252,7 @@ class SentryCoreDataTrackerTests: XCTestCase { }) XCTAssertEqual(transaction.children.count, 1) - XCTAssertEqual(transaction.children[0].status, .internalError) + XCTAssertEqual(try XCTUnwrap(transaction.children.first).status, .internalError) } func test_save_with_Error() throws { @@ -264,7 +264,7 @@ class SentryCoreDataTrackerTests: XCTestCase { }) XCTAssertEqual(transaction.children.count, 1) - XCTAssertEqual(transaction.children[0].status, .internalError) + XCTAssertEqual(try XCTUnwrap(transaction.children.first).status, .internalError) } func test_save_with_error_is_nil() throws { @@ -277,7 +277,7 @@ class SentryCoreDataTrackerTests: XCTestCase { } XCTAssertEqual(transaction.children.count, 1) - XCTAssertEqual(transaction.children[0].status, .internalError) + XCTAssertEqual(try XCTUnwrap(transaction.children.first).status, .internalError) } func test_Save_NoChanges() throws { diff --git a/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackingIntegrationTest.swift b/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackingIntegrationTest.swift index 2bb762d5f0c..d740194b850 100644 --- a/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackingIntegrationTest.swift +++ b/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackingIntegrationTest.swift @@ -74,7 +74,7 @@ class SentryCoreDataTrackingIntegrationTests: XCTestCase { try? stack.managedObjectContext.save() XCTAssertEqual(transaction.children.count, 1) - XCTAssertEqual(transaction.children[0].operation, "db.sql.transaction") + XCTAssertEqual(try XCTUnwrap(transaction.children.first).operation, "db.sql.transaction") } func test_Save_noChanges() throws { diff --git a/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationTests.swift b/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationTests.swift index 04217e706b2..b9b145d96bc 100644 --- a/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Performance/IO/SentryFileIOTrackingIntegrationTests.swift @@ -21,9 +21,9 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { return result } - init() { + init() throws { let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) - fileDirectory = paths[0] + fileDirectory = try XCTUnwrap(paths.first) fileURL = fileDirectory.appendingPathComponent("TestFile") filePath = fileURL?.path } @@ -32,9 +32,9 @@ class SentryFileIOTrackingIntegrationTests: XCTestCase { private var fixture: Fixture! var deleteFileDirectory = false - override func setUp() { - super.setUp() - fixture = Fixture() + override func setUpWithError() throws { + try super.setUpWithError() + fixture = try Fixture() if !FileManager.default.fileExists(atPath: fixture.fileDirectory.path) { try? FileManager.default.createDirectory(at: fixture.fileDirectory, withIntermediateDirectories: true, attributes: nil) diff --git a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift index d0c58e64520..d3badd78bac 100644 --- a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift @@ -202,7 +202,7 @@ class SentryNetworkTrackerIntegrationTests: XCTestCase { let children = Dynamic(transaction).children as [SentrySpan]? XCTAssertEqual(children?.count, 1) //Span was created in task resume swizzle. - let networkSpan = children![0] + let networkSpan = try XCTUnwrap(children?.first) let expectedTraceHeader = networkSpan.toTraceHeader().value() XCTAssertEqual(expectedTraceHeader, response) diff --git a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift index 04e56bb1740..b1353ea5741 100644 --- a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift @@ -687,8 +687,8 @@ class SentryNetworkTrackerTests: XCTestCase { let transaction = try XCTUnwrap(startTransaction() as? SentryTracer) sut.urlSessionTaskResume(task) - let children = Dynamic(transaction).children as [SentrySpan]? - let networkSpan = children![0] + let children = try XCTUnwrap(Dynamic(transaction).children.asArray as? [SentrySpan]) + let networkSpan = try XCTUnwrap(children.first) let expectedTraceHeader = networkSpan.toTraceHeader().value() XCTAssertEqual(task.currentRequest?.allHTTPHeaderFields?["sentry-trace"] ?? "", expectedTraceHeader) } diff --git a/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerPerformanceTrackerTests.swift b/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerPerformanceTrackerTests.swift index c022366a262..4c4e90ccfb8 100644 --- a/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerPerformanceTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerPerformanceTrackerTests.swift @@ -258,7 +258,7 @@ class SentryUIViewControllerPerformanceTrackerTests: XCTestCase { wait(for: [callbackExpectation], timeout: 0) } - func testReportFullyDisplayed() { + func testReportFullyDisplayed() throws { let sut = fixture.getSut() sut.enableWaitForFullDisplay = true let viewController = fixture.viewController @@ -277,9 +277,9 @@ class SentryUIViewControllerPerformanceTrackerTests: XCTestCase { reportFrame() let expectedTTFDTimestamp = fixture.dateProvider.date() - let ttfdSpan = tracer?.children[1] - XCTAssertEqual(ttfdSpan?.isFinished, true) - XCTAssertEqual(ttfdSpan?.timestamp, expectedTTFDTimestamp) + let ttfdSpan = try XCTUnwrap(tracer?.children.element(at: 1)) + XCTAssertEqual(ttfdSpan.isFinished, true) + XCTAssertEqual(ttfdSpan.timestamp, expectedTTFDTimestamp) } func testSecondViewController() { @@ -531,8 +531,8 @@ class SentryUIViewControllerPerformanceTrackerTests: XCTestCase { tracer = self.getStack(tracker).first as? SentryTracer } XCTAssertEqual(tracer?.children.count, 3) - XCTAssertEqual(tracer?.children[1].operation, "ui.load.full_display") - XCTAssertEqual(tracer?.children[1].origin, "manual.ui.time_to_display") + XCTAssertEqual(try XCTUnwrap(tracer?.children.element(at: 1)).operation, "ui.load.full_display") + XCTAssertEqual(try XCTUnwrap(tracer?.children.element(at: 1)).origin, "manual.ui.time_to_display") } func test_dontWaitForFullDisplay() { diff --git a/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerSwizzlingTests.swift b/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerSwizzlingTests.swift index 88079affad2..f11525dc60b 100644 --- a/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerSwizzlingTests.swift +++ b/Tests/SentryTests/Integrations/Performance/UIViewController/SentryUIViewControllerSwizzlingTests.swift @@ -151,7 +151,7 @@ class SentryUIViewControllerSwizzlingTests: XCTestCase { // UIScene is available from iOS 13 and above. if #available(iOS 13.0, tvOS 13.0, macCatalyst 13.0, *) { XCTAssertEqual(swizzler.viewControllers.count, 1) - XCTAssertTrue(swizzler.viewControllers[0] is TestViewController) + XCTAssertTrue(try XCTUnwrap(swizzler.viewControllers.first) is TestViewController) } else { XCTAssertEqual(swizzler.viewControllers.count, 0) } diff --git a/Tests/SentryTests/Integrations/Screenshot/SentryScreenshotIntegrationTests.swift b/Tests/SentryTests/Integrations/Screenshot/SentryScreenshotIntegrationTests.swift index f39be6b71df..841547aeb68 100644 --- a/Tests/SentryTests/Integrations/Screenshot/SentryScreenshotIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Screenshot/SentryScreenshotIntegrationTests.swift @@ -177,17 +177,17 @@ class SentryScreenshotIntegrationTests: XCTestCase { let newAttachmentList = sut.processAttachments([], for: event) ?? [] XCTAssertEqual(newAttachmentList.count, 3) - XCTAssertEqual(newAttachmentList[0].filename, "screenshot.png") - XCTAssertEqual(newAttachmentList[1].filename, "screenshot-2.png") - XCTAssertEqual(newAttachmentList[2].filename, "screenshot-3.png") + XCTAssertEqual(try XCTUnwrap(newAttachmentList.first).filename, "screenshot.png") + XCTAssertEqual(try XCTUnwrap(newAttachmentList.element(at: 1)).filename, "screenshot-2.png") + XCTAssertEqual(try XCTUnwrap(newAttachmentList.element(at: 2)).filename, "screenshot-3.png") - XCTAssertEqual(newAttachmentList[0].contentType, "image/png") - XCTAssertEqual(newAttachmentList[1].contentType, "image/png") - XCTAssertEqual(newAttachmentList[2].contentType, "image/png") + XCTAssertEqual(try XCTUnwrap(newAttachmentList.first).contentType, "image/png") + XCTAssertEqual(try XCTUnwrap(newAttachmentList.element(at: 1)).contentType, "image/png") + XCTAssertEqual(try XCTUnwrap(newAttachmentList.element(at: 2)).contentType, "image/png") - XCTAssertEqual(newAttachmentList[0].data?.count, 1) - XCTAssertEqual(newAttachmentList[1].data?.count, 2) - XCTAssertEqual(newAttachmentList[2].data?.count, 3) + XCTAssertEqual(try XCTUnwrap(newAttachmentList.first).data?.count, 1) + XCTAssertEqual(try XCTUnwrap(newAttachmentList.element(at: 1)).data?.count, 2) + XCTAssertEqual(try XCTUnwrap(newAttachmentList.element(at: 2)).data?.count, 3) } diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentryReplayRecordingTests.swift b/Tests/SentryTests/Integrations/SessionReplay/SentryReplayRecordingTests.swift index d6a12b404de..822caac2d02 100644 --- a/Tests/SentryTests/Integrations/SessionReplay/SentryReplayRecordingTests.swift +++ b/Tests/SentryTests/Integrations/SessionReplay/SentryReplayRecordingTests.swift @@ -4,15 +4,15 @@ import XCTest class SentryReplayRecordingTests: XCTestCase { - func test_serialize() { + func test_serialize() throws { let sut = SentryReplayRecording(segmentId: 3, size: 200, start: Date(timeIntervalSince1970: 2), duration: 5_000, frameCount: 5, frameRate: 1, height: 930, width: 390, extraEvents: nil) let data = sut.serialize() - let metaInfo = data[0] + let metaInfo = try XCTUnwrap(data.first) let metaInfoData = metaInfo["data"] as? [String: Any] - let recordingInfo = data[1] + let recordingInfo = try XCTUnwrap(data.element(at: 1)) let recordingData = recordingInfo["data"] as? [String: Any] let recordingPayload = recordingData?["payload"] as? [String: Any] @@ -38,7 +38,7 @@ class SentryReplayRecordingTests: XCTestCase { XCTAssertEqual(recordingPayload?["top"] as? Int, 0) } - func test_serializeWithExtra() { + func test_serializeWithExtra() throws { let date = Date(timeIntervalSince1970: 5) let sut = SentryReplayRecording(segmentId: 3, size: 200, start: Date(timeIntervalSince1970: 2), duration: 5_000, frameCount: 5, frameRate: 1, height: 930, width: 390, extraEvents: [ SentryRRWebEvent(type: .custom, timestamp: date, data: nil) @@ -46,7 +46,7 @@ class SentryReplayRecordingTests: XCTestCase { let data = sut.serialize() - let extraInfo = data[2] + let extraInfo = try XCTUnwrap(data.element(at: 2)) XCTAssertEqual(extraInfo["type"] as? Int, 5) XCTAssertEqual(extraInfo["timestamp"] as? Int, 5_000) } diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentrySRDefaultBreadcrumbConverterTests.swift b/Tests/SentryTests/Integrations/SessionReplay/SentrySRDefaultBreadcrumbConverterTests.swift index 60befc92bb9..bc4789ad201 100644 --- a/Tests/SentryTests/Integrations/SessionReplay/SentrySRDefaultBreadcrumbConverterTests.swift +++ b/Tests/SentryTests/Integrations/SessionReplay/SentrySRDefaultBreadcrumbConverterTests.swift @@ -147,4 +147,16 @@ class SentrySRDefaultBreadcrumbConverterTests: XCTestCase { XCTAssertEqual(payload["message"] as? String, "Custom message") XCTAssertEqual(payloadData["SomeInfo"] as? String, "Info") } + + func testSerializedSRBreadcrumbLevelIsString() throws { + let sut = SentrySRDefaultBreadcrumbConverter() + let breadcrumb = Breadcrumb() + breadcrumb.level = .error + + let result = try XCTUnwrap(sut.convert(from: breadcrumb) as? SentryRRWebBreadcrumbEvent) + let crumbData = try XCTUnwrap(result.data) + let payload = try XCTUnwrap(crumbData["payload"] as? [String: Any]) + + XCTAssertEqual(payload["level"] as! String, "error") + } } diff --git a/Tests/SentryTests/Integrations/SessionReplay/SentryTouchTrackerTests.swift b/Tests/SentryTests/Integrations/SessionReplay/SentryTouchTrackerTests.swift index c95a06a2854..d0fe9b53e29 100644 --- a/Tests/SentryTests/Integrations/SessionReplay/SentryTouchTrackerTests.swift +++ b/Tests/SentryTests/Integrations/SessionReplay/SentryTouchTrackerTests.swift @@ -140,7 +140,7 @@ class SentryTouchTrackerTests: XCTestCase { XCTAssertEqual(data?["source"] as? Int, 2) } - func testTrackTouchEventKeepSameIdAccrossEvents() { + func testTrackTouchEventKeepSameIdAccrossEvents() throws { let sut = getSut() let event = MockUIEvent(timestamp: 3) let touch = MockUITouch(phase: .began, location: CGPoint(x: 100, y: 100)) @@ -154,10 +154,10 @@ class SentryTouchTrackerTests: XCTestCase { sut.trackTouchFrom(event: event) let result = sut.replayEvents(from: referenceDate, until: referenceDate.addingTimeInterval(5)) - let firstEventFirstTouch = result[0].data - let firstEventSecondTouch = result[1].data - let secondEventFirstTouch = result[2].data - let secondEventSecondTouch = result[3].data + let firstEventFirstTouch = try XCTUnwrap(result.first).data + let firstEventSecondTouch = try XCTUnwrap(result.element(at: 1)).data + let secondEventFirstTouch = try XCTUnwrap(result.element(at: 2)).data + let secondEventSecondTouch = try XCTUnwrap(result.element(at: 3)).data XCTAssertEqual(firstEventFirstTouch?["pointerId"] as? Int, secondEventFirstTouch?["pointerId"] as? Int) XCTAssertEqual(firstEventSecondTouch?["pointerId"] as? Int, secondEventSecondTouch?["pointerId"] as? Int) diff --git a/Tests/SentryTests/Networking/RateLimits/SentryEnvelopeRateLimitTests.swift b/Tests/SentryTests/Networking/RateLimits/SentryEnvelopeRateLimitTests.swift index eaa597aad46..8c6a55c676c 100644 --- a/Tests/SentryTests/Networking/RateLimits/SentryEnvelopeRateLimitTests.swift +++ b/Tests/SentryTests/Networking/RateLimits/SentryEnvelopeRateLimitTests.swift @@ -74,7 +74,7 @@ class SentryEnvelopeRateLimitTests: XCTestCase { let actual = sut.removeRateLimitedItems(envelope) XCTAssertEqual(1, actual.items.count) - XCTAssertEqual(SentryEnvelopeItemTypeEvent, actual.items[0].header.type) + XCTAssertEqual(SentryEnvelopeItemTypeEvent, try XCTUnwrap(actual.items.first).header.type) } func getEnvelope() -> SentryEnvelope { diff --git a/Tests/SentryTests/Networking/SentryHttpTransportTests.swift b/Tests/SentryTests/Networking/SentryHttpTransportTests.swift index e4e799d703c..62366e822d9 100644 --- a/Tests/SentryTests/Networking/SentryHttpTransportTests.swift +++ b/Tests/SentryTests/Networking/SentryHttpTransportTests.swift @@ -444,7 +444,7 @@ class SentryHttpTransportTests: XCTestCase { let sessionRequest = try! SentryNSURLRequest(envelopeRequestWith: SentryHttpTransportTests.dsn(), andData: sessionData) if fixture.requestManager.requests.invocations.count > 3 { - XCTAssertEqual(sessionRequest.httpBody, fixture.requestManager.requests.invocations[3].httpBody, "Envelope with only session item should be sent.") + XCTAssertEqual(sessionRequest.httpBody, try XCTUnwrap(fixture.requestManager.requests.invocations.element(at: 3)).httpBody, "Envelope with only session item should be sent.") } else { XCTFail("Expected a fourth invocation") } @@ -470,10 +470,10 @@ class SentryHttpTransportTests: XCTestCase { fixture.requestManager.waitForAllRequests() XCTAssertEqual(3, fixture.requestManager.requests.count) - XCTAssertEqual(fixture.eventWithAttachmentRequest.httpBody, fixture.requestManager.requests.invocations[1].httpBody, "Cached envelope was not sent first.") + XCTAssertEqual(fixture.eventWithAttachmentRequest.httpBody, try XCTUnwrap(fixture.requestManager.requests.invocations.element(at: 1)).httpBody, "Cached envelope was not sent first.") if fixture.requestManager.requests.invocations.count > 2 { - XCTAssertEqual(fixture.sessionRequest.httpBody, fixture.requestManager.requests.invocations[2].httpBody, "Cached envelope was not sent first.") + XCTAssertEqual(fixture.sessionRequest.httpBody, try XCTUnwrap(fixture.requestManager.requests.invocations.element(at: 2)).httpBody, "Cached envelope was not sent first.") } else { XCTFail("Expected a third invocation") } diff --git a/Tests/SentryTests/Protocol/SentryClientReportTests.swift b/Tests/SentryTests/Protocol/SentryClientReportTests.swift index 7bf9cec91c5..9e08c788ac3 100644 --- a/Tests/SentryTests/Protocol/SentryClientReportTests.swift +++ b/Tests/SentryTests/Protocol/SentryClientReportTests.swift @@ -30,8 +30,8 @@ class SentryClientReportTests: XCTestCase { XCTAssertEqual(category, event["category"] as? String) XCTAssertEqual(quantity, event["quantity"] as? UInt) } - assertEvent(event: discardedEvents[0], reason: "sample_rate", category: "transaction", quantity: event1.quantity) - assertEvent(event: discardedEvents[1], reason: "before_send", category: "transaction", quantity: event2.quantity) - assertEvent(event: discardedEvents[2], reason: "ratelimit_backoff", category: "error", quantity: event3.quantity) + assertEvent(event: try XCTUnwrap(discardedEvents.first), reason: "sample_rate", category: "transaction", quantity: event1.quantity) + assertEvent(event: try XCTUnwrap(discardedEvents.element(at: 1)), reason: "before_send", category: "transaction", quantity: event2.quantity) + assertEvent(event: try XCTUnwrap(discardedEvents.element(at: 2)), reason: "ratelimit_backoff", category: "error", quantity: event3.quantity) } } diff --git a/Tests/SentryTests/Protocol/SentryEnvelopeTests.swift b/Tests/SentryTests/Protocol/SentryEnvelopeTests.swift index 3af8e3fd0dc..c5f2648aebe 100644 --- a/Tests/SentryTests/Protocol/SentryEnvelopeTests.swift +++ b/Tests/SentryTests/Protocol/SentryEnvelopeTests.swift @@ -68,7 +68,7 @@ class SentryEnvelopeTests: XCTestCase { private let defaultSdkInfo = SentrySdkInfo(name: SentryMeta.sdkName, andVersion: SentryMeta.versionString) - func testSentryEnvelopeFromEvent() { + func testSentryEnvelopeFromEvent() throws { let event = Event() let item = SentryEnvelopeItem(event: event) @@ -76,11 +76,11 @@ class SentryEnvelopeTests: XCTestCase { XCTAssertEqual(event.eventId, envelope.header.eventId) XCTAssertEqual(1, envelope.items.count) - XCTAssertEqual("event", envelope.items[0].header.type) + XCTAssertEqual("event", try XCTUnwrap(envelope.items.first).header.type) let json = try! JSONSerialization.data(withJSONObject: event.serialize(), options: JSONSerialization.WritingOptions(rawValue: 0)) - assertJsonIsEqual(actual: json, expected: envelope.items[0].data) + assertJsonIsEqual(actual: json, expected: try XCTUnwrap(envelope.items.first).data) } func testSentryEnvelopeWithExplicitInitMessages() { @@ -96,10 +96,10 @@ class SentryEnvelopeTests: XCTestCase { XCTAssertEqual(envelopeId, envelope.header.eventId) XCTAssertEqual(1, envelope.items.count) - XCTAssertEqual("attachment", envelope.items[0].header.type) - XCTAssertEqual(attachment.count, Int(envelope.items[0].header.length)) + XCTAssertEqual("attachment", try XCTUnwrap(envelope.items.first).header.type) + XCTAssertEqual(attachment.count, Int(try XCTUnwrap(envelope.items.first).header.length)) - XCTAssertEqual(data, envelope.items[0].data) + XCTAssertEqual(data, try XCTUnwrap(envelope.items.first).data) } func testSentryEnvelopeWithExplicitInitMessagesMultipleItems() { diff --git a/Tests/SentryTests/Protocol/SentryIdTests.swift b/Tests/SentryTests/Protocol/SentryIdTests.swift index 33b0a3be439..72ad75c7c8c 100644 --- a/Tests/SentryTests/Protocol/SentryIdTests.swift +++ b/Tests/SentryTests/Protocol/SentryIdTests.swift @@ -22,6 +22,12 @@ class SentryIdTests: XCTestCase { func testInit() { XCTAssertNotEqual(SentryId(), SentryId()) } + + func testInitFromString() { + let string = "abcdefabcdefabcdefabcdefabcdefab" + let sentryId = SentryId(uuidString: "abcdefabcdefabcdefabcdefabcdefab") + XCTAssertEqual(sentryId.sentryIdString, string) + } func testInitWithUUID_ValidIdString() { let sentryId = SentryId(uuid: fixture.uuid) diff --git a/Tests/SentryTests/RedactRegionTests.swift b/Tests/SentryTests/RedactRegionTests.swift index 81bf02d85dc..63a37e4297d 100644 --- a/Tests/SentryTests/RedactRegionTests.swift +++ b/Tests/SentryTests/RedactRegionTests.swift @@ -30,7 +30,7 @@ class RedactRegionTests: XCTestCase { XCTAssertEqual(result.count, 2) XCTAssertEqual(result.first?.rect, CGRect(x: 0, y: 50, width: 100, height: 50)) - XCTAssertEqual(result[1].rect, CGRect(x: 0, y: 0, width: 50, height: 50)) + XCTAssertEqual(try XCTUnwrap(result.element(at: 1)).rect, CGRect(x: 0, y: 0, width: 50, height: 50)) } func testSplitBySubtractingBottomLeft() { @@ -40,7 +40,7 @@ class RedactRegionTests: XCTestCase { XCTAssertEqual(result.count, 2) XCTAssertEqual(result.first?.rect, CGRect(x: 0, y: 0, width: 100, height: 50)) - XCTAssertEqual(result[1].rect, CGRect(x: 50, y: 50, width: 50, height: 50)) + XCTAssertEqual(try XCTUnwrap(result.element(at: 1)).rect, CGRect(x: 50, y: 50, width: 50, height: 50)) } func testSplitBySubtractingMiddle() { @@ -49,10 +49,10 @@ class RedactRegionTests: XCTestCase { let result = sut.splitBySubtracting(region: CGRect(x: 25, y: 25, width: 50, height: 50)) XCTAssertEqual(result.count, 4) - XCTAssertEqual(result[0].rect, CGRect(x: 0, y: 0, width: 100, height: 25)) - XCTAssertEqual(result[1].rect, CGRect(x: 0, y: 75, width: 100, height: 25)) - XCTAssertEqual(result[2].rect, CGRect(x: 0, y: 25, width: 25, height: 50)) - XCTAssertEqual(result[3].rect, CGRect(x: 75, y: 25, width: 25, height: 50)) + XCTAssertEqual(try XCTUnwrap(result.first).rect, CGRect(x: 0, y: 0, width: 100, height: 25)) + XCTAssertEqual(try XCTUnwrap(result.element(at: 1)).rect, CGRect(x: 0, y: 75, width: 100, height: 25)) + XCTAssertEqual(try XCTUnwrap(result.element(at: 2)).rect, CGRect(x: 0, y: 25, width: 25, height: 50)) + XCTAssertEqual(try XCTUnwrap(result.element(at: 3)).rect, CGRect(x: 75, y: 25, width: 25, height: 50)) } func testSplitBySubtractingInHalfHorizontally() { @@ -61,8 +61,8 @@ class RedactRegionTests: XCTestCase { let result = sut.splitBySubtracting(region: CGRect(x: 0, y: 25, width: 100, height: 50)) XCTAssertEqual(result.count, 2) - XCTAssertEqual(result[0].rect, CGRect(x: 0, y: 0, width: 100, height: 25)) - XCTAssertEqual(result[1].rect, CGRect(x: 0, y: 75, width: 100, height: 25)) + XCTAssertEqual(try XCTUnwrap(result.first).rect, CGRect(x: 0, y: 0, width: 100, height: 25)) + XCTAssertEqual(try XCTUnwrap(result.element(at: 1)).rect, CGRect(x: 0, y: 75, width: 100, height: 25)) } func testSplitBySubtractingInHalfVertically() { @@ -71,8 +71,8 @@ class RedactRegionTests: XCTestCase { let result = sut.splitBySubtracting(region: CGRect(x: 25, y: 0, width: 50, height: 100)) XCTAssertEqual(result.count, 2) - XCTAssertEqual(result[0].rect, CGRect(x: 0, y: 0, width: 25, height: 100)) - XCTAssertEqual(result[1].rect, CGRect(x: 75, y: 0, width: 25, height: 100)) + XCTAssertEqual(try XCTUnwrap(result.first).rect, CGRect(x: 0, y: 0, width: 25, height: 100)) + XCTAssertEqual(try XCTUnwrap(result.element(at: 1)).rect, CGRect(x: 75, y: 0, width: 25, height: 100)) } func testSplitBySubtractingMiddleRight() { @@ -81,9 +81,9 @@ class RedactRegionTests: XCTestCase { let result = sut.splitBySubtracting(region: CGRect(x: 25, y: 25, width: 100, height: 50)) XCTAssertEqual(result.count, 3) - XCTAssertEqual(result[0].rect, CGRect(x: 0, y: 0, width: 100, height: 25)) - XCTAssertEqual(result[1].rect, CGRect(x: 0, y: 75, width: 100, height: 25)) - XCTAssertEqual(result[2].rect, CGRect(x: 0, y: 25, width: 25, height: 50)) + XCTAssertEqual(try XCTUnwrap(result.first).rect, CGRect(x: 0, y: 0, width: 100, height: 25)) + XCTAssertEqual(try XCTUnwrap(result.element(at: 1)).rect, CGRect(x: 0, y: 75, width: 100, height: 25)) + XCTAssertEqual(try XCTUnwrap(result.element(at: 2)).rect, CGRect(x: 0, y: 25, width: 25, height: 50)) } func testSplitBySubtractingMiddleLeft() { @@ -92,9 +92,9 @@ class RedactRegionTests: XCTestCase { let result = sut.splitBySubtracting(region: CGRect(x: 0, y: 25, width: 100, height: 50)) XCTAssertEqual(result.count, 3) - XCTAssertEqual(result[0].rect, CGRect(x: 50, y: 0, width: 100, height: 25)) - XCTAssertEqual(result[1].rect, CGRect(x: 50, y: 75, width: 100, height: 25)) - XCTAssertEqual(result[2].rect, CGRect(x: 100, y: 25, width: 50, height: 50)) + XCTAssertEqual(try XCTUnwrap(result.first).rect, CGRect(x: 50, y: 0, width: 100, height: 25)) + XCTAssertEqual(try XCTUnwrap(result.element(at: 1)).rect, CGRect(x: 50, y: 75, width: 100, height: 25)) + XCTAssertEqual(try XCTUnwrap(result.element(at: 2)).rect, CGRect(x: 100, y: 25, width: 50, height: 50)) } func testSplitBySubtracting_TopIsWider() { diff --git a/Tests/SentryTests/SentryBinaryImageCacheTests.swift b/Tests/SentryTests/SentryBinaryImageCacheTests.swift index e02ed23128e..48f88b6a9a5 100644 --- a/Tests/SentryTests/SentryBinaryImageCacheTests.swift +++ b/Tests/SentryTests/SentryBinaryImageCacheTests.swift @@ -33,13 +33,13 @@ class SentryBinaryImageCacheTests: XCTestCase { sut.binaryImageAdded(&binaryImage2) XCTAssertEqual(sut.cache.count, 3) XCTAssertEqual(sut.cache.first?.name, "Expected Name at 100") - XCTAssertEqual(sut.cache[1].name, "Expected Name at 200") + XCTAssertEqual(try XCTUnwrap(sut.cache.element(at: 1)).name, "Expected Name at 200") XCTAssertEqual(sut.cache.last?.name, "Expected Name at 400") sut.binaryImageAdded(&binaryImage0) XCTAssertEqual(sut.cache.count, 4) XCTAssertEqual(sut.cache.first?.name, "Expected Name at 0") - XCTAssertEqual(sut.cache[1].name, "Expected Name at 100") + XCTAssertEqual(try XCTUnwrap(sut.cache.element(at: 1)).name, "Expected Name at 100") } func testBinaryImageAdded_IsNull() { diff --git a/Tests/SentryTests/SentryClientTests.swift b/Tests/SentryTests/SentryClientTests.swift index 43a69c416dc..fd73b3b5f55 100644 --- a/Tests/SentryTests/SentryClientTests.swift +++ b/Tests/SentryTests/SentryClientTests.swift @@ -665,7 +665,7 @@ class SentryClientTest: XCTestCase { } } - func testCaptureErrorWithSession_WithBeforeSendReturnsNil() { + func testCaptureErrorWithSession_WithBeforeSendReturnsNil() throws { let sessionBlockExpectation = expectation(description: "session block does not get called") sessionBlockExpectation.isInverted = true @@ -679,7 +679,6 @@ class SentryClientTest: XCTestCase { wait(for: [sessionBlockExpectation], timeout: 0.2) eventId.assertIsEmpty() - assertLastSentEnvelopeIsASession() } func testCaptureCrashEventWithSession() throws { @@ -934,15 +933,20 @@ class SentryClientTest: XCTestCase { } } - func testCaptureExceptionWithSession_WithBeforeSendReturnsNil() { + func testCaptureExceptionWithSession_WithBeforeSendReturnsNil() throws { + let sessionBlockExpectation = expectation(description: "session block does not get called") + sessionBlockExpectation.isInverted = true + let eventId = fixture.getSut(configureOptions: { options in options.beforeSend = { _ in return nil } }).capture(exception, with: fixture.scope) { - self.fixture.session + // This should NOT be called + sessionBlockExpectation.fulfill() + return self.fixture.session } + wait(for: [sessionBlockExpectation], timeout: 0.2) eventId.assertIsEmpty() - assertLastSentEnvelopeIsASession() } func testCaptureExceptionWithUserInfo() throws { @@ -963,11 +967,14 @@ class SentryClientTest: XCTestCase { XCTAssertEqual(fixture.environment, actual.environment) } - func testCaptureSession() { + func testCaptureSession() throws { let session = SentrySession(releaseName: "release", distinctId: "some-id") fixture.getSut().capture(session: session) - - assertLastSentEnvelopeIsASession() + + XCTAssertNotNil(fixture.transport.sentEnvelopes) + let actual = try XCTUnwrap(fixture.transport.sentEnvelopes.last) + XCTAssertEqual(1, actual.items.count) + XCTAssertEqual("session", try XCTUnwrap(actual.items.first).header.type) } func testCaptureSessionWithoutReleaseName() { @@ -1617,7 +1624,7 @@ class SentryClientTest: XCTestCase { sut.capture(replayEvent, replayRecording: replayRecording, video: movieUrl!, with: Scope()) let envelope = fixture.transport.sentEnvelopes.first - XCTAssertEqual(envelope?.items[0].header.type, SentryEnvelopeItemTypeReplayVideo) + XCTAssertEqual(try XCTUnwrap(envelope?.items.first).header.type, SentryEnvelopeItemTypeReplayVideo) } func testCaptureReplayEvent_WrongEventFromEventProcessor() { @@ -1754,7 +1761,7 @@ private extension SentryClientTest { XCTFail("Event should contain one exception"); return } XCTAssertEqual(1, exceptions.count) - let exception = exceptions[0] + let exception = try XCTUnwrap(exceptions.first) XCTAssertEqual(expectedError.domain, exception.type) XCTAssertEqual(exceptionValue ?? "Code: \(expectedError.code)", exception.value) @@ -1781,20 +1788,6 @@ private extension SentryClientTest { assertValidThreads(actual: event.threads) } - private func assertLastSentEnvelope(assert: (SentryEnvelope) -> Void) { - XCTAssertNotNil(fixture.transport.sentEnvelopes) - if let lastSentEnvelope = fixture.transport.sentEnvelopes.last { - assert(lastSentEnvelope) - } - } - - private func assertLastSentEnvelopeIsASession() { - assertLastSentEnvelope { actual in - XCTAssertEqual(1, actual.items.count) - XCTAssertEqual("session", actual.items[0].header.type) - } - } - private func assertValidDebugMeta(actual: [DebugMeta]?, forThreads threads: [SentryThread]?) { let debugMetas = fixture.debugImageBuilder.getDebugImages(for: threads ?? [], isCrash: false) diff --git a/Tests/SentryTests/SentryCrash/SentryCrashLogger_Tests.m b/Tests/SentryTests/SentryCrash/SentryCrashLogger_Tests.m deleted file mode 100644 index 9c846fbb5c6..00000000000 --- a/Tests/SentryTests/SentryCrash/SentryCrashLogger_Tests.m +++ /dev/null @@ -1,98 +0,0 @@ -// Adapted from: https://github.com/kstenerud/KSCrash -// -// SentryCrashLogger_Tests.m -// -// Created by Karl Stenerud on 2013-01-26. -// -// Copyright (c) 2012 Karl Stenerud. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall remain in place -// in this source code. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// - -#import "XCTestCase+SentryCrash.h" -#import - -#import "SentryCrashLogger.h" - -@interface SentryCrashLogger_Tests : XCTestCase - -@property (nonatomic, readwrite, retain) NSString *tempDir; - -@end - -@implementation SentryCrashLogger_Tests - -@synthesize tempDir = _tempDir; - -- (void)setUp -{ - [super setUp]; - self.tempDir = [self createTempPath]; -} - -- (void)tearDown -{ - [self removePath:self.tempDir]; -} - -- (void)testLogError -{ - SentryCrashLOG_ERROR(@"TEST"); -} - -- (void)testLogErrorNull -{ - NSString *str = nil; - SentryCrashLOG_ERROR(str); -} - -- (void)testLogAlways -{ - SentryCrashLOG_ALWAYS(@"TEST"); -} - -- (void)testLogAlwaysNull -{ - NSString *str = nil; - SentryCrashLOG_ALWAYS(str); -} - -- (void)testLogBasicError -{ - SentryCrashLOGBASIC_ERROR(@"TEST"); -} - -- (void)testLogBasicErrorNull -{ - NSString *str = nil; - SentryCrashLOGBASIC_ERROR(str); -} - -- (void)testLogBasicAlways -{ - SentryCrashLOGBASIC_ALWAYS(@"TEST"); -} - -- (void)testLogBasicAlwaysNull -{ - NSString *str = nil; - SentryCrashLOGBASIC_ALWAYS(str); -} - -@end diff --git a/Tests/SentryTests/SentryCrash/SentryDebugImageProviderTests.swift b/Tests/SentryTests/SentryCrash/SentryDebugImageProviderTests.swift index 5cc2576bed6..14d578f2d09 100644 --- a/Tests/SentryTests/SentryCrash/SentryDebugImageProviderTests.swift +++ b/Tests/SentryTests/SentryCrash/SentryDebugImageProviderTests.swift @@ -55,17 +55,17 @@ class SentryDebugImageProviderTests: XCTestCase { private let fixture = Fixture() - func testThreeImages() { + func testThreeImages() throws { let sut = fixture.getSut(images: fixture.getTestImages()) let actual = sut.getDebugImagesCrashed(false) XCTAssertEqual(3, actual.count) - XCTAssertEqual("dyld_sim", actual[0].codeFile) - XCTAssertEqual("UIKit", actual[1].codeFile) - XCTAssertEqual("CoreData", actual[2].codeFile) + XCTAssertEqual("dyld_sim", try XCTUnwrap(actual.first).codeFile) + XCTAssertEqual("UIKit", try XCTUnwrap(actual.element(at: 1)).codeFile) + XCTAssertEqual("CoreData", try XCTUnwrap(actual.element(at: 2)).codeFile) - let debugMeta = actual[0] + let debugMeta = try XCTUnwrap(actual.first) XCTAssertEqual("84BAEBDA-AD1A-33F4-B35D-8A45F5DAF322", debugMeta.debugID) XCTAssertEqual("0x0000000105705000", debugMeta.imageAddress) XCTAssertEqual("0x00007fff51af0000", debugMeta.imageVmAddress) @@ -79,7 +79,7 @@ class SentryDebugImageProviderTests: XCTestCase { let sut = fixture.getSut(images: [image]) let actual = sut.getDebugImagesCrashed(false) - XCTAssertNil(actual[0].imageVmAddress) + XCTAssertNil(try XCTUnwrap(actual.first).imageVmAddress) } func testImageSize() { @@ -87,7 +87,7 @@ class SentryDebugImageProviderTests: XCTestCase { let image = SentryDebugImageProviderTests.createSentryCrashBinaryImage(size: value) let sut = fixture.getSut(images: [image]) let actual = sut.getDebugImagesCrashed(false) - XCTAssertEqual(NSNumber(value: value), actual[0].imageSize) + XCTAssertEqual(NSNumber(value: value), try XCTUnwrap(actual.first).imageSize) } testWith(value: 0) @@ -95,22 +95,22 @@ class SentryDebugImageProviderTests: XCTestCase { testWith(value: UINT64_MAX) } - func testImageAddress() { - func testWith(value: UInt64, expected: String) { + func testImageAddress() throws { + func testWith(value: UInt64, expected: String) throws { let image = SentryDebugImageProviderTests.createSentryCrashBinaryImage(address: value) let sut = fixture.getSut(images: [image]) let actual = sut.getDebugImagesCrashed(false) XCTAssertEqual(1, actual.count) - let debugMeta = actual[0] + let debugMeta = try XCTUnwrap(actual.first) XCTAssertEqual(expected, debugMeta.imageAddress) } - testWith(value: UINT64_MAX, expected: "0xffffffffffffffff") - testWith(value: 0, expected: "0x0000000000000000") - testWith(value: 0, expected: "0x0000000000000000") - testWith(value: 4_361_940_992, expected: "0x0000000103fdf000") + try testWith(value: UINT64_MAX, expected: "0xffffffffffffffff") + try testWith(value: 0, expected: "0x0000000000000000") + try testWith(value: 0, expected: "0x0000000000000000") + try testWith(value: 4_361_940_992, expected: "0x0000000103fdf000") } func testNoImages() { @@ -130,8 +130,8 @@ class SentryDebugImageProviderTests: XCTestCase { var actual = sut.getDebugImages(for: [thread], isCrash: false) XCTAssertEqual(actual.count, 1) - XCTAssertEqual(actual[0].codeFile, "dyld_sim") - XCTAssertEqual(actual[0].imageAddress, "0x0000000105705000") + XCTAssertEqual(try XCTUnwrap(actual.first).codeFile, "dyld_sim") + XCTAssertEqual(try XCTUnwrap(actual.first).imageAddress, "0x0000000105705000") let frame2 = Sentry.Frame() frame2.imageAddress = "0x00000001410b1a00" @@ -142,11 +142,11 @@ class SentryDebugImageProviderTests: XCTestCase { actual = sut.getDebugImages(for: [thread], isCrash: false) XCTAssertEqual(actual.count, 2) - XCTAssertEqual(actual[0].codeFile, "UIKit") - XCTAssertEqual(actual[0].imageAddress, "0x00000001410b1a00") + XCTAssertEqual(try XCTUnwrap(actual.first).codeFile, "UIKit") + XCTAssertEqual(try XCTUnwrap(actual.first).imageAddress, "0x00000001410b1a00") - XCTAssertEqual(actual[1].codeFile, "CoreData") - XCTAssertEqual(actual[1].imageAddress, "0x000000017ca5e400") + XCTAssertEqual(try XCTUnwrap(actual.element(at: 1)).codeFile, "CoreData") + XCTAssertEqual(try XCTUnwrap(actual.element(at: 1)).imageAddress, "0x000000017ca5e400") } func test_NoImage_ForThread_WithoutStackTrace() { diff --git a/Tests/SentryTests/SentryCrash/SentryThreadInspectorTests.swift b/Tests/SentryTests/SentryCrash/SentryThreadInspectorTests.swift index a0930392380..0e419292ee0 100644 --- a/Tests/SentryTests/SentryCrash/SentryThreadInspectorTests.swift +++ b/Tests/SentryTests/SentryCrash/SentryThreadInspectorTests.swift @@ -39,9 +39,9 @@ class SentryThreadInspectorTests: XCTestCase { XCTAssertEqual(0, actual.count) } - func testStacktraceHasFrames() { + func testStacktraceHasFrames() throws { let actual = fixture.getSut(testWithRealMachineContextWrapper: true).getCurrentThreads() - let stacktrace = actual[0].stacktrace + let stacktrace = try XCTUnwrap(actual.first).stacktrace // The stacktrace has usually more than 40 frames. Feel free to change the number if the tests are failing XCTAssertTrue(30 < stacktrace?.frames.count ?? 0, "Not enough stacktrace frames.") @@ -178,19 +178,19 @@ class SentryThreadInspectorTests: XCTestCase { XCTAssertEqual(stackTrace.frames.first?.function, "") } - func testOnlyCurrentThreadHasStacktrace() { + func testOnlyCurrentThreadHasStacktrace() throws { let actual = fixture.getSut(testWithRealMachineContextWrapper: true).getCurrentThreads() - XCTAssertEqual(true, actual[0].current) - XCTAssertNotNil(actual[0].stacktrace) + XCTAssertEqual(true, try XCTUnwrap(actual.first).current) + XCTAssertNotNil(try XCTUnwrap(actual.first).stacktrace) - XCTAssertEqual(false, actual[1].current) - XCTAssertNil(actual[1].stacktrace) + XCTAssertEqual(false, try XCTUnwrap(actual.element(at: 1)).current) + XCTAssertNil(try XCTUnwrap(actual.element(at: 1)).stacktrace) } - func testOnlyFirstThreadIsCurrent() { + func testOnlyFirstThreadIsCurrent() throws { let actual = fixture.getSut(testWithRealMachineContextWrapper: true).getCurrentThreads() - let thread0 = actual[0] + let thread0 = try XCTUnwrap(actual.first) XCTAssertEqual(true, thread0.current) let threadCount = actual.count @@ -199,10 +199,10 @@ class SentryThreadInspectorTests: XCTestCase { } } - func testStacktraceOnlyForCurrentThread() { + func testStacktraceOnlyForCurrentThread() throws { let actual = fixture.getSut(testWithRealMachineContextWrapper: true).getCurrentThreads() - XCTAssertNotNil(actual[0].stacktrace) + XCTAssertNotNil(try XCTUnwrap(actual.first).stacktrace) let threadCount = actual.count for i in 1.. Void) { + func assertEventWithScopeCaptured(_ callback: (Event?, Scope?, [SentryEnvelopeItem]?) throws -> Void) throws { guard let client = SentrySDK.currentHub().getClient() as? TestClient else { XCTFail("Hub Client is not a `TestClient`") return @@ -60,7 +60,7 @@ class SentrySDKIntegrationTestsBase: XCTestCase { XCTAssertEqual(1, client.captureEventWithScopeInvocations.count, "More than one `Event` captured.") let capture = client.captureEventWithScopeInvocations.first - callback(capture?.event, capture?.scope, capture?.additionalEnvelopeItems) + try callback(capture?.event, capture?.scope, capture?.additionalEnvelopeItems) } func lastErrorWithScopeCaptured(_ callback: (Error?, Scope?) -> Void) { diff --git a/Tests/SentryTests/SentryScreenShotTests.swift b/Tests/SentryTests/SentryScreenShotTests.swift index 4ad3f778bc1..924da3f2b04 100644 --- a/Tests/SentryTests/SentryScreenShotTests.swift +++ b/Tests/SentryTests/SentryScreenShotTests.swift @@ -68,12 +68,12 @@ class SentryScreenShotTests: XCTestCase { XCTAssertTrue(drawSecondWindow) } - func test_image_size() { + func test_image_size() throws { let testWindow = TestWindow(frame: CGRect(x: 0, y: 0, width: 10, height: 10)) fixture.uiApplication.windows = [testWindow] let data = self.fixture.sut.appScreenshots() - let image = UIImage(data: data[0]) + let image = UIImage(data: try XCTUnwrap(data.first)) XCTAssertEqual(image?.size.width, 10) XCTAssertEqual(image?.size.height, 10) diff --git a/Tests/SentryTests/StringExtensionTests.swift b/Tests/SentryTests/StringExtensionTests.swift deleted file mode 100644 index 1a22b0ee3bf..00000000000 --- a/Tests/SentryTests/StringExtensionTests.swift +++ /dev/null @@ -1,44 +0,0 @@ -import Foundation -@testable import Sentry -import XCTest - -class StringExtensionTests: XCTestCase { - - func testSingleCharacterSubscript() { - let testString = "Hello, World!" - XCTAssertEqual(testString[0], "H") - XCTAssertEqual(testString[7], "W") - XCTAssertEqual(testString[12], "!") - } - - func testRangeOfCharactersSubscript() { - let testString = "Hello, World!" - XCTAssertEqual(testString[1..<5], "ello") - XCTAssertEqual(testString[7...11], "World") - XCTAssertEqual(testString[3...3], "l") - XCTAssertEqual(testString[1...5], "ello,") - XCTAssertEqual(testString[7...11], "World") - XCTAssertEqual(testString[0...0], "H") - } - - func testPartialRangeThroughSubscript() { - let testString = "Hello, World!" - XCTAssertEqual(testString[...5], "Hello,") - XCTAssertEqual(testString[...4], "Hello") - XCTAssertEqual(testString[...0], "H") - } - - func testPartialRangeFromSubscript() { - let testString = "Hello, World!" - XCTAssertEqual(testString[7...], "World!") - XCTAssertEqual(testString[0...], "Hello, World!") - XCTAssertEqual(testString[5...], ", World!") - } - - func testPartialRangeUpToSubscript() { - let testString = "Hello, World!" - XCTAssertEqual(testString[..<5], "Hello") - XCTAssertEqual(testString[..<4], "Hell") - XCTAssertEqual(testString[..<0], "") - } -} diff --git a/Tests/SentryTests/Swift/Metrics/BucketMetricsAggregatorTests.swift b/Tests/SentryTests/Swift/Metrics/BucketMetricsAggregatorTests.swift index 631add93809..7eb48087652 100644 --- a/Tests/SentryTests/Swift/Metrics/BucketMetricsAggregatorTests.swift +++ b/Tests/SentryTests/Swift/Metrics/BucketMetricsAggregatorTests.swift @@ -219,7 +219,7 @@ final class BucketMetricsAggregatorTests: XCTestCase { sut.increment(key: "key5", value: 1.0, unit: MeasurementUnitDuration.day, tags: [:]) XCTAssertEqual(metricsClient.captureInvocations.count, 2) - let buckets2 = try XCTUnwrap(metricsClient.captureInvocations.invocations[1]) + let buckets2 = try XCTUnwrap(try XCTUnwrap(metricsClient.captureInvocations.invocations.element(at: 1))) XCTAssertEqual(buckets2.count, 1) let bucket = try XCTUnwrap(buckets2.first) diff --git a/Tests/SentryTests/Transaction/SentrySpanTests.swift b/Tests/SentryTests/Transaction/SentrySpanTests.swift index e5cfa335b10..0133c8eeb66 100644 --- a/Tests/SentryTests/Transaction/SentrySpanTests.swift +++ b/Tests/SentryTests/Transaction/SentrySpanTests.swift @@ -376,7 +376,7 @@ class SentrySpanTests: XCTestCase { let serializedData = lastEvent.serialize() let spans = try XCTUnwrap(serializedData["spans"] as? [Any]) - let serializedChild = try XCTUnwrap(spans[0] as? [String: Any]) + let serializedChild = try XCTUnwrap(spans.first as? [String: Any]) XCTAssertEqual(serializedChild["span_id"] as? String, childSpan.spanId.sentrySpanIdString) XCTAssertEqual(serializedChild["parent_span_id"] as? String, span.spanId.sentrySpanIdString) diff --git a/Tests/SentryTests/Transaction/SentryTransactionTests.swift b/Tests/SentryTests/Transaction/SentryTransactionTests.swift index a61ba9de76c..f689d02a18c 100644 --- a/Tests/SentryTests/Transaction/SentryTransactionTests.swift +++ b/Tests/SentryTests/Transaction/SentryTransactionTests.swift @@ -222,9 +222,6 @@ class SentryTransactionTests: XCTestCase { } #if os(iOS) || os(macOS) || targetEnvironment(macCatalyst) - // test that when a trace runs concurrently with the continuous profiler - // and is serialized to a transaction, that it contains the profile id at - // the keypath contexts.trace.data.profile_id func testTransactionWithContinuousProfile() throws { SentrySDK.setStart(Options()) let transaction = fixture.getTransaction() @@ -232,9 +229,8 @@ class SentryTransactionTests: XCTestCase { let profileId = try XCTUnwrap(SentryContinuousProfiler.profiler()?.profilerId.sentryIdString) let serialized = transaction.serialize() let contexts = try XCTUnwrap(serialized["contexts"] as? [String: Any]) - let trace = try XCTUnwrap(contexts["trace"] as? [String: Any]) - let data = try XCTUnwrap(trace["data"] as? [String: Any]) - let profileIdFromContexts = try XCTUnwrap(data["profiler_id"] as? String) + let profileData = try XCTUnwrap(contexts["profile"] as? [String: Any]) + let profileIdFromContexts = try XCTUnwrap(profileData["profiler_id"] as? String) XCTAssertEqual(profileId, profileIdFromContexts) } #endif // os(iOS) || os(macOS) || targetEnvironment(macCatalyst) diff --git a/develop-docs/README.md b/develop-docs/README.md index 7608a729970..e087fa93367 100644 --- a/develop-docs/README.md +++ b/develop-docs/README.md @@ -110,7 +110,7 @@ This feature is experimental and is currently not compatible with SPM. ## Logging -We have a set of macros for debugging at various levels defined in SentryLog.h. These are not async-safe; to log from special places like crash handlers, see SentryCrashLogger.h; see the headerdocs in that header for how to work with those logging macros. There are also separate macros in SentryProfilingLogging.hpp specifically for the profiler; these are completely compiled out of release builds due to https://github.com/getsentry/sentry-cocoa/issues/3336. +We have a set of macros for logging at various levels defined in SentryLog.h. These are not async-safe because they use NSLog, which takes its own lock; to log from special places like crash handlers, see SentryAsyncSafeLog.h. By default, it only writes to file. If you'll be debuggin, you can set `SENTRY_ASYNC_SAFE_LOG_ALSO_WRITE_TO_CONSOLE` to `1` and logs will also write to the console, but note this is unsafe to do from contexts that actually require async safety, so this should always remain disabled in version control by leaving it set it to `0`. ## Profiling