From 90ab170c5fc6a89717d70ad2e4cae07d50c8d0c8 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Mon, 7 Nov 2022 09:39:38 +0100 Subject: [PATCH 01/13] test: Delete empty OOMLogicTests (#2361) The class has no tests and can be removed. --- Sentry.xcodeproj/project.pbxproj | 4 -- .../SentryOutOfMemoryLogicTests.swift | 55 ------------------- 2 files changed, 59 deletions(-) delete mode 100644 Tests/SentryTests/Integrations/OutOfMemory/SentryOutOfMemoryLogicTests.swift diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 163e4c08a46..f358e4e2db9 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -571,7 +571,6 @@ 7BF9EF862722D10600B5BBEF /* SentryTestObjCRuntimeWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BF9EF852722D10600B5BBEF /* SentryTestObjCRuntimeWrapper.h */; }; 7BF9EF882722D13000B5BBEF /* SentryTestObjCRuntimeWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BF9EF872722D13000B5BBEF /* SentryTestObjCRuntimeWrapper.m */; }; 7BF9EF8B2722D58700B5BBEF /* SentryInitializeForGettingSubclassesNotCalled.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BF9EF8A2722D58700B5BBEF /* SentryInitializeForGettingSubclassesNotCalled.m */; }; - 7BFA69F427E07FF700233199 /* SentryOutOfMemoryLogicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFA69F327E07FF700233199 /* SentryOutOfMemoryLogicTests.swift */; }; 7BFA69F627E0840400233199 /* SentryANRTrackingIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BFA69F527E0840400233199 /* SentryANRTrackingIntegrationTests.swift */; }; 7BFC169B2524995700FF6266 /* SentryMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BFC169A2524995700FF6266 /* SentryMessage.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7BFC16A125249A9D00FF6266 /* SentryMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BFC16A025249A9D00FF6266 /* SentryMessage.m */; }; @@ -1333,7 +1332,6 @@ 7BF9EF872722D13000B5BBEF /* SentryTestObjCRuntimeWrapper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryTestObjCRuntimeWrapper.m; sourceTree = ""; }; 7BF9EF892722D57100B5BBEF /* SentryInitializeForGettingSubclassesNotCalled.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryInitializeForGettingSubclassesNotCalled.h; sourceTree = ""; }; 7BF9EF8A2722D58700B5BBEF /* SentryInitializeForGettingSubclassesNotCalled.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryInitializeForGettingSubclassesNotCalled.m; sourceTree = ""; }; - 7BFA69F327E07FF700233199 /* SentryOutOfMemoryLogicTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryOutOfMemoryLogicTests.swift; sourceTree = ""; }; 7BFA69F527E0840400233199 /* SentryANRTrackingIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryANRTrackingIntegrationTests.swift; sourceTree = ""; }; 7BFC169A2524995700FF6266 /* SentryMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryMessage.h; path = Public/SentryMessage.h; sourceTree = ""; }; 7BFC16A025249A9D00FF6266 /* SentryMessage.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryMessage.m; sourceTree = ""; }; @@ -2615,7 +2613,6 @@ children = ( 7B98D7DF25FB73B900C5A389 /* SentryOutOfMemoryTrackerTests.swift */, 7BFE7A0927A1B6B000D2B66E /* SentryOutOfMemoryIntegrationTests.swift */, - 7BFA69F327E07FF700233199 /* SentryOutOfMemoryLogicTests.swift */, ); path = OutOfMemory; sourceTree = ""; @@ -3553,7 +3550,6 @@ 7B0A5452252311CE00A71716 /* SentryBreadcrumbTests.swift in Sources */, 7BA0C04A280563AA003E0326 /* TestTransportAdapter.swift in Sources */, 7BE3C7752445C82300A38442 /* SentryCurrentDateTests.swift in Sources */, - 7BFA69F427E07FF700233199 /* SentryOutOfMemoryLogicTests.swift in Sources */, 7B3398672459C4AE00BD9C96 /* SentryEnvelopeRateLimitTests.swift in Sources */, 8EA9AF492665AC48002771B4 /* SentryPerformanceTrackerTests.swift in Sources */, 7BF1F6AE282A4FE2006BD6AB /* SentryTestObserver.m in Sources */, diff --git a/Tests/SentryTests/Integrations/OutOfMemory/SentryOutOfMemoryLogicTests.swift b/Tests/SentryTests/Integrations/OutOfMemory/SentryOutOfMemoryLogicTests.swift deleted file mode 100644 index f34f3cdb6d4..00000000000 --- a/Tests/SentryTests/Integrations/OutOfMemory/SentryOutOfMemoryLogicTests.swift +++ /dev/null @@ -1,55 +0,0 @@ -import XCTest - -class SentryOutOfMemoryLogicTests: XCTestCase { - - private static let dsnAsString = TestConstants.dsnAsString(username: "SentryOutOfMemoryLogicTests") - private static let dsn = TestConstants.dsn(username: "SentryOutOfMemoryLogicTests") - - private class Fixture { - - let options: Options - let client: TestClient! - let crashWrapper: TestSentryCrashWrapper - let fileManager: SentryFileManager - let currentDate = TestCurrentDateProvider() - let sysctl = TestSysctl() - let dispatchQueue = TestSentryDispatchQueueWrapper() - - init() { - options = Options() - options.dsn = SentryOutOfMemoryLogicTests.dsnAsString - options.releaseName = TestData.appState.releaseName - - client = TestClient(options: options) - - crashWrapper = TestSentryCrashWrapper.sharedInstance() - - fileManager = try! SentryFileManager(options: options, andCurrentDateProvider: currentDate) - } - - func getSut() -> SentryOutOfMemoryLogic { - let appStateManager = SentryAppStateManager(options: options, crashWrapper: crashWrapper, fileManager: fileManager, currentDateProvider: currentDate, sysctl: sysctl, dispatchQueueWrapper: self.dispatchQueue) - return SentryOutOfMemoryLogic(options: options, crashAdapter: crashWrapper, appStateManager: appStateManager) - } - } - - private var fixture: Fixture! - private var sut: SentryOutOfMemoryLogic! - - override func setUp() { - super.setUp() - - fixture = Fixture() - sut = fixture.getSut() - } - - override func tearDown() { - super.tearDown() - fixture.fileManager.deleteAllFolders() - } - - func testExample() throws { - - } - -} From 88056122d332a90959c6a5c7913dd356ae3d535f Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Mon, 7 Nov 2022 10:02:54 +0100 Subject: [PATCH 02/13] docs: Why GH actions formats code differently (#2363) Explain why GH actions can suddenly format code differently. --- .github/workflows/format-code.yml | 1 + CONTRIBUTING.md | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.github/workflows/format-code.yml b/.github/workflows/format-code.yml index ec59d10af5f..b9a8e787d37 100644 --- a/.github/workflows/format-code.yml +++ b/.github/workflows/format-code.yml @@ -18,6 +18,7 @@ jobs: - uses: actions/checkout@v3 - name: Install Clang-Format run: brew install clang-format + - run: clang-format --version - name: Format Code run: make format diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4386bff64db..816a399fd11 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,12 +60,21 @@ If you see a test being flaky, you should ideally fix it immediately. If that's Please follow the convention of removing the copyright code comments at the top of files. We only keep them inside [SentryCrash](/SentryCrash/), as the code is based on [KSCrash](https://github.com/kstenerud/KSCrash). -All Objective-C, C and C++ needs to be formatted with [Clang Format](http://clang.llvm.org/docs/ClangFormat.html). The configuration can be found in [`.clang-format`](./.clang-format). Simply run the make task before submitting your changes for review: +All Objective-C, C and C++ needs to be formatted with [Clang Format](http://clang.llvm.org/docs/ClangFormat.html). The configuration can be found in [`.clang-format`](./.clang-format). Simply run the make task, which runs automatically with git pre commit, before submitting your changes for review: ```sh make format ``` +### GH actions suddenly formats code differently + +It can be that it uses a different clang-format version, than you local computer. Please run `brew install clang-format`, and ensure that your version (run `clang-format --version`) matches the one from GH actions. + +**More information:** +We always use the latest version of clang-format in homebrew in [our GH actions](https://github.com/getsentry/sentry-cocoa/blob/059320e4947025875a0ef149666f819e244a042c/.github/workflows/format-code.yml#L20) for formatting the code. +As we use homebrew for setting up the development environment, homebrew only contains formulas for clang-format 8, 11, or the latest, and we want to use the latest clang-format version; we accept that we don't pin clang-format to a specific version. Using the GH action images clang-format version doesn't work, as it can be different than the one from homebrew. +This means if homebrew updates the [formula](https://formulae.brew.sh/formula/) for the default clang-format version so does our GH actions job. If the GH actions job suddenly starts to format code differently than your local make format, please compare your clang-format version with the GH actions jobs version. + ## Linting We use [Swiftlint](https://github.com/realm/SwiftLint) and Clang-Format. For Swiftlint we keep a seperate [config file](/Tests/.swiftlint) for the tests. To run all the linters locally execute: From bc6fb399cdf57fddd28eee8125984c4d75011f0a Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Mon, 7 Nov 2022 10:32:41 +0100 Subject: [PATCH 03/13] ci: Update brew before installing clang-format (#2365) Co-authored-by: Sentry Github Bot --- .github/workflows/format-code.yml | 3 ++- CONTRIBUTING.md | 2 +- Sources/SentryCrash/Recording/SentryCrash.m | 5 ++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/format-code.yml b/.github/workflows/format-code.yml index b9a8e787d37..df27c07186a 100644 --- a/.github/workflows/format-code.yml +++ b/.github/workflows/format-code.yml @@ -16,9 +16,10 @@ jobs: runs-on: macos-11 steps: - uses: actions/checkout@v3 + ## Update internal list of formulae to the latest + - run: brew update - name: Install Clang-Format run: brew install clang-format - - run: clang-format --version - name: Format Code run: make format diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 816a399fd11..f002d239ccf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,7 +71,7 @@ make format It can be that it uses a different clang-format version, than you local computer. Please run `brew install clang-format`, and ensure that your version (run `clang-format --version`) matches the one from GH actions. **More information:** -We always use the latest version of clang-format in homebrew in [our GH actions](https://github.com/getsentry/sentry-cocoa/blob/059320e4947025875a0ef149666f819e244a042c/.github/workflows/format-code.yml#L20) for formatting the code. +We always use the latest version of clang-format in homebrew in [our GH actions](https://github.com/getsentry/sentry-cocoa/blob/bdaf35331fa9dc67fc318e4a25b92cdc9b0c0ed7/.github/workflows/format-code.yml#L19-L20) for formatting the code. As we use homebrew for setting up the development environment, homebrew only contains formulas for clang-format 8, 11, or the latest, and we want to use the latest clang-format version; we accept that we don't pin clang-format to a specific version. Using the GH action images clang-format version doesn't work, as it can be different than the one from homebrew. This means if homebrew updates the [formula](https://formulae.brew.sh/formula/) for the default clang-format version so does our GH actions job. If the GH actions job suddenly starts to format code differently than your local make format, please compare your clang-format version with the GH actions jobs version. diff --git a/Sources/SentryCrash/Recording/SentryCrash.m b/Sources/SentryCrash/Recording/SentryCrash.m index c4e10cc9649..7fb39b38a80 100644 --- a/Sources/SentryCrash/Recording/SentryCrash.m +++ b/Sources/SentryCrash/Recording/SentryCrash.m @@ -355,7 +355,10 @@ - (void)deleteReportWithID:(NSNumber *)reportID // ============================================================================ #define SYNTHESIZE_CRASH_STATE_PROPERTY(TYPE, NAME) \ - -(TYPE)NAME { return sentrycrashstate_currentState()->NAME; } + -(TYPE)NAME \ + { \ + return sentrycrashstate_currentState()->NAME; \ + } SYNTHESIZE_CRASH_STATE_PROPERTY(NSTimeInterval, activeDurationSinceLastCrash) SYNTHESIZE_CRASH_STATE_PROPERTY(NSTimeInterval, backgroundDurationSinceLastCrash) From 8513f269d5a02806cd0868a71fa8ce3c5cbda6ae Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 7 Nov 2022 10:34:58 +0100 Subject: [PATCH 04/13] build(deps): bump github/codeql-action from 2.1.30 to 2.1.31 (#2364) Bumps [github/codeql-action](https://github.com/github/codeql-action) from 2.1.30 to 2.1.31. - [Release notes](https://github.com/github/codeql-action/releases) - [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/github/codeql-action/compare/18fe527fa8b29f134bb91f32f1a5dc5abb15ed7f...c3b6fce4ee2ca25bc1066aa3bf73962fda0e8898) --- updated-dependencies: - dependency-name: github/codeql-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a341b2fd634..7e7bbc9f4ad 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -22,7 +22,7 @@ jobs: uses: actions/checkout@v3 - name: Initialize CodeQL - uses: github/codeql-action/init@18fe527fa8b29f134bb91f32f1a5dc5abb15ed7f # pin@v2 + uses: github/codeql-action/init@c3b6fce4ee2ca25bc1066aa3bf73962fda0e8898 # pin@v2 with: languages: ${{ matrix.language }} @@ -35,4 +35,4 @@ jobs: -destination platform="iOS Simulator,OS=latest,name=iPhone 11 Pro" - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@18fe527fa8b29f134bb91f32f1a5dc5abb15ed7f # pin@v2 + uses: github/codeql-action/analyze@c3b6fce4ee2ca25bc1066aa3bf73962fda0e8898 # pin@v2 From 739ba7fd14c413ae6d66ed2cd100e461193cfc33 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Mon, 7 Nov 2022 11:31:43 +0100 Subject: [PATCH 05/13] Fix typos in NetworkTrackerIntegrationTests (#2367) --- .../Network/SentryNetworkTrackerIntegrationTests.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift index 9c7293c7463..0ed776e19a4 100644 --- a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift @@ -43,25 +43,25 @@ class SentryNetworkTrackerIntegrationTests: XCTestCase { } func testNetworkTrackerDisabled_WhenNetworkTrackingDisabled() { - asserrtNetworkTrackerDisabled { options in + assertNetworkTrackerDisabled { options in options.enableNetworkTracking = false } } func testNetworkTrackerDisabled_WhenAutoPerformanceTrackingDisabled() { - asserrtNetworkTrackerDisabled { options in + assertNetworkTrackerDisabled { options in options.enableAutoPerformanceTracking = false } } func testNetworkTrackerDisabled_WhenTracingDisabled() { - asserrtNetworkTrackerDisabled { options in + assertNetworkTrackerDisabled { options in options.tracesSampleRate = 0.0 } } func testNetworkTrackerDisabled_WhenSwizzlingDisabled() { - asserrtNetworkTrackerDisabled { options in + assertNetworkTrackerDisabled { options in options.enableSwizzling = false } } @@ -253,7 +253,7 @@ class SentryNetworkTrackerIntegrationTests: XCTestCase { XCTAssertEqual(sentryResponse?["status_code"] as? NSNumber, 400) } - private func asserrtNetworkTrackerDisabled(configureOptions: (Options) -> Void) { + private func assertNetworkTrackerDisabled(configureOptions: (Options) -> Void) { configureOptions(fixture.options) startSDK() From 062f06c9d3d15800a2cc1471a6605e2e9dda2730 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Mon, 7 Nov 2022 07:32:18 -0300 Subject: [PATCH 06/13] Update SentryNetworkTrackerIntegrationTests.swift (#2366) `testGetCaptureFailedRequestsEnabled` should fail and not crash when the test server is not running. --- .../Network/SentryNetworkTrackerIntegrationTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift index 0ed776e19a4..0bf60cf34a4 100644 --- a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerIntegrationTests.swift @@ -246,9 +246,9 @@ class SentryNetworkTrackerIntegrationTests: XCTestCase { wait(for: [expect], timeout: 5) XCTAssertNotNil(sentryEvent) - XCTAssertNotNil(sentryEvent!.request) + XCTAssertNotNil(sentryEvent?.request) - let sentryResponse = sentryEvent!.context?["response"] + let sentryResponse = sentryEvent?.context?["response"] XCTAssertEqual(sentryResponse?["status_code"] as? NSNumber, 400) } From a6899a2eedf80ea2bef30989de1ec840d0a5566d Mon Sep 17 00:00:00 2001 From: Kevin Renskers Date: Tue, 8 Nov 2022 11:04:00 +0100 Subject: [PATCH 07/13] feat: Track usage of the enableCaptureFailedRequests option (#2368) --- CHANGELOG.md | 4 ++++ Sources/Sentry/Public/SentryOptions.h | 2 +- Sources/Sentry/SentryClient.m | 4 ++++ Tests/SentryTests/SentryClientTests.swift | 16 ++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44bff4d10aa..d9d0f986f3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased +### Features + +- Report usage of enableCaptureFailedRequests (#2368) + ### Fixes - Fix issue with invalid profiles uploading (#2358 and #2359) diff --git a/Sources/Sentry/Public/SentryOptions.h b/Sources/Sentry/Public/SentryOptions.h index efa1537d230..b33eae0e5d7 100644 --- a/Sources/Sentry/Public/SentryOptions.h +++ b/Sources/Sentry/Public/SentryOptions.h @@ -416,7 +416,7 @@ NS_SWIFT_NAME(Options) /** * When enabled, the SDK captures HTTP Client errors. Default value is NO. - * This feature requires enableSwizzling enabled as well, Default value is YES. + * This feature requires enableSwizzling enabled as well, default value is YES. */ @property (nonatomic, assign) BOOL enableCaptureFailedRequests; diff --git a/Sources/Sentry/SentryClient.m b/Sources/Sentry/SentryClient.m index 3f916aa5ba7..6165f843403 100644 --- a/Sources/Sentry/SentryClient.m +++ b/Sources/Sentry/SentryClient.m @@ -654,6 +654,10 @@ - (void)setSdk:(SentryEvent *)event if (self.options.stitchAsyncCode) { [integrations addObject:@"StitchAsyncCode"]; } + + if (self.options.enableCaptureFailedRequests) { + [integrations addObject:@"CaptureFailedRequests"]; + } } event.sdk = @{ diff --git a/Tests/SentryTests/SentryClientTests.swift b/Tests/SentryTests/SentryClientTests.swift index c3e0f5359f2..181ff8d14b5 100644 --- a/Tests/SentryTests/SentryClientTests.swift +++ b/Tests/SentryTests/SentryClientTests.swift @@ -1047,6 +1047,22 @@ class SentryClientTest: XCTestCase { ) } } + + func testTrackEnableCaptureFailedRequests() { + SentrySDK.start(options: Options()) + + let eventId = fixture.getSut(configureOptions: { options in + options.enableCaptureFailedRequests = true + }).capture(message: fixture.messageAsString) + + eventId.assertIsNotEmpty() + assertLastSentEvent { actual in + assertArrayEquals( + expected: ["AutoBreadcrumbTracking", "AutoSessionTracking", "Crash", "NetworkTracking", "CaptureFailedRequests"], + actual: actual.sdk?["integrations"] as? [String] + ) + } + } func testSetSDKIntegrations_NoIntegrations() { let expected: [String] = [] From 01057a9b9083011efd38ad6df9a21c34e3571885 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Tue, 8 Nov 2022 07:42:58 -0300 Subject: [PATCH 08/13] chore: Remove PrivateSentrySDKOnly.h from umbrella header (#2349) Remove PrivateSentrySDKOnly.h from umbrella headers to prevent users from use it by mistake. --- .../iOS-Swift/Tools/iOS-Swift-Bridging-Header.h | 1 + .../iOS13-Swift/iOS13-Swift-Bridging-Header.h | 1 + Sentry.podspec | 11 +++++++++-- Sentry.xcodeproj/project.pbxproj | 8 ++++---- Sources/Sentry/Public/Sentry.h | 1 - .../Sentry/{Public => include}/PrivateSentrySDKOnly.h | 9 ++++++++- 6 files changed, 23 insertions(+), 8 deletions(-) rename Sources/Sentry/{Public => include}/PrivateSentrySDKOnly.h (91%) diff --git a/Samples/iOS-Swift/iOS-Swift/Tools/iOS-Swift-Bridging-Header.h b/Samples/iOS-Swift/iOS-Swift/Tools/iOS-Swift-Bridging-Header.h index 538c020b328..44fe01477e4 100644 --- a/Samples/iOS-Swift/iOS-Swift/Tools/iOS-Swift-Bridging-Header.h +++ b/Samples/iOS-Swift/iOS-Swift/Tools/iOS-Swift-Bridging-Header.h @@ -1 +1,2 @@ #import "SentryBenchmarking.h" +#import diff --git a/Samples/iOS-Swift/iOS13-Swift/iOS13-Swift-Bridging-Header.h b/Samples/iOS-Swift/iOS13-Swift/iOS13-Swift-Bridging-Header.h index 538c020b328..44fe01477e4 100644 --- a/Samples/iOS-Swift/iOS13-Swift/iOS13-Swift-Bridging-Header.h +++ b/Samples/iOS-Swift/iOS13-Swift/iOS13-Swift-Bridging-Header.h @@ -1 +1,2 @@ #import "SentryBenchmarking.h" +#import diff --git a/Sentry.podspec b/Sentry.podspec index 553a421ae8d..8cc151b2ff3 100644 --- a/Sentry.podspec +++ b/Sentry.podspec @@ -31,8 +31,15 @@ Pod::Spec.new do |s| sp.source_files = "Sources/Sentry/**/*.{h,hpp,m,mm,c,cpp}", "Sources/SentryCrash/**/*.{h,hpp,m,mm,c,cpp}" + sp.public_header_files = "Sources/Sentry/Public/*.h" + end + + s.subspec 'HybridSDK' do |sp| + sp.source_files = "Sources/Sentry/**/*.{h,hpp,m,mm,c,cpp}", + "Sources/SentryCrash/**/*.{h,hpp,m,mm,c,cpp}" + sp.public_header_files = - "Sources/Sentry/Public/*.h" - + "Sources/Sentry/Public/*.h", "Sources/Sentry/include/PrivateSentrySDKOnly.h" end + end diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index f358e4e2db9..45e372636e4 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -368,7 +368,6 @@ 7B6C5F8126034354007F7DFF /* SentryOutOfMemoryLogic.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B6C5F8026034354007F7DFF /* SentryOutOfMemoryLogic.h */; }; 7B6C5F8726034395007F7DFF /* SentryOutOfMemoryLogic.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B6C5F8626034395007F7DFF /* SentryOutOfMemoryLogic.m */; }; 7B6CC50224EE5A42001816D7 /* SentryHubTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6CC50124EE5A42001816D7 /* SentryHubTests.swift */; }; - 7B6D125F265F778500C9BE4B /* PrivateSentrySDKOnly.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B6D125E265F778500C9BE4B /* PrivateSentrySDKOnly.h */; settings = {ATTRIBUTES = (Public, ); }; }; 7B6D1261265F784000C9BE4B /* PrivateSentrySDKOnly.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D1260265F784000C9BE4B /* PrivateSentrySDKOnly.m */; }; 7B6D1263265F7CC600C9BE4B /* PrivateSentrySDKOnlyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D1262265F7CC600C9BE4B /* PrivateSentrySDKOnlyTests.swift */; }; 7B6D135C27F4605D00331ED2 /* TestEnvelopeRateLimitDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D135B27F4605D00331ED2 /* TestEnvelopeRateLimitDelegate.swift */; }; @@ -705,6 +704,7 @@ D88817DA26D72AB800BF2251 /* SentryTraceContext.h in Headers */ = {isa = PBXBuildFile; fileRef = D88817D926D72AB800BF2251 /* SentryTraceContext.h */; }; D88817DD26D72BA500BF2251 /* SentryTraceStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D88817DB26D72B7B00BF2251 /* SentryTraceStateTests.swift */; }; D8918B222849FA6D00701F9A /* SentrySDKIntegrationTestsBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8918B212849FA6D00701F9A /* SentrySDKIntegrationTestsBase.swift */; }; + D8A22A6929140081006907D9 /* PrivateSentrySDKOnly.h in Headers */ = {isa = PBXBuildFile; fileRef = D8A22A6829140081006907D9 /* PrivateSentrySDKOnly.h */; settings = {ATTRIBUTES = (Private, ); }; }; D8AB40DB2806EC1900E5E9F7 /* SentryScreenshotIntegration.h in Headers */ = {isa = PBXBuildFile; fileRef = D8AB40DA2806EC1900E5E9F7 /* SentryScreenshotIntegration.h */; }; D8ACE3C72762187200F5A213 /* SentryNSDataSwizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = D8ACE3C42762187200F5A213 /* SentryNSDataSwizzling.m */; }; D8ACE3C82762187200F5A213 /* SentryNSDataTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = D8ACE3C52762187200F5A213 /* SentryNSDataTracker.m */; }; @@ -1114,7 +1114,6 @@ 7B6C5F8026034354007F7DFF /* SentryOutOfMemoryLogic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryOutOfMemoryLogic.h; path = include/SentryOutOfMemoryLogic.h; sourceTree = ""; }; 7B6C5F8626034395007F7DFF /* SentryOutOfMemoryLogic.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryOutOfMemoryLogic.m; sourceTree = ""; }; 7B6CC50124EE5A42001816D7 /* SentryHubTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryHubTests.swift; sourceTree = ""; }; - 7B6D125E265F778500C9BE4B /* PrivateSentrySDKOnly.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = PrivateSentrySDKOnly.h; path = Public/PrivateSentrySDKOnly.h; sourceTree = ""; }; 7B6D1260265F784000C9BE4B /* PrivateSentrySDKOnly.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrivateSentrySDKOnly.m; sourceTree = ""; }; 7B6D1262265F7CC600C9BE4B /* PrivateSentrySDKOnlyTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivateSentrySDKOnlyTests.swift; sourceTree = ""; }; 7B6D135B27F4605D00331ED2 /* TestEnvelopeRateLimitDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestEnvelopeRateLimitDelegate.swift; sourceTree = ""; }; @@ -1497,6 +1496,7 @@ D88817D926D72AB800BF2251 /* SentryTraceContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryTraceContext.h; path = include/SentryTraceContext.h; sourceTree = ""; }; D88817DB26D72B7B00BF2251 /* SentryTraceStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryTraceStateTests.swift; sourceTree = ""; }; D8918B212849FA6D00701F9A /* SentrySDKIntegrationTestsBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySDKIntegrationTestsBase.swift; sourceTree = ""; }; + D8A22A6829140081006907D9 /* PrivateSentrySDKOnly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PrivateSentrySDKOnly.h; path = include/PrivateSentrySDKOnly.h; sourceTree = ""; }; D8AB40DA2806EC1900E5E9F7 /* SentryScreenshotIntegration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryScreenshotIntegration.h; path = include/SentryScreenshotIntegration.h; sourceTree = ""; }; D8ACE3C42762187200F5A213 /* SentryNSDataSwizzling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryNSDataSwizzling.m; sourceTree = ""; }; D8ACE3C52762187200F5A213 /* SentryNSDataTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryNSDataTracker.m; sourceTree = ""; }; @@ -1967,7 +1967,7 @@ 8ECC673625C23936000E2BF6 /* Transaction */, 8E25C94F25F836AB00DC215B /* Tools */, 63AA76931EB9C1C200D153DE /* Sentry.h */, - 7B6D125E265F778500C9BE4B /* PrivateSentrySDKOnly.h */, + D8A22A6829140081006907D9 /* PrivateSentrySDKOnly.h */, 7B6D1260265F784000C9BE4B /* PrivateSentrySDKOnly.m */, 63AA76941EB9C1C200D153DE /* SentryClient.h */, 63AA75ED1EB8B3C400D153DE /* SentryClient.m */, @@ -2968,7 +2968,6 @@ D867063D27C3BC2400048851 /* SentryCoreDataTrackingIntegration.h in Headers */, 0A2D8D5D289815EB008720F6 /* SentryBaseIntegration.h in Headers */, 63FE716520DA4C1100CDBAE8 /* SentryCrashMemory.h in Headers */, - 7B6D125F265F778500C9BE4B /* PrivateSentrySDKOnly.h in Headers */, 63FE713F20DA4C1100CDBAE8 /* SentryCrashStackCursor_SelfThread.h in Headers */, 639FCFA41EBC809A00778193 /* SentryStacktrace.h in Headers */, 63FE716320DA4C1100CDBAE8 /* SentryCrashDynamicLinker.h in Headers */, @@ -3002,6 +3001,7 @@ 63FE717920DA4C1100CDBAE8 /* SentryCrashReportStore.h in Headers */, 0AAE202128ED9BCC00D0CD80 /* SentryReachability.h in Headers */, A839D89824864B80003B7AFD /* SentrySystemEventBreadcrumbs.h in Headers */, + D8A22A6929140081006907D9 /* PrivateSentrySDKOnly.h in Headers */, 7B14089624878F090035403D /* SentryCrashStackEntryMapper.h in Headers */, 63FE714920DA4C1100CDBAE8 /* SentryCrashStackCursor_Backtrace.h in Headers */, 7BFC169B2524995700FF6266 /* SentryMessage.h in Headers */, diff --git a/Sources/Sentry/Public/Sentry.h b/Sources/Sentry/Public/Sentry.h index 0674fb2deb5..c34cd661459 100644 --- a/Sources/Sentry/Public/Sentry.h +++ b/Sources/Sentry/Public/Sentry.h @@ -6,7 +6,6 @@ FOUNDATION_EXPORT double SentryVersionNumber; //! Project version string for Sentry. FOUNDATION_EXPORT const unsigned char SentryVersionString[]; -#import "PrivateSentrySDKOnly.h" #import "SentryAppStartMeasurement.h" #import "SentryAttachment.h" #import "SentryBreadcrumb.h" diff --git a/Sources/Sentry/Public/PrivateSentrySDKOnly.h b/Sources/Sentry/include/PrivateSentrySDKOnly.h similarity index 91% rename from Sources/Sentry/Public/PrivateSentrySDKOnly.h rename to Sources/Sentry/include/PrivateSentrySDKOnly.h index 5cbbe17096d..6cef3c3ce31 100644 --- a/Sources/Sentry/Public/PrivateSentrySDKOnly.h +++ b/Sources/Sentry/include/PrivateSentrySDKOnly.h @@ -1,4 +1,11 @@ -#import "SentryDefines.h" +// We need this because if Sentry library is added as a Framework +// the reference should be in the form of . +// Otherwise, the reference is direct. +#if __has_include() +# import +#else +# import "SentryDefines.h" +#endif @class SentryEnvelope, SentryDebugMeta, SentryAppStartMeasurement, SentryScreenFrames, SentryOptions; From 512ef36a8ae3d13136b57fecabfb01f4177ad546 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Tue, 8 Nov 2022 15:47:33 +0100 Subject: [PATCH 09/13] Revert "feat: Track usage of the enableCaptureFailedRequests option (#2368)" (#2371) This reverts commit a6899a2eedf80ea2bef30989de1ec840d0a5566d. --- CHANGELOG.md | 4 ---- Sources/Sentry/Public/SentryOptions.h | 2 +- Sources/Sentry/SentryClient.m | 4 ---- Tests/SentryTests/SentryClientTests.swift | 16 ---------------- 4 files changed, 1 insertion(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9d0f986f3c..44bff4d10aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,6 @@ ## Unreleased -### Features - -- Report usage of enableCaptureFailedRequests (#2368) - ### Fixes - Fix issue with invalid profiles uploading (#2358 and #2359) diff --git a/Sources/Sentry/Public/SentryOptions.h b/Sources/Sentry/Public/SentryOptions.h index b33eae0e5d7..efa1537d230 100644 --- a/Sources/Sentry/Public/SentryOptions.h +++ b/Sources/Sentry/Public/SentryOptions.h @@ -416,7 +416,7 @@ NS_SWIFT_NAME(Options) /** * When enabled, the SDK captures HTTP Client errors. Default value is NO. - * This feature requires enableSwizzling enabled as well, default value is YES. + * This feature requires enableSwizzling enabled as well, Default value is YES. */ @property (nonatomic, assign) BOOL enableCaptureFailedRequests; diff --git a/Sources/Sentry/SentryClient.m b/Sources/Sentry/SentryClient.m index 6165f843403..3f916aa5ba7 100644 --- a/Sources/Sentry/SentryClient.m +++ b/Sources/Sentry/SentryClient.m @@ -654,10 +654,6 @@ - (void)setSdk:(SentryEvent *)event if (self.options.stitchAsyncCode) { [integrations addObject:@"StitchAsyncCode"]; } - - if (self.options.enableCaptureFailedRequests) { - [integrations addObject:@"CaptureFailedRequests"]; - } } event.sdk = @{ diff --git a/Tests/SentryTests/SentryClientTests.swift b/Tests/SentryTests/SentryClientTests.swift index 181ff8d14b5..c3e0f5359f2 100644 --- a/Tests/SentryTests/SentryClientTests.swift +++ b/Tests/SentryTests/SentryClientTests.swift @@ -1047,22 +1047,6 @@ class SentryClientTest: XCTestCase { ) } } - - func testTrackEnableCaptureFailedRequests() { - SentrySDK.start(options: Options()) - - let eventId = fixture.getSut(configureOptions: { options in - options.enableCaptureFailedRequests = true - }).capture(message: fixture.messageAsString) - - eventId.assertIsNotEmpty() - assertLastSentEvent { actual in - assertArrayEquals( - expected: ["AutoBreadcrumbTracking", "AutoSessionTracking", "Crash", "NetworkTracking", "CaptureFailedRequests"], - actual: actual.sdk?["integrations"] as? [String] - ) - } - } func testSetSDKIntegrations_NoIntegrations() { let expected: [String] = [] From f444dc48a7f26216be7da8c625736e0cfd0f9282 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Tue, 8 Nov 2022 17:39:35 -0300 Subject: [PATCH 10/13] chore: Add match_local to Fastfile Add a new task to Fastfile that recreate certificates and provisioning profiles. --- fastlane/Fastfile | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 1b7b3aabd8c..2db18626bdc 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -45,6 +45,34 @@ platform :ios do ) end + desc "Run match for local development" + lane :match_local do + match( + type: "development", + app_identifier: ["io.sentry.sample.iOS-Swift", + "io.sentry.sample.iOS-Swift.Clip", + "io.sentry.iOS-SwiftUITests.xctrunner", + "io.sentry.sample.movies.ProfileDataGeneratorUITest", + "io.sentry.sample.TrendingMovies", + "io.sentry.cocoa.perf-test-app-plain", + "io.sentry.*", + "io.sentry.iOS-Benchmarking.xctrunner", + "io.sentry.cocoa.perf-test-app-sentry"] + ) + match( + type: "appstore", + app_identifier: ["io.sentry.sample.iOS-Swift", + "io.sentry.sample.iOS-Swift.Clip", + "io.sentry.iOS-SwiftUITests.xctrunner", + "io.sentry.sample.movies.ProfileDataGeneratorUITest", + "io.sentry.sample.TrendingMovies", + "io.sentry.cocoa.perf-test-app-plain", + "io.sentry.*", + "io.sentry.iOS-Benchmarking.xctrunner", + "io.sentry.cocoa.perf-test-app-sentry"] + ) + end + desc "Build iOS-Swift with Release" lane :build_ios_swift do From 725723e10c8d2448514e4cd4cee4e71351922e9f Mon Sep 17 00:00:00 2001 From: Kevin Renskers Date: Wed, 9 Nov 2022 10:53:21 +0100 Subject: [PATCH 11/13] fix: Call UIDevice methods on the main thread (#2369) --- CHANGELOG.md | 1 + Sentry.xcodeproj/project.pbxproj | 12 +++-- Sources/Sentry/SentryANRTracker.m | 2 +- Sources/Sentry/SentryDispatchQueueWrapper.m | 11 +++- Sources/Sentry/SentryScreenshot.m | 8 ++- Sources/Sentry/SentrySubClassFinder.m | 2 +- Sources/Sentry/SentryUIDeviceWrapper.m | 51 +++++++++++++------ .../include/SentryDispatchQueueWrapper.h | 4 +- .../Sentry/include/SentryUIDeviceWrapper.h | 5 ++ .../Helper/SentryFileManagerTests.swift | 1 - .../UIEvents/SentryUIEventTrackerTests.swift | 4 ++ .../Networking/SentryHttpTransportTests.swift | 2 - .../TestSentryDispatchQueueWrapper.swift | 12 +++-- .../Performance/SentryTracerTests.swift | 2 + ...swift => SentryCrashReportSinkTests.swift} | 0 .../SentryUIDeviceWrapperTests.swift | 14 +++++ .../TestSentryUIDeviceWrapper.swift | 4 -- 17 files changed, 96 insertions(+), 39 deletions(-) rename Tests/SentryTests/SentryCrash/{SentryCrashReportSinkTest.swift => SentryCrashReportSinkTests.swift} (100%) create mode 100644 Tests/SentryTests/SentryCrash/SentryUIDeviceWrapperTests.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index 44bff4d10aa..3be7f3c06e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixes - Fix issue with invalid profiles uploading (#2358 and #2359) +- Call UIDevice methods on the main thread (#2369) ## 7.30.0 diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 45e372636e4..4cec9a30249 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -40,6 +40,7 @@ 0A1B497328E597DD00D7BFA3 /* TestLogOutput.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A1B497228E597DD00D7BFA3 /* TestLogOutput.swift */; }; 0A1C3592287D7107007D01E3 /* SentryMetaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A1C3591287D7107007D01E3 /* SentryMetaTests.swift */; }; 0A2690B72885C2E000E4432D /* TestSentryPermissionsObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AABE2EF2885C2120057ED69 /* TestSentryPermissionsObserver.swift */; }; + 0A283E79291A67E000EF4126 /* SentryUIDeviceWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A283E78291A67E000EF4126 /* SentryUIDeviceWrapperTests.swift */; }; 0A2D8D5B289815C0008720F6 /* SentryBaseIntegration.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A2D8D5A289815C0008720F6 /* SentryBaseIntegration.m */; }; 0A2D8D5D289815EB008720F6 /* SentryBaseIntegration.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A2D8D5C289815EB008720F6 /* SentryBaseIntegration.h */; }; 0A2D8D8728992260008720F6 /* SentryBaseIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A2D8D8628992260008720F6 /* SentryBaseIntegrationTests.swift */; }; @@ -668,7 +669,7 @@ A8AFFCD42907E0CA00967CD7 /* SentryRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8AFFCD32907E0CA00967CD7 /* SentryRequestTests.swift */; }; A8F17B2E2901765900990B25 /* SentryRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F17B2D2901765900990B25 /* SentryRequest.m */; }; A8F17B342902870300990B25 /* SentryHttpStatusCodeRange.m in Sources */ = {isa = PBXBuildFile; fileRef = A8F17B332902870300990B25 /* SentryHttpStatusCodeRange.m */; }; - D8019910286B089000C277F0 /* SentryCrashReportSinkTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D801990F286B089000C277F0 /* SentryCrashReportSinkTest.swift */; }; + D8019910286B089000C277F0 /* SentryCrashReportSinkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D801990F286B089000C277F0 /* SentryCrashReportSinkTests.swift */; }; D808FB88281AB33C009A2A33 /* SentryUIEventTrackerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D808FB86281AB31D009A2A33 /* SentryUIEventTrackerTests.swift */; }; D808FB8B281BCE96009A2A33 /* TestSentrySwizzleWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D808FB89281BCE46009A2A33 /* TestSentrySwizzleWrapper.swift */; }; D808FB92281BF6EC009A2A33 /* SentryUIEventTrackingIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D808FB90281BF6E9009A2A33 /* SentryUIEventTrackingIntegrationTests.swift */; }; @@ -766,6 +767,7 @@ 03F9D37B2819A65C00602916 /* SentryProfilerTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SentryProfilerTests.mm; sourceTree = ""; }; 0A1B497228E597DD00D7BFA3 /* TestLogOutput.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestLogOutput.swift; sourceTree = ""; }; 0A1C3591287D7107007D01E3 /* SentryMetaTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryMetaTests.swift; sourceTree = ""; }; + 0A283E78291A67E000EF4126 /* SentryUIDeviceWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUIDeviceWrapperTests.swift; sourceTree = ""; }; 0A2D8D5A289815C0008720F6 /* SentryBaseIntegration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryBaseIntegration.m; sourceTree = ""; }; 0A2D8D5C289815EB008720F6 /* SentryBaseIntegration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryBaseIntegration.h; path = include/SentryBaseIntegration.h; sourceTree = ""; }; 0A2D8D8628992260008720F6 /* SentryBaseIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryBaseIntegrationTests.swift; sourceTree = ""; }; @@ -1459,7 +1461,7 @@ A8AFFCD32907E0CA00967CD7 /* SentryRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryRequestTests.swift; sourceTree = ""; }; A8F17B2D2901765900990B25 /* SentryRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryRequest.m; sourceTree = ""; }; A8F17B332902870300990B25 /* SentryHttpStatusCodeRange.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryHttpStatusCodeRange.m; sourceTree = ""; }; - D801990F286B089000C277F0 /* SentryCrashReportSinkTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashReportSinkTest.swift; sourceTree = ""; }; + D801990F286B089000C277F0 /* SentryCrashReportSinkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashReportSinkTests.swift; sourceTree = ""; }; D808FB86281AB31D009A2A33 /* SentryUIEventTrackerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUIEventTrackerTests.swift; sourceTree = ""; }; D808FB89281BCE46009A2A33 /* TestSentrySwizzleWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSentrySwizzleWrapper.swift; sourceTree = ""; }; D808FB90281BF6E9009A2A33 /* SentryUIEventTrackingIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryUIEventTrackingIntegrationTests.swift; sourceTree = ""; }; @@ -2227,7 +2229,8 @@ 7B6D98EA24C6E84F005502FA /* SentryCrashInstallationReporterTests.swift */, 7B0A542D2521C62400A71716 /* SentryFrameRemoverTests.swift */, 7BBC827825DFD7D7005F1ED8 /* SentryInAppLogicTests.swift */, - D801990F286B089000C277F0 /* SentryCrashReportSinkTest.swift */, + D801990F286B089000C277F0 /* SentryCrashReportSinkTests.swift */, + 0A283E78291A67E000EF4126 /* SentryUIDeviceWrapperTests.swift */, 7BED3574266F7BC600EAA70D /* TestSentryCrashWrapper.h */, 7BED3575266F7BFF00EAA70D /* TestSentryCrashWrapper.m */, 0AABE2EF2885C2120057ED69 /* TestSentryPermissionsObserver.swift */, @@ -3556,6 +3559,7 @@ 7B3B473E25D6CEA500D01640 /* SentryNSErrorTests.swift in Sources */, 632331F62404FFA8008D91D6 /* SentryScopeTests.m in Sources */, D808FB88281AB33C009A2A33 /* SentryUIEventTrackerTests.swift in Sources */, + 0A283E79291A67E000EF4126 /* SentryUIDeviceWrapperTests.swift in Sources */, 63FE720D20DA66EC00CDBAE8 /* NSError+SimpleConstructor_Tests.m in Sources */, 69BEE6F72620729E006DF9DF /* UrlSessionDelegateSpy.swift in Sources */, 035E73C827D56757005EEB11 /* SentryBacktraceTests.mm in Sources */, @@ -3612,7 +3616,7 @@ 7B6C5ED6264E62CA0010D138 /* SentryTransactionTests.swift in Sources */, D81FDF12280EA1060045E0E4 /* SentryScreenShotTests.swift in Sources */, 7BE3C7772445E50A00A38442 /* TestCurrentDateProvider.swift in Sources */, - D8019910286B089000C277F0 /* SentryCrashReportSinkTest.swift in Sources */, + D8019910286B089000C277F0 /* SentryCrashReportSinkTests.swift in Sources */, D885266427739D01001269FC /* SentryFileIOTrackingIntegrationTests.swift in Sources */, 7BBD18992449DE9D00427C76 /* TestRateLimits.swift in Sources */, 8E4A038625F76A7600000D77 /* TypeMapping.swift in Sources */, diff --git a/Sources/Sentry/SentryANRTracker.m b/Sources/Sentry/SentryANRTracker.m index 7c785b98416..16f943c6fa0 100644 --- a/Sources/Sentry/SentryANRTracker.m +++ b/Sources/Sentry/SentryANRTracker.m @@ -61,7 +61,7 @@ - (void)detectANRs ticksSinceUiUpdate++; - [self.dispatchQueueWrapper dispatchOnMainQueue:^{ + [self.dispatchQueueWrapper dispatchAsyncOnMainQueue:^{ ticksSinceUiUpdate = 0; if (reported) { diff --git a/Sources/Sentry/SentryDispatchQueueWrapper.m b/Sources/Sentry/SentryDispatchQueueWrapper.m index 5bd84083371..88a89fef3e2 100644 --- a/Sources/Sentry/SentryDispatchQueueWrapper.m +++ b/Sources/Sentry/SentryDispatchQueueWrapper.m @@ -38,7 +38,7 @@ - (void)dispatchAsyncWithBlock:(void (^)(void))block }); } -- (void)dispatchOnMainQueue:(void (^)(void))block +- (void)dispatchAsyncOnMainQueue:(void (^)(void))block { dispatch_async(dispatch_get_main_queue(), ^{ @autoreleasepool { @@ -47,6 +47,15 @@ - (void)dispatchOnMainQueue:(void (^)(void))block }); } +- (void)dispatchSyncOnMainQueue:(void (^)(void))block +{ + if ([NSThread isMainThread]) { + block(); + } else { + dispatch_sync(dispatch_get_main_queue(), block); + } +} + - (void)dispatchAfter:(NSTimeInterval)interval block:(dispatch_block_t)block { dispatch_time_t delta = (int64_t)(interval * NSEC_PER_SEC); diff --git a/Sources/Sentry/SentryScreenshot.m b/Sources/Sentry/SentryScreenshot.m index 8944c5e7786..a3eba3e120b 100644 --- a/Sources/Sentry/SentryScreenshot.m +++ b/Sources/Sentry/SentryScreenshot.m @@ -1,5 +1,6 @@ #import "SentryScreenshot.h" #import "SentryDependencyContainer.h" +#import "SentryDispatchQueueWrapper.h" #import "SentryUIApplication.h" #if SENTRY_HAS_UIKIT @@ -13,11 +14,8 @@ @implementation SentryScreenshot void (^takeScreenShot)(void) = ^{ result = [self takeScreenshots]; }; - if ([NSThread isMainThread]) { - takeScreenShot(); - } else { - dispatch_sync(dispatch_get_main_queue(), takeScreenShot); - } + [[SentryDependencyContainer sharedInstance].dispatchQueueWrapper + dispatchSyncOnMainQueue:takeScreenShot]; return result; } diff --git a/Sources/Sentry/SentrySubClassFinder.m b/Sources/Sentry/SentrySubClassFinder.m index 6ff6b670c7c..b9b099e2f2d 100644 --- a/Sources/Sentry/SentrySubClassFinder.m +++ b/Sources/Sentry/SentrySubClassFinder.m @@ -60,7 +60,7 @@ - (void)actOnSubclassesOfViewControllerInImage:(NSString *)imageName block:(void } free(classes); - [self.dispatchQueue dispatchOnMainQueue:^{ + [self.dispatchQueue dispatchAsyncOnMainQueue:^{ for (NSString *className in classesToSwizzle) { block(NSClassFromString(className)); } diff --git a/Sources/Sentry/SentryUIDeviceWrapper.m b/Sources/Sentry/SentryUIDeviceWrapper.m index eb4d03c1caf..cb394500aaf 100644 --- a/Sources/Sentry/SentryUIDeviceWrapper.m +++ b/Sources/Sentry/SentryUIDeviceWrapper.m @@ -1,4 +1,6 @@ #import "SentryUIDeviceWrapper.h" +#import "SentryDependencyContainer.h" +#import "SentryDispatchQueueWrapper.h" NS_ASSUME_NONNULL_BEGIN @@ -6,6 +8,7 @@ SentryUIDeviceWrapper () @property (nonatomic) BOOL cleanupDeviceOrientationNotifications; @property (nonatomic) BOOL cleanupBatteryMonitoring; +@property (strong, nonatomic) SentryDispatchQueueWrapper *dispatchQueueWrapper; @end @implementation SentryUIDeviceWrapper @@ -13,31 +16,47 @@ @implementation SentryUIDeviceWrapper #if TARGET_OS_IOS - (instancetype)init +{ + return [self initWithDispatchQueueWrapper:[SentryDependencyContainer sharedInstance] + .dispatchQueueWrapper]; +} + +- (instancetype)initWithDispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper { if (self = [super init]) { - // Needed to read the device orientation on demand - if (!UIDevice.currentDevice.isGeneratingDeviceOrientationNotifications) { - self.cleanupDeviceOrientationNotifications = YES; - [UIDevice.currentDevice beginGeneratingDeviceOrientationNotifications]; - } + self.dispatchQueueWrapper = dispatchQueueWrapper; + [self.dispatchQueueWrapper dispatchSyncOnMainQueue:^{ + // Needed to read the device orientation on demand + if (!UIDevice.currentDevice.isGeneratingDeviceOrientationNotifications) { + self.cleanupDeviceOrientationNotifications = YES; + [UIDevice.currentDevice beginGeneratingDeviceOrientationNotifications]; + } - // Needed so we can read the battery level - if (!UIDevice.currentDevice.isBatteryMonitoringEnabled) { - self.cleanupBatteryMonitoring = YES; - UIDevice.currentDevice.batteryMonitoringEnabled = YES; - } + // Needed so we can read the battery level + if (!UIDevice.currentDevice.isBatteryMonitoringEnabled) { + self.cleanupBatteryMonitoring = YES; + UIDevice.currentDevice.batteryMonitoringEnabled = YES; + } + }]; } return self; } +- (void)stop +{ + [self.dispatchQueueWrapper dispatchSyncOnMainQueue:^{ + if (self.cleanupDeviceOrientationNotifications) { + [UIDevice.currentDevice endGeneratingDeviceOrientationNotifications]; + } + if (self.cleanupBatteryMonitoring) { + UIDevice.currentDevice.batteryMonitoringEnabled = NO; + } + }]; +} + - (void)dealloc { - if (self.cleanupDeviceOrientationNotifications) { - [UIDevice.currentDevice endGeneratingDeviceOrientationNotifications]; - } - if (self.cleanupBatteryMonitoring) { - UIDevice.currentDevice.batteryMonitoringEnabled = NO; - } + [self stop]; } - (UIDeviceOrientation)orientation diff --git a/Sources/Sentry/include/SentryDispatchQueueWrapper.h b/Sources/Sentry/include/SentryDispatchQueueWrapper.h index a28c2ad53c5..06bcfaba1e0 100644 --- a/Sources/Sentry/include/SentryDispatchQueueWrapper.h +++ b/Sources/Sentry/include/SentryDispatchQueueWrapper.h @@ -11,7 +11,9 @@ NS_ASSUME_NONNULL_BEGIN - (void)dispatchAsyncWithBlock:(void (^)(void))block; -- (void)dispatchOnMainQueue:(void (^)(void))block; +- (void)dispatchAsyncOnMainQueue:(void (^)(void))block; + +- (void)dispatchSyncOnMainQueue:(void (^)(void))block; - (void)dispatchAfter:(NSTimeInterval)interval block:(dispatch_block_t)block; diff --git a/Sources/Sentry/include/SentryUIDeviceWrapper.h b/Sources/Sentry/include/SentryUIDeviceWrapper.h index c89c21eff92..211f4ef0b12 100644 --- a/Sources/Sentry/include/SentryUIDeviceWrapper.h +++ b/Sources/Sentry/include/SentryUIDeviceWrapper.h @@ -6,9 +6,14 @@ NS_ASSUME_NONNULL_BEGIN +@class SentryDispatchQueueWrapper; + @interface SentryUIDeviceWrapper : NSObject #if TARGET_OS_IOS +- (instancetype)init; +- (instancetype)initWithDispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper; +- (void)stop; - (UIDeviceOrientation)orientation; - (BOOL)isBatteryMonitoringEnabled; - (UIDeviceBatteryState)batteryState; diff --git a/Tests/SentryTests/Helper/SentryFileManagerTests.swift b/Tests/SentryTests/Helper/SentryFileManagerTests.swift index 1b1c81e1d0d..6b3d833415a 100644 --- a/Tests/SentryTests/Helper/SentryFileManagerTests.swift +++ b/Tests/SentryTests/Helper/SentryFileManagerTests.swift @@ -35,7 +35,6 @@ class SentryFileManagerTests: XCTestCase { init() { currentDateProvider = TestCurrentDateProvider() dispatchQueueWrapper = TestSentryDispatchQueueWrapper() - dispatchQueueWrapper.dispatchAfterExecutesBlock = true eventIds = (0...(maxCacheItems + 10)).map { _ in SentryId() } diff --git a/Tests/SentryTests/Integrations/UIEvents/SentryUIEventTrackerTests.swift b/Tests/SentryTests/Integrations/UIEvents/SentryUIEventTrackerTests.swift index 526a0ce6cea..f1a6be0f691 100644 --- a/Tests/SentryTests/Integrations/UIEvents/SentryUIEventTrackerTests.swift +++ b/Tests/SentryTests/Integrations/UIEvents/SentryUIEventTrackerTests.swift @@ -10,6 +10,10 @@ class SentryUIEventTrackerTests: XCTestCase { let hub = SentryHub(client: TestClient(options: Options()), andScope: nil) let dispatchQueue = TestSentryDispatchQueueWrapper() let button = UIButton() + + init () { + dispatchQueue.blockBeforeMainBlock = { false } + } func getSut() -> SentryUIEventTracker { return SentryUIEventTracker(swizzleWrapper: swizzleWrapper, dispatchQueueWrapper: dispatchQueue, idleTimeout: 3.0) diff --git a/Tests/SentryTests/Networking/SentryHttpTransportTests.swift b/Tests/SentryTests/Networking/SentryHttpTransportTests.swift index e35c77aa4c3..84cbc665a09 100644 --- a/Tests/SentryTests/Networking/SentryHttpTransportTests.swift +++ b/Tests/SentryTests/Networking/SentryHttpTransportTests.swift @@ -90,8 +90,6 @@ class SentryHttpTransportTests: XCTestCase { ] clientReportEnvelope = SentryEnvelope(id: event.eventId, items: clientReportEnvelopeItems) clientReportRequest = buildRequest(clientReportEnvelope) - - dispatchQueueWrapper.dispatchAfterExecutesBlock = true } var sut: SentryHttpTransport { diff --git a/Tests/SentryTests/Networking/TestSentryDispatchQueueWrapper.swift b/Tests/SentryTests/Networking/TestSentryDispatchQueueWrapper.swift index a31b34884e1..bfabe90484b 100644 --- a/Tests/SentryTests/Networking/TestSentryDispatchQueueWrapper.swift +++ b/Tests/SentryTests/Networking/TestSentryDispatchQueueWrapper.swift @@ -3,7 +3,6 @@ import Foundation class TestSentryDispatchQueueWrapper: SentryDispatchQueueWrapper { var dispatchAsyncCalled = 0 - var dispatchAfterExecutesBlock = false override func dispatchAsync(_ block: @escaping () -> Void) { dispatchAsyncCalled += 1 @@ -13,7 +12,14 @@ class TestSentryDispatchQueueWrapper: SentryDispatchQueueWrapper { var blockOnMainInvocations = Invocations<() -> Void>() var blockBeforeMainBlock: () -> Bool = { true } - override func dispatch(onMainQueue block: @escaping () -> Void) { + override func dispatchAsync(onMainQueue block: @escaping () -> Void) { + blockOnMainInvocations.record(block) + if blockBeforeMainBlock() { + block() + } + } + + override func dispatchSync(onMainQueue block: @escaping () -> Void) { blockOnMainInvocations.record(block) if blockBeforeMainBlock() { block() @@ -23,7 +29,7 @@ class TestSentryDispatchQueueWrapper: SentryDispatchQueueWrapper { var dispatchAfterInvocations = Invocations<(interval: TimeInterval, block: () -> Void)>() override func dispatch(after interval: TimeInterval, block: @escaping () -> Void) { dispatchAfterInvocations.record((interval, block)) - if dispatchAfterExecutesBlock { + if blockBeforeMainBlock() { block() } } diff --git a/Tests/SentryTests/Performance/SentryTracerTests.swift b/Tests/SentryTests/Performance/SentryTracerTests.swift index 4c65e0facde..6a3868afaed 100644 --- a/Tests/SentryTests/Performance/SentryTracerTests.swift +++ b/Tests/SentryTests/Performance/SentryTracerTests.swift @@ -38,6 +38,8 @@ class SentryTracerTests: XCTestCase { #endif init() { + dispatchQueue.blockBeforeMainBlock = { false } + CurrentDate.setCurrentDateProvider(currentDateProvider) appStart = currentDateProvider.date() appStartEnd = appStart.addingTimeInterval(0.5) diff --git a/Tests/SentryTests/SentryCrash/SentryCrashReportSinkTest.swift b/Tests/SentryTests/SentryCrash/SentryCrashReportSinkTests.swift similarity index 100% rename from Tests/SentryTests/SentryCrash/SentryCrashReportSinkTest.swift rename to Tests/SentryTests/SentryCrash/SentryCrashReportSinkTests.swift diff --git a/Tests/SentryTests/SentryCrash/SentryUIDeviceWrapperTests.swift b/Tests/SentryTests/SentryCrash/SentryUIDeviceWrapperTests.swift new file mode 100644 index 00000000000..eeda6908032 --- /dev/null +++ b/Tests/SentryTests/SentryCrash/SentryUIDeviceWrapperTests.swift @@ -0,0 +1,14 @@ +import XCTest + +#if os(iOS) +class SentryUIDeviceWrapperTests: XCTestCase { + func testExecutesLogicViaDispatchQueue() { + let dispatchQueue = TestSentryDispatchQueueWrapper() + let sut = SentryUIDeviceWrapper(dispatchQueueWrapper: dispatchQueue) + XCTAssertEqual(dispatchQueue.blockOnMainInvocations.count, 1) + + sut.stop() + XCTAssertEqual(dispatchQueue.blockOnMainInvocations.count, 2) + } +} +#endif diff --git a/Tests/SentryTests/SentryCrash/TestSentryUIDeviceWrapper.swift b/Tests/SentryTests/SentryCrash/TestSentryUIDeviceWrapper.swift index 1c3f625c570..c3caae43b64 100644 --- a/Tests/SentryTests/SentryCrash/TestSentryUIDeviceWrapper.swift +++ b/Tests/SentryTests/SentryCrash/TestSentryUIDeviceWrapper.swift @@ -7,10 +7,6 @@ class TestSentryUIDeviceWrapper: SentryUIDeviceWrapper { var internalBatteryLevel: Float = 0.6 var interalBatteryState = UIDevice.BatteryState.charging - override init() { - // Do nothing - } - override func orientation() -> UIDeviceOrientation { return internalOrientation } From d4933ec25e43e604d5b5dc5ee98baca912443ecc Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Wed, 9 Nov 2022 14:43:51 -0900 Subject: [PATCH 12/13] fix: profile payload issues (#2375) * keep frame index across entire profile, not just within one sample * instead of using indexOfObject: for stack comparison, also use a lookup dictionary of stacks using a custom string key * extract function to handle profile sampler backtrace callbacks * discard profiles with less than 2 samples --- CHANGELOG.md | 1 + Sources/Sentry/SentryProfiler.mm | 165 ++++++++++-------- Sources/Sentry/include/SentryProfiler+Test.h | 17 +- .../Profiling/SentryProfilerTests.mm | 69 ++++++++ .../SentryTests/SentryTests-Bridging-Header.h | 2 +- 5 files changed, 174 insertions(+), 80 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3be7f3c06e8..4584352b924 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Fix issue with invalid profiles uploading (#2358 and #2359) - Call UIDevice methods on the main thread (#2369) +- Avoid sending profiles with 0 samples or incorrectly deduplicated backtrace elements (#2375) ## 7.30.0 diff --git a/Sources/Sentry/SentryProfiler.mm b/Sources/Sentry/SentryProfiler.mm index 70b4cd1358c..ff70e579afc 100644 --- a/Sources/Sentry/SentryProfiler.mm +++ b/Sources/Sentry/SentryProfiler.mm @@ -64,6 +64,86 @@ return [symbolNSStr substringWithRange:[match rangeAtIndex:1]]; } +void +processBacktrace(const Backtrace &backtrace, + NSMutableDictionary *threadMetadata, + NSMutableDictionary *queueMetadata, + NSMutableArray *> *samples, + NSMutableArray *> *stacks, + NSMutableArray *> *frames, + NSMutableDictionary *frameIndexLookup, uint64_t startTimestamp, + NSMutableDictionary *stackIndexLookup) +{ + const auto threadID = [@(backtrace.threadMetadata.threadID) stringValue]; + NSString *queueAddress = nil; + if (backtrace.queueMetadata.address != 0) { + queueAddress = sentry_formatHexAddress(@(backtrace.queueMetadata.address)); + } + NSMutableDictionary *metadata = threadMetadata[threadID]; + if (metadata == nil) { + metadata = [NSMutableDictionary dictionary]; + threadMetadata[threadID] = metadata; + } + if (!backtrace.threadMetadata.name.empty() && metadata[@"name"] == nil) { + metadata[@"name"] = [NSString stringWithUTF8String:backtrace.threadMetadata.name.c_str()]; + } + if (backtrace.threadMetadata.priority != -1 && metadata[@"priority"] == nil) { + metadata[@"priority"] = @(backtrace.threadMetadata.priority); + } + if (queueAddress != nil && queueMetadata[queueAddress] == nil + && backtrace.queueMetadata.label != nullptr) { + queueMetadata[queueAddress] = + @ { @"label" : [NSString stringWithUTF8String:backtrace.queueMetadata.label->c_str()] }; + } +# if defined(DEBUG) + const auto symbols + = backtrace_symbols(reinterpret_cast(backtrace.addresses.data()), + static_cast(backtrace.addresses.size())); +# endif + + const auto stack = [NSMutableArray array]; + for (std::vector::size_type backtraceAddressIdx = 0; + backtraceAddressIdx < backtrace.addresses.size(); backtraceAddressIdx++) { + const auto instructionAddress + = sentry_formatHexAddress(@(backtrace.addresses[backtraceAddressIdx])); + + const auto frameIndex = frameIndexLookup[instructionAddress]; + if (frameIndex == nil) { + const auto frame = [NSMutableDictionary dictionary]; + frame[@"instruction_addr"] = instructionAddress; +# if defined(DEBUG) + frame[@"function"] = parseBacktraceSymbolsFunctionName(symbols[backtraceAddressIdx]); +# endif + [stack addObject:@(frames.count)]; + frameIndexLookup[instructionAddress] = @(frames.count); + [frames addObject:frame]; + } else { + [stack addObject:frameIndex]; + } + } + + const auto sample = [NSMutableDictionary dictionary]; + sample[@"elapsed_since_start_ns"] = + [@(getDurationNs(startTimestamp, backtrace.absoluteTimestamp)) stringValue]; + sample[@"thread_id"] = threadID; + if (queueAddress != nil) { + sample[@"queue_address"] = queueAddress; + } + + const auto stackKey = [stack componentsJoinedByString:@"|"]; + const auto stackIndex = stackIndexLookup[stackKey]; + if (stackIndex) { + sample[@"stack_id"] = stackIndex; + } else { + const auto nextStackIndex = @(stacks.count); + sample[@"stack_id"] = nextStackIndex; + stackIndexLookup[stackKey] = nextStackIndex; + [stacks addObject:stack]; + } + + [samples addObject:sample]; +} + std::mutex _gProfilerLock; NSMutableDictionary *_gProfilersPerSpanID; SentryProfiler *_Nullable _gCurrentProfiler; @@ -350,6 +430,8 @@ - (void)start const auto samples = [NSMutableArray *> array]; const auto stacks = [NSMutableArray *> array]; const auto frames = [NSMutableArray *> array]; + const auto frameIndexLookup = [NSMutableDictionary dictionary]; + const auto stackIndexLookup = [NSMutableDictionary dictionary]; sampledProfile[@"samples"] = samples; sampledProfile[@"stacks"] = stacks; sampledProfile[@"frames"] = frames; @@ -368,82 +450,15 @@ - (void)start __weak const auto weakSelf = self; _profiler = std::make_shared( [weakSelf, threadMetadata, queueMetadata, samples, mainThreadID = _mainThreadID, frames, - stacks](auto &backtrace) { + frameIndexLookup, stacks, stackIndexLookup](auto &backtrace) { const auto strongSelf = weakSelf; if (strongSelf == nil) { + SENTRY_LOG_WARN( + @"Profiler instance no longer exists, cannot process next sample."); return; } - const auto threadID = [@(backtrace.threadMetadata.threadID) stringValue]; - NSString *queueAddress = nil; - if (backtrace.queueMetadata.address != 0) { - queueAddress = sentry_formatHexAddress(@(backtrace.queueMetadata.address)); - } - NSMutableDictionary *metadata = threadMetadata[threadID]; - if (metadata == nil) { - metadata = [NSMutableDictionary dictionary]; - threadMetadata[threadID] = metadata; - } - if (!backtrace.threadMetadata.name.empty() && metadata[@"name"] == nil) { - metadata[@"name"] = - [NSString stringWithUTF8String:backtrace.threadMetadata.name.c_str()]; - } - if (backtrace.threadMetadata.priority != -1 && metadata[@"priority"] == nil) { - metadata[@"priority"] = @(backtrace.threadMetadata.priority); - } - if (queueAddress != nil && queueMetadata[queueAddress] == nil - && backtrace.queueMetadata.label != nullptr) { - queueMetadata[queueAddress] = @{ - @"label" : - [NSString stringWithUTF8String:backtrace.queueMetadata.label->c_str()] - }; - } -# if defined(DEBUG) - const auto symbols - = backtrace_symbols(reinterpret_cast(backtrace.addresses.data()), - static_cast(backtrace.addresses.size())); -# endif - - const auto stack = [NSMutableArray array]; - const auto frameIndexLookup = - [NSMutableDictionary dictionary]; - for (std::vector::size_type i = 0; i < backtrace.addresses.size(); i++) { - const auto instructionAddress - = sentry_formatHexAddress(@(backtrace.addresses[i])); - - const auto frameIndex = frameIndexLookup[instructionAddress]; - - if (frameIndex == nil) { - const auto frame = [NSMutableDictionary dictionary]; - frame[@"instruction_addr"] = instructionAddress; -# if defined(DEBUG) - frame[@"function"] = parseBacktraceSymbolsFunctionName(symbols[i]); -# endif - [stack addObject:@(frames.count)]; - [frames addObject:frame]; - frameIndexLookup[instructionAddress] = @(stack.count); - } else { - [stack addObject:frameIndex]; - } - } - - const auto sample = [NSMutableDictionary dictionary]; - sample[@"elapsed_since_start_ns"] = - [@(getDurationNs(strongSelf->_startTimestamp, backtrace.absoluteTimestamp)) - stringValue]; - sample[@"thread_id"] = threadID; - if (queueAddress != nil) { - sample[@"queue_address"] = queueAddress; - } - - const auto stackIndex = [stacks indexOfObject:stack]; - if (stackIndex != NSNotFound) { - sample[@"stack_id"] = @(stackIndex); - } else { - sample[@"stack_id"] = @(stacks.count); - [stacks addObject:stack]; - } - - [samples addObject:sample]; + processBacktrace(backtrace, threadMetadata, queueMetadata, samples, stacks, frames, + frameIndexLookup, strongSelf->_startTimestamp, stackIndexLookup); }, kSentryProfilerFrequencyHz); _profiler->startSampling(); @@ -486,6 +501,12 @@ - (void)captureEnvelope @synchronized(self) { profile = [_profile mutableCopy]; } + + if ([((NSArray *)profile[@"profile"][@"samples"]) count] < 2) { + SENTRY_LOG_DEBUG(@"No samples located in profile"); + return; + } + profile[@"version"] = @"1"; const auto debugImages = [NSMutableArray *> new]; const auto debugMeta = [_debugImageProvider getDebugImages]; diff --git a/Sources/Sentry/include/SentryProfiler+Test.h b/Sources/Sentry/include/SentryProfiler+Test.h index 076d243a84a..8ad95a01fb0 100644 --- a/Sources/Sentry/include/SentryProfiler+Test.h +++ b/Sources/Sentry/include/SentryProfiler+Test.h @@ -1,11 +1,14 @@ +#include "SentryBacktrace.hpp" #import "SentryProfiler.h" #import "SentryProfilingConditionals.h" #if SENTRY_TARGET_PROFILING_SUPPORTED -@interface -SentryProfiler (SentryTest) - -+ (void)timeoutAbort; - -@end -#endif // SENTRY_TARGET_PROFILING_SUPPORTED +void processBacktrace(const sentry::profiling::Backtrace &backtrace, + NSMutableDictionary *threadMetadata, + NSMutableDictionary *queueMetadata, + NSMutableArray *> *samples, + NSMutableArray *> *stacks, + NSMutableArray *> *frames, + NSMutableDictionary *frameIndexLookup, uint64_t startTimestamp, + NSMutableDictionary *stackIndexLookup); +#endif diff --git a/Tests/SentryTests/Profiling/SentryProfilerTests.mm b/Tests/SentryTests/Profiling/SentryProfilerTests.mm index 90ccf34d369..5111f9ca733 100644 --- a/Tests/SentryTests/Profiling/SentryProfilerTests.mm +++ b/Tests/SentryTests/Profiling/SentryProfilerTests.mm @@ -1,7 +1,10 @@ +#import "SentryProfiler+Test.h" #import "SentryProfilingConditionals.h" #if SENTRY_TARGET_PROFILING_SUPPORTED +using namespace sentry::profiling; + # import "SentryProfiler.h" # import # import @@ -49,6 +52,72 @@ - (void)testProfilerCanBeInitializedOffMainThread handler:^(NSError *_Nullable error) { NSLog(@"%@", error); }]; } +- (void)testProfilerPayload +{ + const auto resolvedThreadMetadata = + [NSMutableDictionary dictionary]; + const auto resolvedQueueMetadata = [NSMutableDictionary dictionary]; + const auto resolvedStacks = [NSMutableArray *> array]; + const auto resolvedSamples = [NSMutableArray *> array]; + const auto resolvedFrames = [NSMutableArray *> array]; + const auto frameIndexLookup = [NSMutableDictionary dictionary]; + const auto stackIndexLookup = [NSMutableDictionary dictionary]; + const auto profileStartTimestamp = 0; + + // record an initial backtrace + + ThreadMetadata threadMetadata1; + threadMetadata1.name = "testThread"; + threadMetadata1.threadID = 12345568910; + threadMetadata1.priority = 666; + + QueueMetadata queueMetadata1; + queueMetadata1.address = 9876543210; + queueMetadata1.label = std::make_shared("testQueue"); + + const auto addresses1 = std::vector({ 123, 456, 789 }); + + Backtrace backtrace1; + backtrace1.threadMetadata = threadMetadata1; + backtrace1.queueMetadata = queueMetadata1; + backtrace1.absoluteTimestamp = 5; + backtrace1.addresses = addresses1; + + processBacktrace(backtrace1, resolvedThreadMetadata, resolvedQueueMetadata, resolvedSamples, + resolvedStacks, resolvedFrames, frameIndexLookup, profileStartTimestamp, stackIndexLookup); + + // record a second backtrace with some common addresses to test frame deduplication + + ThreadMetadata threadMetadata2; + threadMetadata2.name = "testThread"; + threadMetadata2.threadID = 12345568910; + threadMetadata2.priority = 666; + + QueueMetadata queueMetadata2; + queueMetadata2.address = 9876543210; + queueMetadata2.label = std::make_shared("testQueue"); + + const auto addresses2 = std::vector({ 777, 888, 789 }); + + Backtrace backtrace2; + backtrace2.threadMetadata = threadMetadata2; + backtrace2.queueMetadata = queueMetadata2; + backtrace2.absoluteTimestamp = 5; + backtrace2.addresses = addresses2; + + processBacktrace(backtrace2, resolvedThreadMetadata, resolvedQueueMetadata, resolvedSamples, + resolvedStacks, resolvedFrames, frameIndexLookup, profileStartTimestamp, stackIndexLookup); + + // record a third backtrace that's identical to the second to test stack deduplication + + processBacktrace(backtrace2, resolvedThreadMetadata, resolvedQueueMetadata, resolvedSamples, + resolvedStacks, resolvedFrames, frameIndexLookup, profileStartTimestamp, stackIndexLookup); + + XCTAssertEqual(resolvedFrames.count, 5UL); + XCTAssertEqual(resolvedStacks.count, 2UL); + XCTAssertEqual(resolvedSamples.count, 3UL); +} + @end #endif diff --git a/Tests/SentryTests/SentryTests-Bridging-Header.h b/Tests/SentryTests/SentryTests-Bridging-Header.h index d5b4b21e7ac..8845fa563b7 100644 --- a/Tests/SentryTests/SentryTests-Bridging-Header.h +++ b/Tests/SentryTests/SentryTests-Bridging-Header.h @@ -116,7 +116,7 @@ #import "SentryPerformanceTracker.h" #import "SentryPerformanceTrackingIntegration.h" #import "SentryPredicateDescriptor.h" -#import "SentryProfiler+Test.h" +#import "SentryProfiler.h" #import "SentryQueueableRequestManager.h" #import "SentryRandom.h" #import "SentryRateLimitParser.h" From 71fd3032635fed58ae1c1ba22bb7ffa158dbb5ee Mon Sep 17 00:00:00 2001 From: getsentry-bot Date: Thu, 10 Nov 2022 01:07:12 +0000 Subject: [PATCH 13/13] release: 7.30.2 --- CHANGELOG.md | 2 +- Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj | 8 ++++---- Sentry.podspec | 2 +- Sources/Configuration/Sentry.xcconfig | 2 +- Sources/Sentry/SentryMeta.m | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4584352b924..d936df4c737 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Changelog -## Unreleased +## 7.30.2 ### Fixes diff --git a/Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj b/Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj index 3fd493faa5d..47b7303a508 100644 --- a/Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj +++ b/Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj @@ -1096,7 +1096,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 7.30.0; + MARKETING_VERSION = 7.30.2; PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.sample.iOS-Swift"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "match Development io.sentry.sample.iOS-Swift"; @@ -1125,7 +1125,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 7.30.0; + MARKETING_VERSION = 7.30.2; PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.sample.iOS-Swift"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "match AppStore io.sentry.sample.iOS-Swift"; @@ -1770,7 +1770,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 7.30.0; + MARKETING_VERSION = 7.30.2; PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.sample.iOS-Swift.Clip"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "match Development io.sentry.sample.iOS-Swift.Clip"; @@ -1805,7 +1805,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 7.30.0; + MARKETING_VERSION = 7.30.2; PRODUCT_BUNDLE_IDENTIFIER = "io.sentry.sample.iOS-Swift.Clip"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "match AppStore io.sentry.sample.iOS-Swift.Clip"; diff --git a/Sentry.podspec b/Sentry.podspec index 8cc151b2ff3..746cc54d8c2 100644 --- a/Sentry.podspec +++ b/Sentry.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Sentry" - s.version = "7.30.0" + s.version = "7.30.2" s.summary = "Sentry client for cocoa" s.homepage = "https://github.com/getsentry/sentry-cocoa" s.license = "mit" diff --git a/Sources/Configuration/Sentry.xcconfig b/Sources/Configuration/Sentry.xcconfig index f93455b6434..a3af26c4eb3 100644 --- a/Sources/Configuration/Sentry.xcconfig +++ b/Sources/Configuration/Sentry.xcconfig @@ -28,7 +28,7 @@ MACH_O_TYPE = mh_dylib FRAMEWORK_VERSION = A PRODUCT_NAME = Sentry -CURRENT_PROJECT_VERSION = 7.30.0 +CURRENT_PROJECT_VERSION = 7.30.2 INFOPLIST_FILE = Sources/Sentry/Info.plist PRODUCT_BUNDLE_IDENTIFIER = io.sentry.Sentry ALWAYS_SEARCH_USER_PATHS = NO diff --git a/Sources/Sentry/SentryMeta.m b/Sources/Sentry/SentryMeta.m index 63eeb36ed40..3cf8d44aa40 100644 --- a/Sources/Sentry/SentryMeta.m +++ b/Sources/Sentry/SentryMeta.m @@ -5,7 +5,7 @@ @implementation SentryMeta // Don't remove the static keyword. If you do the compiler adds the constant name to the global // symbol table and it might clash with other constants. When keeping the static keyword the // compiler replaces all occurrences with the value. -static NSString *versionString = @"7.30.0"; +static NSString *versionString = @"7.30.2"; static NSString *sdkName = @"sentry.cocoa"; + (NSString *)versionString