From 15cf6bf273458fa326bc356ad0a65281a9bf81ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Aug 2023 10:29:11 +0200 Subject: [PATCH 01/13] build(deps): bump activesupport from 7.0.6 to 7.0.7.2 (#3254) Bumps [activesupport](https://github.com/rails/rails) from 7.0.6 to 7.0.7.2. - [Release notes](https://github.com/rails/rails/releases) - [Changelog](https://github.com/rails/rails/blob/v7.0.7.2/activesupport/CHANGELOG.md) - [Commits](https://github.com/rails/rails/compare/v7.0.6...v7.0.7.2) --- updated-dependencies: - dependency-name: activesupport dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0a8eb24fc94..dd8d2d0d057 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,7 +3,7 @@ GEM specs: CFPropertyList (3.0.6) rexml - activesupport (7.0.6) + activesupport (7.0.7.2) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) @@ -216,7 +216,7 @@ GEM mini_magick (4.12.0) mini_mime (1.1.2) mini_portile2 (2.8.4) - minitest (5.18.1) + minitest (5.19.0) molinillo (0.8.0) multi_json (1.15.0) multipart-post (2.3.0) From 30331154bc6db8391a2f43350ecb1f48c880f716 Mon Sep 17 00:00:00 2001 From: Ivan Dlugos <6349682+vaind@users.noreply.github.com> Date: Mon, 28 Aug 2023 16:09:48 +0200 Subject: [PATCH 02/13] chore: update profiling API for hybrid SDKs (#3255) * chore: update profiling API for hybrid SDKs * add thread ID to hybrid SDK profile payload --- Sentry.xcodeproj/project.pbxproj | 8 ++--- ...entrySDKOnly.m => PrivateSentrySDKOnly.mm} | 29 +++++++++++++----- .../HybridPublic/PrivateSentrySDKOnly.h | 14 +++++++-- .../PrivateSentrySDKOnlyTests.swift | 30 +++++++++++++++++-- 4 files changed, 63 insertions(+), 18 deletions(-) rename Sources/Sentry/{PrivateSentrySDKOnly.m => PrivateSentrySDKOnly.mm} (82%) diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 7a820c7fef0..2686da382d0 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -377,7 +377,7 @@ 7B6C5F8126034354007F7DFF /* SentryWatchdogTerminationLogic.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B6C5F8026034354007F7DFF /* SentryWatchdogTerminationLogic.h */; }; 7B6C5F8726034395007F7DFF /* SentryWatchdogTerminationLogic.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B6C5F8626034395007F7DFF /* SentryWatchdogTerminationLogic.m */; }; 7B6CC50224EE5A42001816D7 /* SentryHubTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6CC50124EE5A42001816D7 /* SentryHubTests.swift */; }; - 7B6D1261265F784000C9BE4B /* PrivateSentrySDKOnly.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D1260265F784000C9BE4B /* PrivateSentrySDKOnly.m */; }; + 7B6D1261265F784000C9BE4B /* PrivateSentrySDKOnly.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D1260265F784000C9BE4B /* PrivateSentrySDKOnly.mm */; }; 7B6D1263265F7CC600C9BE4B /* PrivateSentrySDKOnlyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D1262265F7CC600C9BE4B /* PrivateSentrySDKOnlyTests.swift */; }; 7B6D135C27F4605D00331ED2 /* TestEnvelopeRateLimitDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D135B27F4605D00331ED2 /* TestEnvelopeRateLimitDelegate.swift */; }; 7B6D98E924C6D336005502FA /* SentrySdkInfo+Equality.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B6D98E824C6D336005502FA /* SentrySdkInfo+Equality.m */; }; @@ -1277,7 +1277,7 @@ 7B6C5F8026034354007F7DFF /* SentryWatchdogTerminationLogic.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryWatchdogTerminationLogic.h; path = include/SentryWatchdogTerminationLogic.h; sourceTree = ""; }; 7B6C5F8626034395007F7DFF /* SentryWatchdogTerminationLogic.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryWatchdogTerminationLogic.m; sourceTree = ""; }; 7B6CC50124EE5A42001816D7 /* SentryHubTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryHubTests.swift; sourceTree = ""; }; - 7B6D1260265F784000C9BE4B /* PrivateSentrySDKOnly.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrivateSentrySDKOnly.m; sourceTree = ""; }; + 7B6D1260265F784000C9BE4B /* PrivateSentrySDKOnly.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PrivateSentrySDKOnly.mm; 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 = ""; }; 7B6D98E724C6D336005502FA /* SentrySdkInfo+Equality.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentrySdkInfo+Equality.h"; sourceTree = ""; }; @@ -2286,7 +2286,7 @@ 63AA76931EB9C1C200D153DE /* Sentry.h */, D8BBD32628FD9FBF0011F850 /* SentrySwift.h */, D81A346B291AECC7005A27A9 /* PrivateSentrySDKOnly.h */, - 7B6D1260265F784000C9BE4B /* PrivateSentrySDKOnly.m */, + 7B6D1260265F784000C9BE4B /* PrivateSentrySDKOnly.mm */, 63AA76941EB9C1C200D153DE /* SentryClient.h */, 63AA75ED1EB8B3C400D153DE /* SentryClient.m */, 7B85DC1C24EFAFCD007D01D2 /* SentryClient+Private.h */, @@ -4092,7 +4092,7 @@ 7BE1E33424F7E3CB009D3AD0 /* SentryMigrateSessionInit.m in Sources */, 15E0A8F22411A45A00F044E3 /* SentrySession.m in Sources */, 844EDCE62947DC3100C86F34 /* SentryNSTimerFactory.m in Sources */, - 7B6D1261265F784000C9BE4B /* PrivateSentrySDKOnly.m in Sources */, + 7B6D1261265F784000C9BE4B /* PrivateSentrySDKOnly.mm in Sources */, 63BE85711ECEC6DE00DC44F5 /* NSDate+SentryExtras.m in Sources */, 7BD4BD4927EB2A5D0071F4FF /* SentryDiscardedEvent.m in Sources */, 03F84D3827DD4191008FE43F /* SentryBacktrace.cpp in Sources */, diff --git a/Sources/Sentry/PrivateSentrySDKOnly.m b/Sources/Sentry/PrivateSentrySDKOnly.mm similarity index 82% rename from Sources/Sentry/PrivateSentrySDKOnly.m rename to Sources/Sentry/PrivateSentrySDKOnly.mm index 7ac4444b56c..befce66fe20 100644 --- a/Sources/Sentry/PrivateSentrySDKOnly.m +++ b/Sources/Sentry/PrivateSentrySDKOnly.mm @@ -8,9 +8,11 @@ #import "SentryInstallation.h" #import "SentryInternalDefines.h" #import "SentryMeta.h" +#import "SentryProfiledTracerConcurrency.h" #import "SentryProfiler.h" #import "SentrySDK+Private.h" #import "SentrySerialization.h" +#import "SentryThreadHandle.hpp" #import "SentryUser+Private.h" #import "SentryViewHierarchy.h" #import @@ -121,27 +123,38 @@ + (NSDictionary *)getExtraContext } #if SENTRY_TARGET_PROFILING_SUPPORTED -+ (uint64_t)startProfilingForTrace:(SentryId *)traceId; ++ (uint64_t)startProfilerForTrace:(SentryId *)traceId; { [SentryProfiler startWithTracer:traceId]; return SentryDependencyContainer.sharedInstance.dateProvider.systemTime; } -+ (nullable NSDictionary *)collectProfileForTrace:(SentryId *)traceId - since:(uint64_t)startSystemTime; ++ (nullable NSDictionary *)collectProfileBetween:(uint64_t)startSystemTime + and:(uint64_t)endSystemTime + forTrace:(SentryId *)traceId; { - NSMutableDictionary *payload = [SentryProfiler - collectProfileBetween:startSystemTime - and:SentryDependencyContainer.sharedInstance.dateProvider.systemTime - forTrace:traceId - onHub:[SentrySDK currentHub]]; + NSMutableDictionary *payload = + [SentryProfiler collectProfileBetween:startSystemTime + and:endSystemTime + forTrace:traceId + onHub:[SentrySDK currentHub]]; if (payload != nil) { payload[@"platform"] = SentryPlatformName; + payload[@"transaction"] = @{ + @"active_thread_id" : + [NSNumber numberWithLongLong:sentry::profiling::ThreadHandle::current()->tid()] + }; } return payload; } + ++ (void)discardProfilerForTrace:(SentryId *)traceId; +{ + discardProfilerForTracer(traceId); +} + #endif // SENTRY_TARGET_PROFILING_SUPPORTED #if SENTRY_HAS_UIKIT diff --git a/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h b/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h index 79674c49cba..a80a900cd7d 100644 --- a/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h +++ b/Sources/Sentry/include/HybridPublic/PrivateSentrySDKOnly.h @@ -85,13 +85,21 @@ typedef void (^SentryOnAppStartMeasurementAvailable)( * Start a profiler session associated with the given @c SentryId. * @return The system time when the profiler session started. */ -+ (uint64_t)startProfilingForTrace:(SentryId *)traceId; ++ (uint64_t)startProfilerForTrace:(SentryId *)traceId; /** * Collect a profiler session data associated with the given @c SentryId. + * This also discards the profiler. */ -+ (nullable NSDictionary *)collectProfileForTrace:(SentryId *)traceId - since:(uint64_t)startSystemTime; ++ (nullable NSDictionary *)collectProfileBetween:(uint64_t)startSystemTime + and:(uint64_t)endSystemTime + forTrace:(SentryId *)traceId; + +/** + * Discard profiler session data associated with the given @c SentryId. + * This only needs to be called in case you haven't collected the profile (and don't intend to). + */ ++ (void)discardProfilerForTrace:(SentryId *)traceId; #endif @property (class, nullable, nonatomic, copy) diff --git a/Tests/SentryTests/PrivateSentrySDKOnlyTests.swift b/Tests/SentryTests/PrivateSentrySDKOnlyTests.swift index a43c4c97728..908cfc3d4e3 100644 --- a/Tests/SentryTests/PrivateSentrySDKOnlyTests.swift +++ b/Tests/SentryTests/PrivateSentrySDKOnlyTests.swift @@ -124,7 +124,7 @@ class PrivateSentrySDKOnlyTests: XCTestCase { /** * Smoke Tests profiling via PrivateSentrySDKOnly. Actual profiling unit tests are done elsewhere. */ - func testProfiling() { + func testProfilingStartAndCollect() { let options = Options() options.dsn = TestConstants.dsnAsString(username: "SentryFramesTrackingIntegrationTests") let client = TestClient(options: options) @@ -132,10 +132,10 @@ class PrivateSentrySDKOnlyTests: XCTestCase { let traceIdA = SentryId() - let startTime = PrivateSentrySDKOnly.startProfiling(forTrace: traceIdA) + let startTime = PrivateSentrySDKOnly.startProfiler(forTrace: traceIdA) XCTAssertGreaterThan(startTime, 0) Thread.sleep(forTimeInterval: 0.2) - let payload = PrivateSentrySDKOnly.collectProfile(forTrace: traceIdA, since: startTime) + let payload = PrivateSentrySDKOnly.collectProfileBetween(startTime, and: startTime + 200_000_000, forTrace: traceIdA) XCTAssertNotNil(payload) XCTAssertEqual(payload?["platform"] as? String, "cocoa") XCTAssertNotNil(payload?["debug_meta"]) @@ -146,6 +146,30 @@ class PrivateSentrySDKOnlyTests: XCTestCase { XCTAssertNotNil(profile?["samples"]) XCTAssertNotNil(profile?["stacks"]) XCTAssertNotNil(profile?["frames"]) + let transactionInfo = payload?["transaction"] as? NSDictionary + XCTAssertNotNil(transactionInfo) + XCTAssertGreaterThan(transactionInfo?["active_thread_id"] as! Int64, 0) + } + + func testProfilingDiscard() { + let options = Options() + options.dsn = TestConstants.dsnAsString(username: "SentryFramesTrackingIntegrationTests") + let client = TestClient(options: options) + SentrySDK.setCurrentHub(TestHub(client: client, andScope: nil)) + + let traceIdA = SentryId() + + let startTime = PrivateSentrySDKOnly.startProfiler(forTrace: traceIdA) + XCTAssertGreaterThan(startTime, 0) + Thread.sleep(forTimeInterval: 0.2) + PrivateSentrySDKOnly.discardProfiler(forTrace: traceIdA) + // how can we test that that this fails with an NCAssert failure? + // XCTAssertThrowsError( + // PrivateSentrySDKOnly.collectProfileBetween( + // startTime, and: startTime + 200_000_000, forTrace: traceIdA) + // ) { error in + // XCTAssertTrue(error is NSException) + // } } #endif From b9d59f71c5e6d620b54c57bd85e97ea3ab6785c1 Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Mon, 28 Aug 2023 06:28:05 -0800 Subject: [PATCH 03/13] ref: anonymize SentryEvent (MetricKit) (#3240) --- Sources/Sentry/SentryEvent.m | 29 +++++++++++++++++++ Sources/Sentry/SentryMetricKitIntegration.m | 25 ---------------- Sources/Sentry/SentryScreenshotIntegration.m | 2 +- .../Sentry/SentryViewHierarchyIntegration.m | 2 +- Sources/Sentry/include/SentryEvent+Private.h | 5 ++++ .../include/SentryMetricKitIntegration.h | 7 ----- .../MetricKit/SentryMetricKitEventTests.swift | 12 ++++---- 7 files changed, 42 insertions(+), 40 deletions(-) diff --git a/Sources/Sentry/SentryEvent.m b/Sources/Sentry/SentryEvent.m index 95c8828888b..de83a6fa1a6 100644 --- a/Sources/Sentry/SentryEvent.m +++ b/Sources/Sentry/SentryEvent.m @@ -17,6 +17,11 @@ #import "SentryThread.h" #import "SentryUser.h" +#if SENTRY_HAS_METRIC_KIT +# import "SentryMechanism.h" +# import "SentryMetricKitIntegration.h" +#endif // SENTRY_HAS_METRIC_KIT + NS_ASSUME_NONNULL_BEGIN @implementation SentryEvent @@ -172,6 +177,30 @@ - (NSMutableArray *)serializeBreadcrumbs return crumbs; } +#if SENTRY_HAS_METRIC_KIT + +- (BOOL)isMetricKitEvent +{ + if (self.exceptions == nil || self.exceptions.count != 1) { + return NO; + } + + NSArray *metricKitMechanisms = @[ + SentryMetricKitDiskWriteExceptionMechanism, SentryMetricKitCpuExceptionMechanism, + SentryMetricKitHangDiagnosticMechanism, @"MXCrashDiagnostic" + ]; + + SentryException *exception = self.exceptions[0]; + if (exception.mechanism != nil && + [metricKitMechanisms containsObject:exception.mechanism.type]) { + return YES; + } else { + return NO; + } +} + +#endif // SENTRY_HAS_METRIC_KIT + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryMetricKitIntegration.m b/Sources/Sentry/SentryMetricKitIntegration.m index bd5ba54f240..1cb7af79422 100644 --- a/Sources/Sentry/SentryMetricKitIntegration.m +++ b/Sources/Sentry/SentryMetricKitIntegration.m @@ -449,31 +449,6 @@ - (SentryStacktrace *)convertMXFramesToSentryStacktrace:(NSEnumerator *metricKitMechanisms = @[ - SentryMetricKitDiskWriteExceptionMechanism, SentryMetricKitCpuExceptionMechanism, - SentryMetricKitHangDiagnosticMechanism, @"MXCrashDiagnostic" - ]; - - SentryException *exception = self.exceptions[0]; - if (exception.mechanism != nil && - [metricKitMechanisms containsObject:exception.mechanism.type]) { - return YES; - } else { - return NO; - } -} - -@end - NS_ASSUME_NONNULL_END #endif // SENTRY_HAS_METRIC_KIT diff --git a/Sources/Sentry/SentryScreenshotIntegration.m b/Sources/Sentry/SentryScreenshotIntegration.m index 08d3cee4119..f3ceecb897b 100644 --- a/Sources/Sentry/SentryScreenshotIntegration.m +++ b/Sources/Sentry/SentryScreenshotIntegration.m @@ -57,7 +57,7 @@ - (void)uninstall // We don't take screenshots if the event is a crash or metric kit event. if ((event.exceptions == nil && event.error == nil) || event.isCrashEvent # if SENTRY_HAS_METRIC_KIT - || event.isMetricKitEvent + || [event isMetricKitEvent] # endif // SENTRY_HAS_METRIC_KIT ) { return attachments; diff --git a/Sources/Sentry/SentryViewHierarchyIntegration.m b/Sources/Sentry/SentryViewHierarchyIntegration.m index 7d784eaca13..4154460372e 100644 --- a/Sources/Sentry/SentryViewHierarchyIntegration.m +++ b/Sources/Sentry/SentryViewHierarchyIntegration.m @@ -63,7 +63,7 @@ - (void)uninstall // We don't attach the view hierarchy if the event is a crash or metric kit event. if ((event.exceptions == nil && event.error == nil) || event.isCrashEvent # if SENTRY_HAS_METRIC_KIT - || event.isMetricKitEvent + || [event isMetricKitEvent] # endif // SENTRY_HAS_METRIC_KIT ) { return attachments; diff --git a/Sources/Sentry/include/SentryEvent+Private.h b/Sources/Sentry/include/SentryEvent+Private.h index 73464098fd2..c28e338b29e 100644 --- a/Sources/Sentry/include/SentryEvent+Private.h +++ b/Sources/Sentry/include/SentryEvent+Private.h @@ -1,3 +1,4 @@ +#import "SentryDefines.h" #import "SentryEvent.h" #import "SentryProfilingConditionals.h" #import @@ -25,4 +26,8 @@ SentryEvent () @property (nonatomic) uint64_t endSystemTime; #endif // SENTRY_TARGET_PROFILING_SUPPORTED +#if SENTRY_HAS_METRIC_KIT +- (BOOL)isMetricKitEvent; +#endif // SENTRY_HAS_METRIC_KIT + @end diff --git a/Sources/Sentry/include/SentryMetricKitIntegration.h b/Sources/Sentry/include/SentryMetricKitIntegration.h index 6bc9dbb1c13..fdd5f738d89 100644 --- a/Sources/Sentry/include/SentryMetricKitIntegration.h +++ b/Sources/Sentry/include/SentryMetricKitIntegration.h @@ -26,13 +26,6 @@ API_UNAVAILABLE(tvos, watchos) @end -@interface -SentryEvent (MetricKit) - -@property (nonatomic, readonly) BOOL isMetricKitEvent; - -@end - NS_ASSUME_NONNULL_END #endif // SENTRY_HAS_METRIC_KIT diff --git a/Tests/SentryTests/Integrations/MetricKit/SentryMetricKitEventTests.swift b/Tests/SentryTests/Integrations/MetricKit/SentryMetricKitEventTests.swift index 3fdda88e83f..707934ad568 100644 --- a/Tests/SentryTests/Integrations/MetricKit/SentryMetricKitEventTests.swift +++ b/Tests/SentryTests/Integrations/MetricKit/SentryMetricKitEventTests.swift @@ -5,27 +5,27 @@ import XCTest final class SentryMetricKitEventTests: XCTestCase { func testMXCPUException_IsMetricKitEvent() { - XCTAssertTrue(TestData.metricKitEvent.isMetricKitEvent) + XCTAssertTrue(TestData.metricKitEvent.isMetricKitEvent()) } func testMXDiskWriteException_IsMetricKitEvent() { - XCTAssertTrue(createMetricKitEventWith(mechanismType: SentryMetricKitDiskWriteExceptionMechanism).isMetricKitEvent) + XCTAssertTrue(createMetricKitEventWith(mechanismType: SentryMetricKitDiskWriteExceptionMechanism).isMetricKitEvent()) } func testMXHangDiagnostic_IsMetricKitEvent() { - XCTAssertTrue(createMetricKitEventWith(mechanismType: SentryMetricKitHangDiagnosticMechanism).isMetricKitEvent) + XCTAssertTrue(createMetricKitEventWith(mechanismType: SentryMetricKitHangDiagnosticMechanism).isMetricKitEvent()) } func testWatchDogEvent_IsNotMetricKitEvent() { - XCTAssertFalse(TestData.oomEvent.isMetricKitEvent) + XCTAssertFalse(TestData.oomEvent.isMetricKitEvent()) } func testNormalEvent_IsNotMetricKitEvent() { - XCTAssertFalse(TestData.event.isMetricKitEvent) + XCTAssertFalse(TestData.event.isMetricKitEvent()) } func testEmptyEvent_IsNotMetricKitEvent() { - XCTAssertFalse(Event().isMetricKitEvent) + XCTAssertFalse(Event().isMetricKitEvent()) } private func createMetricKitEventWith(mechanismType: String) -> Event { From a4231611a441a8aefd6f8e572dd921d38b6b08e5 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Tue, 29 Aug 2023 10:43:21 +0200 Subject: [PATCH 04/13] Distributed tracing without performance (#3196) Pass through / add sentry-trace and baggage even if performance is disabled Co-authored-by: Andrew McKnight --- CHANGELOG.md | 6 + Sentry.xcodeproj/project.pbxproj | 8 + SentryTestUtils/TestTransportAdapter.swift | 5 - Sources/Sentry/SentryClient.m | 54 ++++--- Sources/Sentry/SentryNetworkTracker.m | 142 ++++++++++-------- Sources/Sentry/SentryPropagationContext.h | 19 +++ Sources/Sentry/SentryPropagationContext.m | 50 ++++++ Sources/Sentry/SentryScope.m | 9 ++ Sources/Sentry/SentryTransportAdapter.m | 5 - Sources/Sentry/include/SentryScope+Private.h | 9 ++ .../Sentry/include/SentryTransportAdapter.h | 4 - .../Network/SentryNetworkTrackerTests.swift | 16 +- .../Performance/Network/URLSessionTaskMock.h | 2 + .../Performance/Network/URLSessionTaskMock.m | 5 + .../SentryTransportAdapterTests.swift | 2 +- Tests/SentryTests/SentryClientTests.swift | 16 +- Tests/SentryTests/SentryScopeSwiftTests.swift | 20 ++- .../SentryTests/SentryTests-Bridging-Header.h | 1 + scripts/no-changes-in-high-risk-files.sh | 4 +- 19 files changed, 259 insertions(+), 118 deletions(-) create mode 100644 Sources/Sentry/SentryPropagationContext.h create mode 100644 Sources/Sentry/SentryPropagationContext.m diff --git a/CHANGELOG.md b/CHANGELOG.md index 615d8685f60..1de993546ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +- Distributed tracing without performance (#3196) + +### Features + ## 8.10.0 ### Features diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 2686da382d0..0e4a6013851 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -803,6 +803,8 @@ D8BFE37229A3782F002E73F3 /* SentryTimeToDisplayTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = D8BFE37029A3782F002E73F3 /* SentryTimeToDisplayTracker.h */; }; D8BFE37329A3782F002E73F3 /* SentryTimeToDisplayTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = D8BFE37129A3782F002E73F3 /* SentryTimeToDisplayTracker.m */; }; D8BFE37929A76666002E73F3 /* SentryTimeToDisplayTrackerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8BFE37729A76519002E73F3 /* SentryTimeToDisplayTrackerTest.swift */; }; + D8C66A362A77B1F70015696A /* SentryPropagationContext.h in Headers */ = {isa = PBXBuildFile; fileRef = D8C66A342A77B1F70015696A /* SentryPropagationContext.h */; }; + D8C66A372A77B1F70015696A /* SentryPropagationContext.m in Sources */ = {isa = PBXBuildFile; fileRef = D8C66A352A77B1F70015696A /* SentryPropagationContext.m */; }; D8C67E9B28000E24007E326E /* SentryUIApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = D8C67E9928000E23007E326E /* SentryUIApplication.h */; }; D8C67E9C28000E24007E326E /* SentryScreenshot.h in Headers */ = {isa = PBXBuildFile; fileRef = D8C67E9A28000E23007E326E /* SentryScreenshot.h */; }; D8CB74152947246600A5F964 /* SentryEnvelopeAttachmentHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = D8CB74142947246600A5F964 /* SentryEnvelopeAttachmentHeader.h */; }; @@ -1753,6 +1755,8 @@ D8BFE37029A3782F002E73F3 /* SentryTimeToDisplayTracker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryTimeToDisplayTracker.h; path = include/SentryTimeToDisplayTracker.h; sourceTree = ""; }; D8BFE37129A3782F002E73F3 /* SentryTimeToDisplayTracker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryTimeToDisplayTracker.m; sourceTree = ""; }; D8BFE37729A76519002E73F3 /* SentryTimeToDisplayTrackerTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryTimeToDisplayTrackerTest.swift; sourceTree = ""; }; + D8C66A342A77B1F70015696A /* SentryPropagationContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SentryPropagationContext.h; sourceTree = ""; }; + D8C66A352A77B1F70015696A /* SentryPropagationContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryPropagationContext.m; sourceTree = ""; }; D8C67E9928000E23007E326E /* SentryUIApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryUIApplication.h; path = include/SentryUIApplication.h; sourceTree = ""; }; D8C67E9A28000E23007E326E /* SentryScreenshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryScreenshot.h; path = include/SentryScreenshot.h; sourceTree = ""; }; D8CB74142947246600A5F964 /* SentryEnvelopeAttachmentHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryEnvelopeAttachmentHeader.h; path = include/SentryEnvelopeAttachmentHeader.h; sourceTree = ""; }; @@ -2092,6 +2096,8 @@ 7BCFBD662681C95000BC27D8 /* SentryScopeObserver.h */, 15360CEF2433A16D00112302 /* SentryInstallation.h */, 15360CEC2433A15500112302 /* SentryInstallation.m */, + D8C66A342A77B1F70015696A /* SentryPropagationContext.h */, + D8C66A352A77B1F70015696A /* SentryPropagationContext.m */, ); name = State; sourceTree = ""; @@ -3619,6 +3625,7 @@ D865892F29D6ECA7000BE151 /* SentryCrashBinaryImageCache.h in Headers */, 6344DDB41EC309E000D9160D /* SentryCrashReportSink.h in Headers */, 7D427C62237B1D200046BAC8 /* SentrySDK.h in Headers */, + D8C66A362A77B1F70015696A /* SentryPropagationContext.h in Headers */, D867063F27C3BC2400048851 /* SentryCoreDataTracker.h in Headers */, 7B9657252683104C00C66E25 /* NSData+Sentry.h in Headers */, 7B6C5EDA264E8D860010D138 /* SentryFramesTrackingIntegration.h in Headers */, @@ -4044,6 +4051,7 @@ D85852B627ECEEDA00C6D8AE /* SentryScreenshot.m in Sources */, 7D5C441C237C2E1F00DAB0A3 /* SentryHub.m in Sources */, 63FE715920DA4C1100CDBAE8 /* SentryCrashCPU_x86_32.c in Sources */, + D8C66A372A77B1F70015696A /* SentryPropagationContext.m in Sources */, 7BE912AD272162D900E49E62 /* SentryNoOpSpan.m in Sources */, 63FE710D20DA4C1000CDBAE8 /* SentryCrashStackCursor_MachineContext.c in Sources */, 63FE70E120DA4C1000CDBAE8 /* SentryCrashMonitor_CPPException.cpp in Sources */, diff --git a/SentryTestUtils/TestTransportAdapter.swift b/SentryTestUtils/TestTransportAdapter.swift index 0135eb69c76..73ce0473dfd 100644 --- a/SentryTestUtils/TestTransportAdapter.swift +++ b/SentryTestUtils/TestTransportAdapter.swift @@ -1,11 +1,6 @@ import Foundation public class TestTransportAdapter: SentryTransportAdapter { - - public override func send(event: Event, attachments: [Attachment]) { - self.send(event: event, traceContext: nil, attachments: attachments) - } - public override func send(_ event: Event, session: SentrySession, attachments: [Attachment]) { self.send(event, with: session, traceContext: nil, attachments: attachments) } diff --git a/Sources/Sentry/SentryClient.m b/Sources/Sentry/SentryClient.m index b90b2c83041..09fd8681f9a 100644 --- a/Sources/Sentry/SentryClient.m +++ b/Sources/Sentry/SentryClient.m @@ -32,6 +32,7 @@ #import "SentryMeta.h" #import "SentryNSError.h" #import "SentryOptions+Private.h" +#import "SentryPropagationContext.h" #import "SentryRandom.h" #import "SentrySDK+Private.h" #import "SentryScope+Private.h" @@ -351,10 +352,15 @@ - (nullable SentryTraceContext *)getTraceStateWithEvent:(SentryEvent *)event } SentryTracer *tracer = [SentryTracer getTracer:span]; - if (tracer == nil) - return nil; + if (tracer != nil) { + return [[SentryTraceContext alloc] initWithTracer:tracer scope:scope options:_options]; + } + + if (event.error || event.exceptions.count > 0) { + return scope.propagationContext.traceContext; + } - return [[SentryTraceContext alloc] initWithTracer:tracer scope:scope options:_options]; + return nil; } - (SentryId *)sendEvent:(SentryEvent *)event @@ -380,27 +386,26 @@ - (SentryId *)sendEvent:(SentryEvent *)event alwaysAttachStacktrace:alwaysAttachStacktrace isCrashEvent:isCrashEvent]; - if (nil != preparedEvent) { - SentryTraceContext *traceContext = [self getTraceStateWithEvent:event withScope:scope]; - - NSArray *attachments = scope.attachments; - if (self.attachmentProcessors.count) { - for (id attachmentProcessor in self - .attachmentProcessors) { - attachments = [attachmentProcessor processAttachments:attachments - forEvent:preparedEvent]; - } - } + if (preparedEvent == nil) { + return SentryId.empty; + } - [self.transportAdapter sendEvent:preparedEvent - traceContext:traceContext - attachments:attachments - additionalEnvelopeItems:additionalEnvelopeItems]; + SentryTraceContext *traceContext = [self getTraceStateWithEvent:event withScope:scope]; - return preparedEvent.eventId; + NSArray *attachments = scope.attachments; + if (self.attachmentProcessors.count) { + for (id attachmentProcessor in self.attachmentProcessors) { + attachments = [attachmentProcessor processAttachments:attachments + forEvent:preparedEvent]; + } } - return SentryId.empty; + [self.transportAdapter sendEvent:preparedEvent + traceContext:traceContext + attachments:attachments + additionalEnvelopeItems:additionalEnvelopeItems]; + + return preparedEvent.eventId; } - (SentryId *)sendEvent:(SentryEvent *)event @@ -416,9 +421,9 @@ - (SentryId *)sendEvent:(SentryEvent *)event } } - if (nil == session.releaseName || [session.releaseName length] == 0) { - SentryTraceContext *traceContext = [self getTraceStateWithEvent:event withScope:scope]; + SentryTraceContext *traceContext = [self getTraceStateWithEvent:event withScope:scope]; + if (nil == session.releaseName || [session.releaseName length] == 0) { SENTRY_LOG_DEBUG(DropSessionLogMessage); [self.transportAdapter sendEvent:event @@ -427,7 +432,10 @@ - (SentryId *)sendEvent:(SentryEvent *)event return event.eventId; } - [self.transportAdapter sendEvent:event session:session attachments:attachments]; + [self.transportAdapter sendEvent:event + withSession:session + traceContext:traceContext + attachments:attachments]; return event.eventId; } diff --git a/Sources/Sentry/SentryNetworkTracker.m b/Sources/Sentry/SentryNetworkTracker.m index 3400238d8aa..7c1500014f5 100644 --- a/Sources/Sentry/SentryNetworkTracker.m +++ b/Sources/Sentry/SentryNetworkTracker.m @@ -11,6 +11,7 @@ #import "SentryLog.h" #import "SentryMechanism.h" #import "SentryNoOpSpan.h" +#import "SentryPropagationContext.h" #import "SentryRequest.h" #import "SentrySDK+Private.h" #import "SentryScope+Private.h" @@ -115,12 +116,19 @@ - (BOOL)isTargetMatch:(NSURL *)URL withTargets:(NSArray *)targets return NO; } +- (BOOL)sessionTaskRequiresPropagation:(NSURLSessionTask *)sessionTask +{ + return sessionTask.currentRequest != nil && + [self isTargetMatch:sessionTask.currentRequest.URL + withTargets:SentrySDK.options.tracePropagationTargets]; +} + - (void)urlSessionTaskResume:(NSURLSessionTask *)sessionTask { - @synchronized(self) { - if (!self.isNetworkTrackingEnabled) { - return; - } + NSURLSessionTaskState sessionState = sessionTask.state; + if (sessionState == NSURLSessionTaskStateCompleted + || sessionState == NSURLSessionTaskStateCanceling) { + return; } if (![self isTaskSupported:sessionTask]) @@ -143,14 +151,15 @@ - (void)urlSessionTaskResume:(NSURLSessionTask *)sessionTask return; } - UrlSanitized *safeUrl = [[UrlSanitized alloc] initWithURL:url]; - - @synchronized(sessionTask) { - if (sessionTask.state == NSURLSessionTaskStateCompleted - || sessionTask.state == NSURLSessionTaskStateCanceling) { + @synchronized(self) { + if (!self.isNetworkTrackingEnabled) { + [self addTraceWithoutTransactionToTask:sessionTask]; return; } + } + UrlSanitized *safeUrl = [[UrlSanitized alloc] initWithURL:url]; + @synchronized(sessionTask) { __block id span; __block id netSpan; netSpan = objc_getAssociatedObject(sessionTask, &SENTRY_NETWORK_REQUEST_TRACKER_SPAN); @@ -187,62 +196,12 @@ - (void)urlSessionTaskResume:(NSURLSessionTask *)sessionTask // otherwise we have nothing else to do here. if (netSpan == nil || [netSpan isKindOfClass:[SentryNoOpSpan class]]) { SENTRY_LOG_DEBUG(@"No transaction bound to scope. Won't track network operation."); + [self addTraceWithoutTransactionToTask:sessionTask]; return; } - if ([sessionTask currentRequest] && - [self isTargetMatch:sessionTask.currentRequest.URL - withTargets:SentrySDK.options.tracePropagationTargets]) { - NSString *baggageHeader = @""; - - SentryTracer *tracer = [SentryTracer getTracer:span]; - if (tracer != nil) { - baggageHeader = [[tracer.traceContext toBaggage] - toHTTPHeaderWithOriginalBaggage: - [SentrySerialization - decodeBaggage:sessionTask.currentRequest - .allHTTPHeaderFields[SENTRY_BAGGAGE_HEADER]]]; - } - - // First we check if the current request is mutable, so we could easily add a new - // header. Otherwise we try to change the current request for a new one with the extra - // header. - if ([sessionTask.currentRequest isKindOfClass:[NSMutableURLRequest class]]) { - NSMutableURLRequest *currentRequest - = (NSMutableURLRequest *)sessionTask.currentRequest; - [currentRequest setValue:[netSpan toTraceHeader].value - forHTTPHeaderField:SENTRY_TRACE_HEADER]; - - if (baggageHeader.length > 0) { - [currentRequest setValue:baggageHeader - forHTTPHeaderField:SENTRY_BAGGAGE_HEADER]; - } - } else { - // Even though NSURLSessionTask doesn't have 'setCurrentRequest', some subclasses - // do. For those subclasses we replace the currentRequest with a mutable one with - // the additional trace header. Since NSURLSessionTask is a public class and can be - // override, we believe this is not considered a private api. - SEL setCurrentRequestSelector = NSSelectorFromString(@"setCurrentRequest:"); - if ([sessionTask respondsToSelector:setCurrentRequestSelector]) { - NSMutableURLRequest *newRequest = [sessionTask.currentRequest mutableCopy]; - - [newRequest setValue:[netSpan toTraceHeader].value - forHTTPHeaderField:SENTRY_TRACE_HEADER]; - - if (baggageHeader.length > 0) { - [newRequest setValue:baggageHeader - forHTTPHeaderField:SENTRY_BAGGAGE_HEADER]; - } - - void (*func)(id, SEL, id param) - = (void *)[sessionTask methodForSelector:setCurrentRequestSelector]; - func(sessionTask, setCurrentRequestSelector, newRequest); - } - } - } else { - SENTRY_LOG_DEBUG(@"Not adding trace_id and baggage headers for %@", - sessionTask.currentRequest.URL.absoluteString); - } + SentryBaggage *baggage = [[[SentryTracer getTracer:span] traceContext] toBaggage]; + [self addBaggageHeader:baggage traceHeader:[netSpan toTraceHeader] toRequest:sessionTask]; SENTRY_LOG_DEBUG( @"SentryNetworkTracker automatically started HTTP span for sessionTask: %@", @@ -253,6 +212,65 @@ - (void)urlSessionTaskResume:(NSURLSessionTask *)sessionTask } } +- (void)addTraceWithoutTransactionToTask:(NSURLSessionTask *)sessionTask +{ + SentryPropagationContext *propagationContext = SentrySDK.currentHub.scope.propagationContext; + [self addBaggageHeader:[[propagationContext traceContext] toBaggage] + traceHeader:[propagationContext traceHeader] + toRequest:sessionTask]; +} + +- (void)addBaggageHeader:(SentryBaggage *)baggage + traceHeader:(SentryTraceHeader *)traceHeader + toRequest:(NSURLSessionTask *)sessionTask +{ + if (![self sessionTaskRequiresPropagation:sessionTask]) { + SENTRY_LOG_DEBUG(@"Not adding trace_id and baggage headers for %@", + sessionTask.currentRequest.URL.absoluteString); + return; + } + NSString *baggageHeader = @""; + + if (baggage != nil) { + baggageHeader = + [baggage toHTTPHeaderWithOriginalBaggage: + [SentrySerialization + decodeBaggage:sessionTask.currentRequest + .allHTTPHeaderFields[SENTRY_BAGGAGE_HEADER]]]; + } + + // First we check if the current request is mutable, so we could easily add a new + // header. Otherwise we try to change the current request for a new one with the extra + // header. + if ([sessionTask.currentRequest isKindOfClass:[NSMutableURLRequest class]]) { + NSMutableURLRequest *currentRequest = (NSMutableURLRequest *)sessionTask.currentRequest; + [currentRequest setValue:traceHeader.value forHTTPHeaderField:SENTRY_TRACE_HEADER]; + + if (baggageHeader.length > 0) { + [currentRequest setValue:baggageHeader forHTTPHeaderField:SENTRY_BAGGAGE_HEADER]; + } + } else { + // Even though NSURLSessionTask doesn't have 'setCurrentRequest', some subclasses + // do. For those subclasses we replace the currentRequest with a mutable one with + // the additional trace header. Since NSURLSessionTask is a public class and can be + // override, we believe this is not considered a private api. + SEL setCurrentRequestSelector = NSSelectorFromString(@"setCurrentRequest:"); + if ([sessionTask respondsToSelector:setCurrentRequestSelector]) { + NSMutableURLRequest *newRequest = [sessionTask.currentRequest mutableCopy]; + + [newRequest setValue:traceHeader.value forHTTPHeaderField:SENTRY_TRACE_HEADER]; + + if (baggageHeader.length > 0) { + [newRequest setValue:baggageHeader forHTTPHeaderField:SENTRY_BAGGAGE_HEADER]; + } + + void (*func)(id, SEL, id param) + = (void *)[sessionTask methodForSelector:setCurrentRequestSelector]; + func(sessionTask, setCurrentRequestSelector, newRequest); + } + } +} + - (void)urlSessionTask:(NSURLSessionTask *)sessionTask setState:(NSURLSessionTaskState)newState { if (!self.isNetworkTrackingEnabled && !self.isNetworkBreadcrumbEnabled diff --git a/Sources/Sentry/SentryPropagationContext.h b/Sources/Sentry/SentryPropagationContext.h new file mode 100644 index 00000000000..dc5c22fae8f --- /dev/null +++ b/Sources/Sentry/SentryPropagationContext.h @@ -0,0 +1,19 @@ +#import + +@class SentryId, SentrySpanId, SentryTraceContext, SentryTraceHeader; + +NS_ASSUME_NONNULL_BEGIN + +@interface SentryPropagationContext : NSObject + +@property (nonatomic, strong) SentryId *traceId; +@property (nonatomic, strong) SentrySpanId *spanId; +@property (nonatomic, readonly, nullable) SentryTraceContext *traceContext; + +@property (nonatomic, readonly) SentryTraceHeader *traceHeader; + +- (NSDictionary *)traceContextForEvent; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryPropagationContext.m b/Sources/Sentry/SentryPropagationContext.m new file mode 100644 index 00000000000..3ae84152b61 --- /dev/null +++ b/Sources/Sentry/SentryPropagationContext.m @@ -0,0 +1,50 @@ +#import "SentryPropagationContext.h" +#import "SentryDSN.h" +#import "SentryHub+Private.h" +#import "SentryId.h" +#import "SentryOptions+Private.h" +#import "SentrySDK+Private.h" +#import "SentryScope+Private.h" +#import "SentrySpanId.h" +#import "SentryTraceContext.h" +#import "SentryTraceHeader.h" +#import "SentryUser+Private.h" + +@implementation SentryPropagationContext + +- (instancetype)init +{ + if (self = [super init]) { + self.traceId = [[SentryId alloc] init]; + self.spanId = [[SentrySpanId alloc] init]; + } + return self; +} + +- (SentryTraceHeader *)traceHeader +{ + return [[SentryTraceHeader alloc] initWithTraceId:self.traceId + spanId:self.spanId + sampled:kSentrySampleDecisionNo]; +} + +- (SentryTraceContext *)traceContext +{ + SentryOptions *options = SentrySDK.options; + SentryScope *scope = SentrySDK.currentHub.scope; + return [[SentryTraceContext alloc] initWithTraceId:self.traceId + publicKey:options.parsedDsn.url.user + releaseName:options.releaseName + environment:options.environment + transaction:nil + userSegment:scope.userObject.segment + sampleRate:nil]; +} + +- (NSDictionary *)traceContextForEvent +{ + return + @{ @"span_id" : self.spanId.sentrySpanIdString, @"trace_id" : self.traceId.sentryIdString }; +} + +@end diff --git a/Sources/Sentry/SentryScope.m b/Sources/Sentry/SentryScope.m index 5888c17d41f..66fd5ffe01c 100644 --- a/Sources/Sentry/SentryScope.m +++ b/Sources/Sentry/SentryScope.m @@ -6,6 +6,7 @@ #import "SentryGlobalEventProcessor.h" #import "SentryLevelMapper.h" #import "SentryLog.h" +#import "SentryPropagationContext.h" #import "SentryScope+Private.h" #import "SentryScopeObserver.h" #import "SentrySession.h" @@ -75,6 +76,7 @@ - (instancetype)initWithMaxBreadcrumbs:(NSInteger)maxBreadcrumbs self.fingerprintArray = [NSMutableArray new]; _spanLock = [[NSObject alloc] init]; self.observers = [NSMutableArray new]; + self.propagationContext = [[SentryPropagationContext alloc] init]; } return self; } @@ -94,6 +96,7 @@ - (instancetype)initWithScope:(SentryScope *)scope [_fingerprintArray addObjectsFromArray:[scope fingerprints]]; [_attachmentArray addObjectsFromArray:[scope attachments]]; + self.propagationContext = [[SentryPropagationContext alloc] init]; self.maxBreadcrumbs = scope.maxBreadcrumbs; self.userObject = scope.userObject.copy; self.distString = scope.distString; @@ -542,6 +545,12 @@ - (SentryEvent *__nullable)applyToEvent:(SentryEvent *)event newContext[@"trace"] = [span serialize]; } } + + if (newContext[@"trace"] == nil) { + // If this is an error event we need to add the distributed trace context. + newContext[@"trace"] = [self.propagationContext traceContextForEvent]; + } + event.context = newContext; return event; } diff --git a/Sources/Sentry/SentryTransportAdapter.m b/Sources/Sentry/SentryTransportAdapter.m index 235d490ad23..829886da2a1 100644 --- a/Sources/Sentry/SentryTransportAdapter.m +++ b/Sources/Sentry/SentryTransportAdapter.m @@ -27,11 +27,6 @@ - (instancetype)initWithTransport:(id)transport options:(Sentry return self; } -- (void)sendEvent:(SentryEvent *)event attachments:(NSArray *)attachments -{ - [self sendEvent:event traceContext:nil attachments:attachments]; -} - - (void)sendEvent:(SentryEvent *)event session:(SentrySession *)session attachments:(NSArray *)attachments diff --git a/Sources/Sentry/include/SentryScope+Private.h b/Sources/Sentry/include/SentryScope+Private.h index 3c012295e4e..de662b856f2 100644 --- a/Sources/Sentry/include/SentryScope+Private.h +++ b/Sources/Sentry/include/SentryScope+Private.h @@ -4,6 +4,7 @@ #import "SentryScopeObserver.h" @class SentryAttachment; +@class SentryPropagationContext; NS_ASSUME_NONNULL_BEGIN @@ -14,8 +15,16 @@ SentryScope () @property (atomic, strong, readonly) NSArray *attachments; +/** + * Set global user -> thus will be sent with every event + */ @property (atomic, strong) SentryUser *_Nullable userObject; +@property (atomic, strong) SentryPropagationContext *propagationContext; + +/** + * used to add values in event context. + */ @property (atomic, strong) NSMutableDictionary *> *contextDictionary; diff --git a/Sources/Sentry/include/SentryTransportAdapter.h b/Sources/Sentry/include/SentryTransportAdapter.h index 502e0945da0..276e3e3adfe 100644 --- a/Sources/Sentry/include/SentryTransportAdapter.h +++ b/Sources/Sentry/include/SentryTransportAdapter.h @@ -18,10 +18,6 @@ SENTRY_NO_INIT - (instancetype)initWithTransport:(id)transport options:(SentryOptions *)options; -- (void)sendEvent:(SentryEvent *)event - attachments:(NSArray *)attachments - NS_SWIFT_NAME(send(event:attachments:)); - - (void)sendEvent:(SentryEvent *)event session:(SentrySession *)session attachments:(NSArray *)attachments; diff --git a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift index 81d02e42d0d..8628aed1728 100644 --- a/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Performance/Network/SentryNetworkTrackerTests.swift @@ -581,7 +581,7 @@ class SentryNetworkTrackerTests: XCTestCase { XCTAssertEqual(task.currentRequest?.allHTTPHeaderFields?["sentry-trace"] ?? "", expectedTraceHeader) } - func testNoHeadersWhenDisabled() { + func testDefaultHeadersWhenDisabled() { let sut = fixture.getSut() sut.disable() @@ -589,17 +589,21 @@ class SentryNetworkTrackerTests: XCTestCase { _ = startTransaction() as! SentryTracer sut.urlSessionTaskResume(task) - XCTAssertNil(task.currentRequest?.allHTTPHeaderFields?["baggage"]) - XCTAssertNil(task.currentRequest?.allHTTPHeaderFields?["sentry-trace"]) + let expectedTraceHeader = SentrySDK.currentHub().scope.propagationContext.traceHeader.value() + let expectedBaggageHeader = SentrySDK.currentHub().scope.propagationContext.traceContext?.toBaggage().toHTTPHeader() + XCTAssertEqual(task.currentRequest?.allHTTPHeaderFields?["baggage"] ?? "", expectedBaggageHeader) + XCTAssertEqual(task.currentRequest?.allHTTPHeaderFields?["sentry-trace"] ?? "", expectedTraceHeader) } - func testNoHeadersWhenNoTransaction() { + func testDefaultHeadersWhenNoTransaction() { let sut = fixture.getSut() let task = createDataTask() sut.urlSessionTaskResume(task) - XCTAssertNil(task.currentRequest?.allHTTPHeaderFields?["baggage"]) - XCTAssertNil(task.currentRequest?.allHTTPHeaderFields?["sentry-trace"]) + let expectedTraceHeader = SentrySDK.currentHub().scope.propagationContext.traceHeader.value() + let expectedBaggageHeader = SentrySDK.currentHub().scope.propagationContext.traceContext?.toBaggage().toHTTPHeader() + XCTAssertEqual(task.currentRequest?.allHTTPHeaderFields?["baggage"] ?? "", expectedBaggageHeader) + XCTAssertEqual(task.currentRequest?.allHTTPHeaderFields?["sentry-trace"] ?? "", expectedTraceHeader) } func testNoHeadersForWrongUrl() { diff --git a/Tests/SentryTests/Integrations/Performance/Network/URLSessionTaskMock.h b/Tests/SentryTests/Integrations/Performance/Network/URLSessionTaskMock.h index 941e87076b5..3074412ffd8 100644 --- a/Tests/SentryTests/Integrations/Performance/Network/URLSessionTaskMock.h +++ b/Tests/SentryTests/Integrations/Performance/Network/URLSessionTaskMock.h @@ -71,6 +71,8 @@ static int64_t const DATA_BYTES_SENT = 652; - (NSURLRequest *)currentRequest NS_UNAVAILABLE; +- (NSURLSessionTaskState)state; + @end NS_ASSUME_NONNULL_END diff --git a/Tests/SentryTests/Integrations/Performance/Network/URLSessionTaskMock.m b/Tests/SentryTests/Integrations/Performance/Network/URLSessionTaskMock.m index 31a3da2cf1f..dbc1b82b209 100644 --- a/Tests/SentryTests/Integrations/Performance/Network/URLSessionTaskMock.m +++ b/Tests/SentryTests/Integrations/Performance/Network/URLSessionTaskMock.m @@ -294,4 +294,9 @@ - (NSURLRequest *)currentRequest @throw @"currentRequest not available"; } +- (NSURLSessionTaskState)state +{ + return NSURLSessionTaskStateRunning; +} + @end diff --git a/Tests/SentryTests/Networking/SentryTransportAdapterTests.swift b/Tests/SentryTests/Networking/SentryTransportAdapterTests.swift index 148fdd2bc6b..8177c8d13fa 100644 --- a/Tests/SentryTests/Networking/SentryTransportAdapterTests.swift +++ b/Tests/SentryTests/Networking/SentryTransportAdapterTests.swift @@ -44,7 +44,7 @@ class SentryTransportAdapterTests: XCTestCase { func testSendFaultyAttachment_FaultyAttachmentGetsDropped() { let event = TestData.event - sut.send(event: event, attachments: [fixture.faultyAttachment, fixture.attachment]) + sut.send(event: event, traceContext: nil, attachments: [fixture.faultyAttachment, fixture.attachment]) let expectedEnvelope = SentryEnvelope(id: event.eventId, items: [ SentryEnvelopeItem(event: event), diff --git a/Tests/SentryTests/SentryClientTests.swift b/Tests/SentryTests/SentryClientTests.swift index 12812647750..7d834609d2f 100644 --- a/Tests/SentryTests/SentryClientTests.swift +++ b/Tests/SentryTests/SentryClientTests.swift @@ -525,7 +525,8 @@ class SentryClientTest: XCTestCase { func testCaptureErrorWithSession() { let sessionBlockExpectation = expectation(description: "session block gets called") - let eventId = fixture.getSut().captureError(error, with: Scope()) { + let scope = Scope() + let eventId = fixture.getSut().captureError(error, with: scope) { sessionBlockExpectation.fulfill() return self.fixture.session } @@ -536,6 +537,9 @@ class SentryClientTest: XCTestCase { if let eventWithSessionArguments = fixture.transportAdapter.sentEventsWithSessionTraceState.last { assertValidErrorEvent(eventWithSessionArguments.event, error) XCTAssertEqual(fixture.session, eventWithSessionArguments.session) + + XCTAssertEqual(eventWithSessionArguments.traceContext?.traceId, + scope.propagationContext.traceContext?.traceId) } } @@ -1371,11 +1375,12 @@ class SentryClientTest: XCTestCase { let transaction = fixture.transaction let client = fixture.getSut() client.capture(event: transaction) - + XCTAssertNotNil(fixture.transportAdapter.sendEventWithTraceStateInvocations.first?.traceContext) + XCTAssertEqual(fixture.transportAdapter.sendEventWithTraceStateInvocations.first?.traceContext?.traceId, transaction.trace.traceId) } - func testCaptureEvent_traceInScope_sendTraceState() { + func testCaptureEvent_sendTraceState() { let event = Event(level: SentryLevel.warning) event.message = fixture.message let scope = Scope() @@ -1383,10 +1388,9 @@ class SentryClientTest: XCTestCase { let client = fixture.getSut() client.capture(event: event, scope: scope) - - client.capture(event: event) - + XCTAssertNotNil(fixture.transportAdapter.sendEventWithTraceStateInvocations.first?.traceContext) + XCTAssertEqual(fixture.transportAdapter.sendEventWithTraceStateInvocations.first?.traceContext?.traceId, fixture.trace.traceId) } func test_AddCrashReportAttacment_withViewHierarchy() { diff --git a/Tests/SentryTests/SentryScopeSwiftTests.swift b/Tests/SentryTests/SentryScopeSwiftTests.swift index a064a301b15..1b7c4b91978 100644 --- a/Tests/SentryTests/SentryScopeSwiftTests.swift +++ b/Tests/SentryTests/SentryScopeSwiftTests.swift @@ -150,7 +150,8 @@ class SentryScopeSwiftTests: XCTestCase { func testApplyToEvent() { let actual = fixture.scope.applyTo(event: fixture.event, maxBreadcrumbs: 10) - + let actualContext = actual?.context as? [String: [String: String]] + XCTAssertEqual(fixture.tags, actual?.tags) XCTAssertEqual(fixture.extra, actual?.extra as? [String: String]) XCTAssertEqual(fixture.user, actual?.user) @@ -159,7 +160,8 @@ class SentryScopeSwiftTests: XCTestCase { XCTAssertEqual(fixture.fingerprint, actual?.fingerprint) XCTAssertEqual(fixture.level, actual?.level) XCTAssertEqual([fixture.breadcrumb], actual?.breadcrumbs) - XCTAssertEqual(fixture.context, actual?.context as? [String: [String: String]]) + XCTAssertEqual(fixture.context["c"], actualContext?["c"]) + XCTAssertNotNil(actualContext?["trace"]) } func testApplyToEvent_EventWithTags() { @@ -267,7 +269,8 @@ class SentryScopeSwiftTests: XCTestCase { } func testApplyToEvent_EventWithContext() { - let context = NSMutableDictionary(dictionary: ["my": ["extra": "context"]]) + let context = NSMutableDictionary(dictionary: ["my": ["extra": "context"], + "trace": fixture.scope.propagationContext.traceForEvent() ]) let event = fixture.event event.context = context as? [String: [String: String]] @@ -277,10 +280,19 @@ class SentryScopeSwiftTests: XCTestCase { XCTAssertEqual(context as? [String: [String: String]], actual?.context as? [String: [String: String]]) } + + func testApplyToEvent_EventWithError_contextHasTrace() { + let event = fixture.event + event.exceptions = [Exception(value: "Error", type: "Exception")] + + let actual = fixture.scope.applyTo(event: event, maxBreadcrumbs: 10) + + XCTAssertNotNil(actual?.context?["trace"]) + } func testApplyToEvent_EventWithContext_MergesContext() { let context = NSMutableDictionary(dictionary: [ - "first": ["a": "b", "c": "d"]]) + "first": ["a": "b", "c": "d"], "trace": fixture.scope.propagationContext.traceForEvent()]) let event = fixture.event event.context = context as? [String: [String: String]] diff --git a/Tests/SentryTests/SentryTests-Bridging-Header.h b/Tests/SentryTests/SentryTests-Bridging-Header.h index 6f6a6679294..18f80f95446 100644 --- a/Tests/SentryTests/SentryTests-Bridging-Header.h +++ b/Tests/SentryTests/SentryTests-Bridging-Header.h @@ -210,6 +210,7 @@ #import "SentryMeasurementValue.h" #import "SentryNSProcessInfoWrapper.h" #import "SentryPerformanceTracker+Testing.h" +#import "SentryPropagationContext.h" #import "SentrySampleDecision+Private.h" #import "SentrySpanOperations.h" #import "SentryTimeToDisplayTracker.h" diff --git a/scripts/no-changes-in-high-risk-files.sh b/scripts/no-changes-in-high-risk-files.sh index 642bf60905e..5a6b0982952 100755 --- a/scripts/no-changes-in-high-risk-files.sh +++ b/scripts/no-changes-in-high-risk-files.sh @@ -1,11 +1,11 @@ #!/bin/bash -set -euxo pipefail +set -euo pipefail # To update the sha run the command in ACTUAL and copy the result in EXPECTED. ACTUAL=$(shasum -a 256 ./Sources/Sentry/SentryNSURLSessionTaskSearch.m ./Sources/Sentry/SentryNetworkTracker.m ./Sources/Sentry/SentryUIViewControllerSwizzling.m ./Sources/Sentry/SentryNSDataSwizzling.m ./Sources/Sentry/SentrySubClassFinder.m ./Sources/Sentry/SentryCoreDataSwizzling.m ./Sources/Sentry/SentrySwizzleWrapper.m ./Sources/Sentry/include/SentrySwizzle.h ./Sources/Sentry/SentrySwizzle.m) EXPECTED="819d5ca5e3db2ac23c859b14c149b7f0754d3ae88bea1dba92c18f49a81da0e1 ./Sources/Sentry/SentryNSURLSessionTaskSearch.m -797f1e4f1f4d0986770c749c6614243417373d3858044a0aa6e16bd4a52533ed ./Sources/Sentry/SentryNetworkTracker.m +545bdd91204ab45d04328dd40233b6fc789b216e1301b5fe2ef23b56db6e3719 ./Sources/Sentry/SentryNetworkTracker.m 128dee523c75c121e9b8b767d84a2a137e5b60498c9f3ba604aad3c935d780d0 ./Sources/Sentry/SentryUIViewControllerSwizzling.m e95e62ec7363984f20c78643bb7d992a41a740f97e1befb71525ac34caf88b37 ./Sources/Sentry/SentryNSDataSwizzling.m 9ad05dd8dd29788cba994736fdcd3bbde59a94e32612640d11f4f9c38ad6610e ./Sources/Sentry/SentrySubClassFinder.m From c76f9b05ff018ade6706fffb7b77a5a385c3e9fb Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Tue, 29 Aug 2023 13:00:16 -0400 Subject: [PATCH 05/13] ci: always run setup_ci (#3258) --- fastlane/Fastfile | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index bfd74a562bb..5879d9df13c 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -263,8 +263,9 @@ platform :ios do desc "Build Perf-test app without Sentry" lane :build_perf_test_app_plain do - - setup_ci + setup_ci( + force: true + ) sync_code_signing( type: "development", @@ -287,7 +288,9 @@ platform :ios do desc "Build Perf-test app with Sentry" lane :build_perf_test_app_sentry do - setup_ci + setup_ci( + force: true + ) sync_code_signing( type: "development", From 72bd9a0c8b01ffc3ddaa248a3f86070e345cf56b Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Tue, 29 Aug 2023 13:00:56 -0400 Subject: [PATCH 06/13] ci: use bundled fastlane (#3257) --- .github/workflows/benchmarking.yml | 11 +++++++---- .github/workflows/build.yml | 6 ++++-- .github/workflows/profile-data-generator.yml | 7 +++++-- .github/workflows/saucelabs-UI-tests.yml | 7 +++++-- .github/workflows/testflight.yml | 4 +++- 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/.github/workflows/benchmarking.yml b/.github/workflows/benchmarking.yml index 5dbe6090bb6..6c2a0a71acf 100644 --- a/.github/workflows/benchmarking.yml +++ b/.github/workflows/benchmarking.yml @@ -27,6 +27,9 @@ jobs: steps: - uses: actions/checkout@v3 - run: ./scripts/ci-select-xcode.sh + - uses: ruby/setup-ruby@v1 + with: + bundler-cache: true - name: Install SentryCli run: brew install getsentry/tools/sentry-cli - run: git apply ./scripts/set-device-tests-environment.patch @@ -45,7 +48,7 @@ jobs: path: | DerivedData/Build/Products/Debug-iphoneos/PerformanceBenchmarks-Runner.app key: ios-swift-for-ui-testing-cache-key-${{ hashFiles('Samples/iOS-Swift/PerformanceBenchmarks/**') }} - - run: fastlane build_ios_swift_for_tests + - run: bundle exec fastlane build_ios_swift_for_tests env: APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} @@ -54,7 +57,7 @@ jobs: MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} - - run: fastlane build_ios_benchmark_test + - run: bundle exec fastlane build_ios_benchmark_test env: APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} @@ -108,7 +111,7 @@ jobs: key: ${{ github.workflow }}-${{ github.job }}-appplain-${{ hashFiles('fastlane/Fastfile', 'Tests/Perf/test-app-plain/**') }} - name: Build test app plain if: steps.app-plain-cache.outputs['cache-hit'] != 'true' - run: fastlane build_perf_test_app_plain + run: bundle exec fastlane build_perf_test_app_plain env: APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} @@ -118,7 +121,7 @@ jobs: MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} - name: Build test app with sentry - run: fastlane build_perf_test_app_sentry + run: bundle exec fastlane build_perf_test_app_sentry env: APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6f8c97aa995..a547dce9598 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,9 @@ jobs: steps: - uses: actions/checkout@v3 - run: ./scripts/ci-select-xcode.sh - + - uses: ruby/setup-ruby@v1 + with: + bundler-cache: true - name: Run Fastlane env: APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} @@ -37,7 +39,7 @@ jobs: MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} - run: fastlane build_ios_swift + run: bundle exec fastlane build_ios_swift shell: sh build-sample: diff --git a/.github/workflows/profile-data-generator.yml b/.github/workflows/profile-data-generator.yml index b87dbf50a79..8244e93c71b 100644 --- a/.github/workflows/profile-data-generator.yml +++ b/.github/workflows/profile-data-generator.yml @@ -17,6 +17,9 @@ jobs: steps: - uses: actions/checkout@v3 - run: ./scripts/ci-select-xcode.sh 13.4.1 + - uses: ruby/setup-ruby@v1 + with: + bundler-cache: true - name: Install SentryCli run: brew install getsentry/tools/sentry-cli - name: Cache Carthage dependencies @@ -43,7 +46,7 @@ jobs: path: | DerivedData/Build/Products/Debug-iphoneos/ProfileDataGeneratorUITest-Runner.app key: profiledatagenerator-test-runner-app-cache-key-${{ hashFiles('Samples/TrendingMovies/ProfileDataGeneratorUITest/**') }} - - run: fastlane build_trending_movies + - run: bundle exec fastlane build_trending_movies if: steps.cache-trending-movies-app.outputs.cache-hit != 'true' env: APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} @@ -53,7 +56,7 @@ jobs: MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} - - run: fastlane build_profile_data_generator_ui_test + - run: bundle exec fastlane build_profile_data_generator_ui_test if: steps.cache-profiledatagenerator-test-runner-app.outputs.cache-hit != 'true' env: APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} diff --git a/.github/workflows/saucelabs-UI-tests.yml b/.github/workflows/saucelabs-UI-tests.yml index c8a0c869cd4..f7931edeb42 100644 --- a/.github/workflows/saucelabs-UI-tests.yml +++ b/.github/workflows/saucelabs-UI-tests.yml @@ -39,6 +39,9 @@ jobs: steps: - uses: actions/checkout@v3 - run: ./scripts/ci-select-xcode.sh ${{matrix.xcode}} + - uses: ruby/setup-ruby@v1 + with: + bundler-cache: true - name: Install SentryCli run: brew install getsentry/tools/sentry-cli - run: git apply ./scripts/set-device-tests-environment.patch @@ -57,7 +60,7 @@ jobs: path: | DerivedData/Build/Products/Test-iphoneos/iOS-SwiftUITests-Runner.app key: ios-swift-for-ui-testing-cache-key-${{ hashFiles('Samples/iOS-Swift/iOS-SwiftUITests/**') }}-Xcode-${{ matrix.xcode }} - - run: fastlane build_ios_swift_for_tests + - run: bundle exec fastlane build_ios_swift_for_tests env: APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} @@ -66,7 +69,7 @@ jobs: MATCH_GIT_PRIVATE_KEY: ${{ secrets.MATCH_GIT_PRIVATE_KEY }} MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} MATCH_USERNAME: ${{ secrets.MATCH_USERNAME }} - - run: fastlane build_ios_swift_ui_test + - run: bundle exec fastlane build_ios_swift_ui_test env: APP_STORE_CONNECT_KEY_ID: ${{ secrets.APP_STORE_CONNECT_KEY_ID }} APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_ISSUER_ID }} diff --git a/.github/workflows/testflight.yml b/.github/workflows/testflight.yml index 1f1df4470e7..ab12b0a6722 100644 --- a/.github/workflows/testflight.yml +++ b/.github/workflows/testflight.yml @@ -22,7 +22,9 @@ jobs: steps: - uses: actions/checkout@v3 - run: ./scripts/ci-select-xcode.sh - - run: bundle install + - uses: ruby/setup-ruby@v1 + with: + bundler-cache: true # We upload a new version to TestFlight on every commit on main # So we need to bump the build number each time From 9c7f314eb026bf27fe99b24a48233493873f17fb Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Tue, 29 Aug 2023 13:01:32 -0400 Subject: [PATCH 07/13] ref: centralize SentrySwizzleWrapper access (#3245) --- SentryTestUtils/ClearTestState.swift | 4 ++-- .../SentryAutoBreadcrumbTrackingIntegration.m | 4 +--- Sources/Sentry/SentryBreadcrumbTracker.m | 15 ++++----------- Sources/Sentry/SentryDependencyContainer.m | 2 +- Sources/Sentry/SentrySwizzleWrapper.m | 8 -------- Sources/Sentry/SentryUIEventTracker.m | 13 ++++++------- Sources/Sentry/SentryUIEventTrackingIntegration.m | 7 +++---- Sources/Sentry/include/SentryBreadcrumbTracker.h | 5 ----- Sources/Sentry/include/SentrySwizzleWrapper.h | 2 -- Sources/Sentry/include/SentryUIEventTracker.h | 7 +++---- .../Helper/SentrySwizzleWrapperTests.swift | 2 +- ...ryAutoBreadcrumbTrackingIntegrationTests.swift | 2 +- .../SentryBreadcrumbTrackerTests.swift | 7 +++---- .../UIEvents/SentryUIEventTrackerTests.swift | 3 ++- scripts/no-changes-in-high-risk-files.sh | 2 +- 15 files changed, 28 insertions(+), 55 deletions(-) diff --git a/SentryTestUtils/ClearTestState.swift b/SentryTestUtils/ClearTestState.swift index 1fdfdf53796..0348f1e526c 100644 --- a/SentryTestUtils/ClearTestState.swift +++ b/SentryTestUtils/ClearTestState.swift @@ -29,8 +29,8 @@ class TestCleanup: NSObject { setenv("ActivePrewarm", "0", 1) SentryAppStartTracker.load() SentryUIViewControllerPerformanceTracker.shared.enableWaitForFullDisplay = false - SentrySwizzleWrapper.sharedInstance.removeAllCallbacks() - #endif + SentryDependencyContainer.sharedInstance().swizzleWrapper.removeAllCallbacks() + #endif // os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) SentryDependencyContainer.reset() Dynamic(SentryGlobalEventProcessor.shared()).removeAllProcessors() diff --git a/Sources/Sentry/SentryAutoBreadcrumbTrackingIntegration.m b/Sources/Sentry/SentryAutoBreadcrumbTrackingIntegration.m index 07c7614bfd5..cb449c1b582 100644 --- a/Sources/Sentry/SentryAutoBreadcrumbTrackingIntegration.m +++ b/Sources/Sentry/SentryAutoBreadcrumbTrackingIntegration.m @@ -26,9 +26,7 @@ - (BOOL)installWithOptions:(SentryOptions *)options } [self installWithOptions:options - breadcrumbTracker:[[SentryBreadcrumbTracker alloc] - initWithSwizzleWrapper:[SentryDependencyContainer sharedInstance] - .swizzleWrapper] + breadcrumbTracker:[[SentryBreadcrumbTracker alloc] init] systemEventBreadcrumbs: [[SentrySystemEventBreadcrumbs alloc] initWithFileManager:[SentryDependencyContainer sharedInstance].fileManager diff --git a/Sources/Sentry/SentryBreadcrumbTracker.m b/Sources/Sentry/SentryBreadcrumbTracker.m index f2cccb57d7d..696c3e0331d 100644 --- a/Sources/Sentry/SentryBreadcrumbTracker.m +++ b/Sources/Sentry/SentryBreadcrumbTracker.m @@ -3,6 +3,7 @@ #import "SentryBreadcrumbDelegate.h" #import "SentryClient.h" #import "SentryDefines.h" +#import "SentryDependencyContainer.h" #import "SentryHub.h" #import "SentryLog.h" #import "SentrySDK+Private.h" @@ -25,21 +26,12 @@ @interface SentryBreadcrumbTracker () -@property (nonatomic, strong) SentrySwizzleWrapper *swizzleWrapper; @property (nonatomic, weak) id delegate; @end @implementation SentryBreadcrumbTracker -- (instancetype)initWithSwizzleWrapper:(SentrySwizzleWrapper *)swizzleWrapper -{ - if (self = [super init]) { - self.swizzleWrapper = swizzleWrapper; - } - return self; -} - - (void)startWithDelegate:(id)delegate { _delegate = delegate; @@ -58,7 +50,8 @@ - (void)stop // All breadcrumbs are guarded by checking the client of the current hub, which we remove when // uninstalling the SDK. Therefore, we don't clean up everything. #if SENTRY_HAS_UIKIT - [self.swizzleWrapper removeSwizzleSendActionForKey:SentryBreadcrumbTrackerSwizzleSendAction]; + [SentryDependencyContainer.sharedInstance.swizzleWrapper + removeSwizzleSendActionForKey:SentryBreadcrumbTrackerSwizzleSendAction]; #endif _delegate = nil; } @@ -163,7 +156,7 @@ + (BOOL)avoidSender:(id)sender forTarget:(id)target action:(NSString *)action - (void)swizzleSendAction { #if SENTRY_HAS_UIKIT - [self.swizzleWrapper + [SentryDependencyContainer.sharedInstance.swizzleWrapper swizzleSendAction:^(NSString *action, id target, id sender, UIEvent *event) { if ([SentryBreadcrumbTracker avoidSender:sender forTarget:target action:action]) { return; diff --git a/Sources/Sentry/SentryDependencyContainer.m b/Sources/Sentry/SentryDependencyContainer.m index d525f214380..9299104dcc2 100644 --- a/Sources/Sentry/SentryDependencyContainer.m +++ b/Sources/Sentry/SentryDependencyContainer.m @@ -208,7 +208,7 @@ - (SentrySwizzleWrapper *)swizzleWrapper if (_swizzleWrapper == nil) { @synchronized(sentryDependencyContainerLock) { if (_swizzleWrapper == nil) { - _swizzleWrapper = SentrySwizzleWrapper.sharedInstance; + _swizzleWrapper = [[SentrySwizzleWrapper alloc] init]; } } } diff --git a/Sources/Sentry/SentrySwizzleWrapper.m b/Sources/Sentry/SentrySwizzleWrapper.m index 2d60a9efe70..0915db6eaf7 100644 --- a/Sources/Sentry/SentrySwizzleWrapper.m +++ b/Sources/Sentry/SentrySwizzleWrapper.m @@ -11,14 +11,6 @@ @implementation SentrySwizzleWrapper *sentrySwizzleSendActionCallbacks; #endif -+ (SentrySwizzleWrapper *)sharedInstance -{ - static SentrySwizzleWrapper *instance = nil; - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ instance = [[self alloc] init]; }); - return instance; -} - #if SENTRY_HAS_UIKIT + (void)initialize { diff --git a/Sources/Sentry/SentryUIEventTracker.m b/Sources/Sentry/SentryUIEventTracker.m index 07a114a311c..22727ca93bf 100644 --- a/Sources/Sentry/SentryUIEventTracker.m +++ b/Sources/Sentry/SentryUIEventTracker.m @@ -3,6 +3,7 @@ #if SENTRY_HAS_UIKIT # import "SentrySwizzleWrapper.h" +# import # import # import # import @@ -24,7 +25,6 @@ @interface SentryUIEventTracker () -@property (nonatomic, strong) SentrySwizzleWrapper *swizzleWrapper; @property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueueWrapper; @property (nonatomic, assign) NSTimeInterval idleTimeout; @property (nullable, nonatomic, strong) NSMutableArray *activeTransactions; @@ -33,12 +33,10 @@ @implementation SentryUIEventTracker -- (instancetype)initWithSwizzleWrapper:(SentrySwizzleWrapper *)swizzleWrapper - dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper - idleTimeout:(NSTimeInterval)idleTimeout +- (instancetype)initWithDispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper + idleTimeout:(NSTimeInterval)idleTimeout { if (self = [super init]) { - self.swizzleWrapper = swizzleWrapper; self.dispatchQueueWrapper = dispatchQueueWrapper; self.idleTimeout = idleTimeout; self.activeTransactions = [NSMutableArray new]; @@ -48,7 +46,7 @@ - (instancetype)initWithSwizzleWrapper:(SentrySwizzleWrapper *)swizzleWrapper - (void)start { - [self.swizzleWrapper + [SentryDependencyContainer.sharedInstance.swizzleWrapper swizzleSendAction:^(NSString *action, id target, id sender, UIEvent *event) { if (target == nil) { SENTRY_LOG_DEBUG(@"Target was nil for action %@; won't capture in transaction " @@ -165,7 +163,8 @@ - (void)start - (void)stop { - [self.swizzleWrapper removeSwizzleSendActionForKey:SentryUIEventTrackerSwizzleSendAction]; + [SentryDependencyContainer.sharedInstance.swizzleWrapper + removeSwizzleSendActionForKey:SentryUIEventTrackerSwizzleSendAction]; } - (NSString *)getOperation:(id)sender diff --git a/Sources/Sentry/SentryUIEventTrackingIntegration.m b/Sources/Sentry/SentryUIEventTrackingIntegration.m index e70ae2b65bf..8aa0e736f38 100644 --- a/Sources/Sentry/SentryUIEventTrackingIntegration.m +++ b/Sources/Sentry/SentryUIEventTrackingIntegration.m @@ -25,10 +25,9 @@ - (BOOL)installWithOptions:(SentryOptions *)options } SentryDependencyContainer *dependencies = [SentryDependencyContainer sharedInstance]; - self.uiEventTracker = [[SentryUIEventTracker alloc] - initWithSwizzleWrapper:[SentryDependencyContainer sharedInstance].swizzleWrapper - dispatchQueueWrapper:dependencies.dispatchQueueWrapper - idleTimeout:options.idleTimeout]; + self.uiEventTracker = + [[SentryUIEventTracker alloc] initWithDispatchQueueWrapper:dependencies.dispatchQueueWrapper + idleTimeout:options.idleTimeout]; [self.uiEventTracker start]; diff --git a/Sources/Sentry/include/SentryBreadcrumbTracker.h b/Sources/Sentry/include/SentryBreadcrumbTracker.h index 8a9b7ffc247..b211a422683 100644 --- a/Sources/Sentry/include/SentryBreadcrumbTracker.h +++ b/Sources/Sentry/include/SentryBreadcrumbTracker.h @@ -2,14 +2,9 @@ NS_ASSUME_NONNULL_BEGIN -@class SentrySwizzleWrapper; - @protocol SentryBreadcrumbDelegate; @interface SentryBreadcrumbTracker : NSObject -SENTRY_NO_INIT - -- (instancetype)initWithSwizzleWrapper:(SentrySwizzleWrapper *)swizzleWrapper; - (void)startWithDelegate:(id)delegate; - (void)startSwizzle; diff --git a/Sources/Sentry/include/SentrySwizzleWrapper.h b/Sources/Sentry/include/SentrySwizzleWrapper.h index 11e3a7aef01..eb13986c2a1 100644 --- a/Sources/Sentry/include/SentrySwizzleWrapper.h +++ b/Sources/Sentry/include/SentrySwizzleWrapper.h @@ -17,8 +17,6 @@ typedef void (^SentrySwizzleSendActionCallback)( */ @interface SentrySwizzleWrapper : NSObject -@property (class, readonly, nonatomic) SentrySwizzleWrapper *sharedInstance; - #if SENTRY_HAS_UIKIT - (void)swizzleSendAction:(SentrySwizzleSendActionCallback)callback forKey:(NSString *)key; diff --git a/Sources/Sentry/include/SentryUIEventTracker.h b/Sources/Sentry/include/SentryUIEventTracker.h index 23db6f171fd..67fb53a3358 100644 --- a/Sources/Sentry/include/SentryUIEventTracker.h +++ b/Sources/Sentry/include/SentryUIEventTracker.h @@ -4,14 +4,13 @@ NS_ASSUME_NONNULL_BEGIN -@class SentrySwizzleWrapper, SentryDispatchQueueWrapper; +@class SentryDispatchQueueWrapper; @interface SentryUIEventTracker : NSObject SENTRY_NO_INIT -- (instancetype)initWithSwizzleWrapper:(SentrySwizzleWrapper *)swizzleWrapper - dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper - idleTimeout:(NSTimeInterval)idleTimeout; +- (instancetype)initWithDispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper + idleTimeout:(NSTimeInterval)idleTimeout; - (void)start; - (void)stop; diff --git a/Tests/SentryTests/Helper/SentrySwizzleWrapperTests.swift b/Tests/SentryTests/Helper/SentrySwizzleWrapperTests.swift index 551f9681977..9959863a906 100644 --- a/Tests/SentryTests/Helper/SentrySwizzleWrapperTests.swift +++ b/Tests/SentryTests/Helper/SentrySwizzleWrapperTests.swift @@ -34,7 +34,7 @@ class SentrySwizzleWrapperTests: XCTestCase { super.setUp() fixture = Fixture() - sut = SentrySwizzleWrapper.sharedInstance + sut = SentryDependencyContainer.sharedInstance().swizzleWrapper } override func tearDown() { diff --git a/Tests/SentryTests/Integrations/Breadcrumbs/SentryAutoBreadcrumbTrackingIntegrationTests.swift b/Tests/SentryTests/Integrations/Breadcrumbs/SentryAutoBreadcrumbTrackingIntegrationTests.swift index 2a7f65ae673..bc12a71d3fb 100644 --- a/Tests/SentryTests/Integrations/Breadcrumbs/SentryAutoBreadcrumbTrackingIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/Breadcrumbs/SentryAutoBreadcrumbTrackingIntegrationTests.swift @@ -5,7 +5,7 @@ import XCTest class SentryAutoBreadcrumbTrackingIntegrationTests: XCTestCase { private class Fixture { - let tracker = SentryTestBreadcrumbTracker(swizzleWrapper: SentrySwizzleWrapper.sharedInstance) + let tracker = SentryTestBreadcrumbTracker() var systemEventBreadcrumbs: SentryTestSystemEventBreadcrumbs? diff --git a/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift b/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift index 655c14aba69..42cc706f902 100644 --- a/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift +++ b/Tests/SentryTests/Integrations/Breadcrumbs/SentryBreadcrumbTrackerTests.swift @@ -19,14 +19,13 @@ class SentryBreadcrumbTrackerTests: XCTestCase { #if os(iOS) || os(tvOS) || targetEnvironment(macCatalyst) func testStopRemovesSwizzleSendAction() { - let swizzleWrapper = SentrySwizzleWrapper.sharedInstance - let sut = SentryBreadcrumbTracker(swizzleWrapper: swizzleWrapper) + let sut = SentryBreadcrumbTracker() sut.start(with: delegate) sut.startSwizzle() sut.stop() - let dict = Dynamic(swizzleWrapper).swizzleSendActionCallbacks().asDictionary + let dict = Dynamic(SentryDependencyContainer.sharedInstance().swizzleWrapper).swizzleSendActionCallbacks().asDictionary XCTAssertEqual(0, dict?.count) } @@ -36,7 +35,7 @@ class SentryBreadcrumbTrackerTests: XCTestCase { let hub = TestHub(client: client, andScope: scope) SentrySDK.setCurrentHub(hub) - let sut = SentryBreadcrumbTracker(swizzleWrapper: SentrySwizzleWrapper.sharedInstance) + let sut = SentryBreadcrumbTracker() sut.start(with: delegate) sut.startSwizzle() diff --git a/Tests/SentryTests/Integrations/UIEvents/SentryUIEventTrackerTests.swift b/Tests/SentryTests/Integrations/UIEvents/SentryUIEventTrackerTests.swift index ed6361c0d53..b4896adc66b 100644 --- a/Tests/SentryTests/Integrations/UIEvents/SentryUIEventTrackerTests.swift +++ b/Tests/SentryTests/Integrations/UIEvents/SentryUIEventTrackerTests.swift @@ -14,10 +14,11 @@ class SentryUIEventTrackerTests: XCTestCase { init () { dispatchQueue.blockBeforeMainBlock = { false } + SentryDependencyContainer.sharedInstance().swizzleWrapper = swizzleWrapper } func getSut() -> SentryUIEventTracker { - return SentryUIEventTracker(swizzleWrapper: swizzleWrapper, dispatchQueueWrapper: dispatchQueue, idleTimeout: 3.0) + return SentryUIEventTracker(dispatchQueueWrapper: dispatchQueue, idleTimeout: 3.0) } } diff --git a/scripts/no-changes-in-high-risk-files.sh b/scripts/no-changes-in-high-risk-files.sh index 5a6b0982952..13db2b40446 100755 --- a/scripts/no-changes-in-high-risk-files.sh +++ b/scripts/no-changes-in-high-risk-files.sh @@ -10,7 +10,7 @@ EXPECTED="819d5ca5e3db2ac23c859b14c149b7f0754d3ae88bea1dba92c18f49a81da0e1 ./So e95e62ec7363984f20c78643bb7d992a41a740f97e1befb71525ac34caf88b37 ./Sources/Sentry/SentryNSDataSwizzling.m 9ad05dd8dd29788cba994736fdcd3bbde59a94e32612640d11f4f9c38ad6610e ./Sources/Sentry/SentrySubClassFinder.m 59db11da66e6ac0058526be0be08b57cdccd3727033e85164a631b205e972134 ./Sources/Sentry/SentryCoreDataSwizzling.m -c6fd5fb82863246c697f4913fdd03c09a18d1006d30322d375a66a0046e9c252 ./Sources/Sentry/SentrySwizzleWrapper.m +4a041cf2704ca4a8cc1df76bc955781ddd29c3e515aef49898d248d4016e0315 ./Sources/Sentry/SentrySwizzleWrapper.m b1c642450170358cab39b4cc6cd546f27c41b12eacb90c3ad93f87733d46e56c ./Sources/Sentry/include/SentrySwizzle.h f97128c823f92d1c2ec37e5e3b2914f7488a94043af6a8344e348f1a14425f47 ./Sources/Sentry/SentrySwizzle.m" From aa26ebb95d426688937dccd128db89cb278d306b Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Tue, 29 Aug 2023 13:15:28 -0400 Subject: [PATCH 08/13] ref: remove umbrella imports (#3256) --- Sentry.xcodeproj/project.pbxproj | 4 ---- .../Helper/SentryFileManager+TestProperties.h | 1 - Tests/SentryTests/Helper/SentryLog+TestInit.h | 1 - .../Helper/SentrySerializationNilTests.m | 1 - Tests/SentryTests/Helper/SentrySwizzleTests.m | 1 - .../CoreData/SentryCoreDataTracker+Test.h | 1 - Tests/SentryTests/Networking/SentryDsnTests.m | 1 - .../Protocol/SentryAttachment+Equality.h | 2 +- Tests/SentryTests/SentryClient+TestInit.h | 1 - Tests/SentryTests/SentryInstallationTests.m | 16 ---------------- Tests/SentryTests/SentryInterfacesTests.m | 9 ++++++++- .../SentryKSCrashReportConverterTests.m | 10 +++++++++- Tests/SentryTests/SentryNSDataCompressionTests.m | 1 - Tests/SentryTests/SentrySDK+Tests.h | 2 -- Tests/SentryTests/SentryScope+Equality.h | 3 +-- Tests/SentryTests/SentryScope+Equality.m | 3 ++- Tests/SentryTests/SentryScope+Properties.h | 6 +++++- Tests/SentryTests/SentryTests.m | 5 ++++- Tests/SentryTests/TestLogOutput.swift | 1 + .../TestUtils/SentryBooleanSerialization.h | 1 - .../TestUtils/SentryBooleanSerialization.m | 2 +- 21 files changed, 32 insertions(+), 40 deletions(-) delete mode 100644 Tests/SentryTests/SentryInstallationTests.m diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 0e4a6013851..220d2759bc0 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -69,7 +69,6 @@ 15360CD92432835400112302 /* SentryAutoSessionTrackingIntegration.h in Headers */ = {isa = PBXBuildFile; fileRef = 15360CD82432835400112302 /* SentryAutoSessionTrackingIntegration.h */; settings = {ATTRIBUTES = (Private, ); }; }; 15360CED2433A15500112302 /* SentryInstallation.m in Sources */ = {isa = PBXBuildFile; fileRef = 15360CEC2433A15500112302 /* SentryInstallation.m */; }; 15360CF02433A16D00112302 /* SentryInstallation.h in Headers */ = {isa = PBXBuildFile; fileRef = 15360CEF2433A16D00112302 /* SentryInstallation.h */; }; - 15360CF52433C59B00112302 /* SentryInstallationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 15360CF22433C59500112302 /* SentryInstallationTests.m */; }; 15D0AC882459EE4D006541C2 /* SentryNSURLRequestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15D0AC872459EE4D006541C2 /* SentryNSURLRequestTests.swift */; }; 15E0A8E1240C41CE00F044E3 /* SentryEnvelope.h in Headers */ = {isa = PBXBuildFile; fileRef = 15E0A8E0240C41CE00F044E3 /* SentryEnvelope.h */; settings = {ATTRIBUTES = (Private, ); }; }; 15E0A8E5240C457D00F044E3 /* SentryEnvelope.m in Sources */ = {isa = PBXBuildFile; fileRef = 15E0A8E4240C457D00F044E3 /* SentryEnvelope.m */; }; @@ -948,7 +947,6 @@ 15360CD82432835400112302 /* SentryAutoSessionTrackingIntegration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryAutoSessionTrackingIntegration.h; path = include/SentryAutoSessionTrackingIntegration.h; sourceTree = ""; }; 15360CEC2433A15500112302 /* SentryInstallation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryInstallation.m; sourceTree = ""; }; 15360CEF2433A16D00112302 /* SentryInstallation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryInstallation.h; path = include/SentryInstallation.h; sourceTree = ""; }; - 15360CF22433C59500112302 /* SentryInstallationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryInstallationTests.m; sourceTree = ""; }; 15D0AC872459EE4D006541C2 /* SentryNSURLRequestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSURLRequestTests.swift; sourceTree = ""; }; 15E0A8E0240C41CE00F044E3 /* SentryEnvelope.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryEnvelope.h; path = include/HybridPublic/SentryEnvelope.h; sourceTree = ""; }; 15E0A8E4240C457D00F044E3 /* SentryEnvelope.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryEnvelope.m; sourceTree = ""; }; @@ -2225,7 +2223,6 @@ 7B569E052590F04700B653FC /* SentryScope+Properties.h */, 7B9421C4260CA393001F9349 /* SentrySDK+Tests.h */, 639889D21EDF06C100EA7442 /* SentryTests-Bridging-Header.h */, - 15360CF22433C59500112302 /* SentryInstallationTests.m */, 63B819131EC352A7002FDF4C /* SentryInterfacesTests.m */, 630C01931EC3402C00C52CEF /* SentryKSCrashReportConverterTests.m */, 630436151EC0AD3100C4D3FA /* SentryNSDataCompressionTests.m */, @@ -4352,7 +4349,6 @@ 7BE912B12721C76000E49E62 /* SentryPerformanceTrackingIntegrationTests.swift in Sources */, 7BA61CCC247D14E600C130A8 /* SentryThreadInspectorTests.swift in Sources */, 623C45B02A651D8200D9E88B /* SentryCoreDataTracker+Test.m in Sources */, - 15360CF52433C59B00112302 /* SentryInstallationTests.m in Sources */, 8E0551E026A7A63C00400526 /* TestProtocolClient.swift in Sources */, 7BD86ECD264A78A6005439DB /* SentryAppStartTrackerTests.swift in Sources */, 7BB6550D253EEB3900887E87 /* SentryUserFeedbackTests.swift in Sources */, diff --git a/Tests/SentryTests/Helper/SentryFileManager+TestProperties.h b/Tests/SentryTests/Helper/SentryFileManager+TestProperties.h index 437eda65d2d..e85d818f134 100644 --- a/Tests/SentryTests/Helper/SentryFileManager+TestProperties.h +++ b/Tests/SentryTests/Helper/SentryFileManager+TestProperties.h @@ -1,5 +1,4 @@ #import "SentryFileManager.h" -#import NS_ASSUME_NONNULL_BEGIN diff --git a/Tests/SentryTests/Helper/SentryLog+TestInit.h b/Tests/SentryTests/Helper/SentryLog+TestInit.h index 38a89f25007..ea6e3c9a6de 100644 --- a/Tests/SentryTests/Helper/SentryLog+TestInit.h +++ b/Tests/SentryTests/Helper/SentryLog+TestInit.h @@ -1,5 +1,4 @@ #import "SentryLog.h" -#import NS_ASSUME_NONNULL_BEGIN diff --git a/Tests/SentryTests/Helper/SentrySerializationNilTests.m b/Tests/SentryTests/Helper/SentrySerializationNilTests.m index b2f6854f47b..ea00d4257db 100644 --- a/Tests/SentryTests/Helper/SentrySerializationNilTests.m +++ b/Tests/SentryTests/Helper/SentrySerializationNilTests.m @@ -1,5 +1,4 @@ #import "SentrySerialization.h" -#import #import @interface SentrySerializationNilTests : XCTestCase diff --git a/Tests/SentryTests/Helper/SentrySwizzleTests.m b/Tests/SentryTests/Helper/SentrySwizzleTests.m index 3af6ab1edb3..b489027cfe6 100644 --- a/Tests/SentryTests/Helper/SentrySwizzleTests.m +++ b/Tests/SentryTests/Helper/SentrySwizzleTests.m @@ -1,5 +1,4 @@ #import "SentrySwizzle.h" -#import #import #pragma mark - HELPER CLASSES - diff --git a/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTracker+Test.h b/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTracker+Test.h index c3615bb1569..2bfcc8a634d 100644 --- a/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTracker+Test.h +++ b/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTracker+Test.h @@ -1,6 +1,5 @@ #import "SentryCoreDataTracker.h" #import -#import NS_ASSUME_NONNULL_BEGIN diff --git a/Tests/SentryTests/Networking/SentryDsnTests.m b/Tests/SentryTests/Networking/SentryDsnTests.m index 8959f6064fd..f7172f01e60 100644 --- a/Tests/SentryTests/Networking/SentryDsnTests.m +++ b/Tests/SentryTests/Networking/SentryDsnTests.m @@ -3,7 +3,6 @@ #import "SentryMeta.h" #import "SentryNSURLRequest.h" #import "SentryOptions+HybridSDKs.h" -#import #import @interface SentryDsnTests : XCTestCase diff --git a/Tests/SentryTests/Protocol/SentryAttachment+Equality.h b/Tests/SentryTests/Protocol/SentryAttachment+Equality.h index 614cbc1692f..73f97be96e7 100644 --- a/Tests/SentryTests/Protocol/SentryAttachment+Equality.h +++ b/Tests/SentryTests/Protocol/SentryAttachment+Equality.h @@ -1,4 +1,4 @@ -#import +#import "SentryAttachment.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Tests/SentryTests/SentryClient+TestInit.h b/Tests/SentryTests/SentryClient+TestInit.h index 27e1213ab18..8cd8aebe153 100644 --- a/Tests/SentryTests/SentryClient+TestInit.h +++ b/Tests/SentryTests/SentryClient+TestInit.h @@ -1,7 +1,6 @@ #import "SentryExtraContextProvider.h" #import "SentryRandom.h" #import "SentryTransport.h" -#import @class SentryCrashWrapper, SentryThreadInspector, SentryTransportAdapter, SentryUIDeviceWrapper; diff --git a/Tests/SentryTests/SentryInstallationTests.m b/Tests/SentryTests/SentryInstallationTests.m deleted file mode 100644 index ecae42be2eb..00000000000 --- a/Tests/SentryTests/SentryInstallationTests.m +++ /dev/null @@ -1,16 +0,0 @@ -#import "SentryInstallation.h" -#import -#import -#import - -@interface SentryInstallationTests : XCTestCase - -@end - -@implementation SentryInstallationTests - -- (void)testSentryInstallation -{ -} - -@end diff --git a/Tests/SentryTests/SentryInterfacesTests.m b/Tests/SentryTests/SentryInterfacesTests.m index e33b7ba2f60..5d01ae94745 100644 --- a/Tests/SentryTests/SentryInterfacesTests.m +++ b/Tests/SentryTests/SentryInterfacesTests.m @@ -1,10 +1,17 @@ -#import #import #import "NSDate+SentryExtras.h" +#import "SentryBreadcrumb.h" +#import "SentryEvent.h" +#import "SentryException.h" #import "SentryFileManager.h" +#import "SentryFrame.h" #import "SentryId.h" +#import "SentryMechanism.h" #import "SentryMeta.h" +#import "SentryStackTrace.h" +#import "SentryThread.h" +#import "SentryUser.h" @interface SentryInterfacesTests : XCTestCase diff --git a/Tests/SentryTests/SentryKSCrashReportConverterTests.m b/Tests/SentryTests/SentryKSCrashReportConverterTests.m index 90aff4d3a43..52119979406 100644 --- a/Tests/SentryTests/SentryKSCrashReportConverterTests.m +++ b/Tests/SentryTests/SentryKSCrashReportConverterTests.m @@ -1,8 +1,16 @@ #import "NSDate+SentryExtras.h" +#import "SentryBreadcrumb.h" #import "SentryCrashReportConverter.h" +#import "SentryDebugMeta.h" +#import "SentryEvent.h" +#import "SentryException.h" +#import "SentryFrame.h" #import "SentryInAppLogic.h" +#import "SentryMechanism.h" #import "SentryMechanismMeta.h" -#import +#import "SentryStacktrace.h" +#import "SentryThread.h" +#import "SentryUser.h" #import @interface SentryCrashReportConverterTests : XCTestCase diff --git a/Tests/SentryTests/SentryNSDataCompressionTests.m b/Tests/SentryTests/SentryNSDataCompressionTests.m index 13ea93759c6..9261e663d07 100644 --- a/Tests/SentryTests/SentryNSDataCompressionTests.m +++ b/Tests/SentryTests/SentryNSDataCompressionTests.m @@ -1,5 +1,4 @@ #import "NSData+SentryCompression.h" -#import #import @interface SentryNSDataCompressionTests : XCTestCase diff --git a/Tests/SentryTests/SentrySDK+Tests.h b/Tests/SentryTests/SentrySDK+Tests.h index af003260e51..159ab4e7841 100644 --- a/Tests/SentryTests/SentrySDK+Tests.h +++ b/Tests/SentryTests/SentrySDK+Tests.h @@ -1,5 +1,3 @@ -#import - NS_ASSUME_NONNULL_BEGIN @interface diff --git a/Tests/SentryTests/SentryScope+Equality.h b/Tests/SentryTests/SentryScope+Equality.h index fbd1a7f5bf5..bfa049a4351 100644 --- a/Tests/SentryTests/SentryScope+Equality.h +++ b/Tests/SentryTests/SentryScope+Equality.h @@ -1,5 +1,4 @@ -#import "SentryScope+Properties.h" -#import +#import "SentryScope.h" NS_ASSUME_NONNULL_BEGIN diff --git a/Tests/SentryTests/SentryScope+Equality.m b/Tests/SentryTests/SentryScope+Equality.m index 8aa77b0503c..b04adffccd3 100644 --- a/Tests/SentryTests/SentryScope+Equality.m +++ b/Tests/SentryTests/SentryScope+Equality.m @@ -1,5 +1,6 @@ - #import "SentryScope+Equality.h" +#import "SentryScope+Properties.h" +#import "SentryUser.h" @implementation SentryScope (Equality) diff --git a/Tests/SentryTests/SentryScope+Properties.h b/Tests/SentryTests/SentryScope+Properties.h index 995b7aeaea2..20b553ace17 100644 --- a/Tests/SentryTests/SentryScope+Properties.h +++ b/Tests/SentryTests/SentryScope+Properties.h @@ -1,4 +1,8 @@ -#import +#import "SentryScope.h" + +@class SentryUser; +@class SentryBreadcrumb; +@class SentryAttachment; NS_ASSUME_NONNULL_BEGIN diff --git a/Tests/SentryTests/SentryTests.m b/Tests/SentryTests/SentryTests.m index 280fedd8228..eb3e0946481 100644 --- a/Tests/SentryTests/SentryTests.m +++ b/Tests/SentryTests/SentryTests.m @@ -1,12 +1,15 @@ #import "NSDate+SentryExtras.h" +#import "SentryBreadcrumb.h" #import "SentryBreadcrumbTracker.h" +#import "SentryClient.h" #import "SentryDataCategory.h" +#import "SentryEvent.h" +#import "SentryHub.h" #import "SentryLevelMapper.h" #import "SentryMessage.h" #import "SentryMeta.h" #import "SentryOptions+HybridSDKs.h" #import "SentrySDK+Private.h" -#import #import @interface diff --git a/Tests/SentryTests/TestLogOutput.swift b/Tests/SentryTests/TestLogOutput.swift index 14e17f578a3..76e02125569 100644 --- a/Tests/SentryTests/TestLogOutput.swift +++ b/Tests/SentryTests/TestLogOutput.swift @@ -1,4 +1,5 @@ import Foundation +import XCTest class TestLogOutput: SentryLogOutput { diff --git a/Tests/SentryTests/TestUtils/SentryBooleanSerialization.h b/Tests/SentryTests/TestUtils/SentryBooleanSerialization.h index fbe5129a7a7..7308c81c746 100644 --- a/Tests/SentryTests/TestUtils/SentryBooleanSerialization.h +++ b/Tests/SentryTests/TestUtils/SentryBooleanSerialization.h @@ -1,6 +1,5 @@ #import "SentrySerializable.h" #import -#import NS_ASSUME_NONNULL_BEGIN diff --git a/Tests/SentryTests/TestUtils/SentryBooleanSerialization.m b/Tests/SentryTests/TestUtils/SentryBooleanSerialization.m index fa4657f59f7..f15a222d3a2 100644 --- a/Tests/SentryTests/TestUtils/SentryBooleanSerialization.m +++ b/Tests/SentryTests/TestUtils/SentryBooleanSerialization.m @@ -1,5 +1,5 @@ #import "SentryBooleanSerialization.h" -#import +#import NS_ASSUME_NONNULL_BEGIN From 91d2d63917914600b4bff41c990896e933fa10ee Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Tue, 29 Aug 2023 14:42:27 -0400 Subject: [PATCH 09/13] ref: centralize SentryUIDeviceWrapper access (#3243) --- Sources/Sentry/SentryDependencyContainer.m | 25 ++++++++++++++++--- Sources/Sentry/SentryExtraContextProvider.h | 2 -- Sources/Sentry/SentryExtraContextProvider.m | 19 ++++++-------- Sources/Sentry/SentryUIDeviceWrapper.m | 12 ++------- .../HybridPublic/SentryDependencyContainer.h | 12 +++++++-- .../Sentry/include/SentryUIDeviceWrapper.h | 3 +-- .../SentryExtraContextProviderTests.swift | 10 +++++--- Tests/SentryTests/SentryClient+TestInit.h | 5 +++- Tests/SentryTests/SentryClientTests.swift | 12 ++++++--- .../SentryUIDeviceWrapperTests.swift | 3 ++- .../TestSentryUIDeviceWrapper.swift | 4 +-- 11 files changed, 66 insertions(+), 41 deletions(-) diff --git a/Sources/Sentry/SentryDependencyContainer.m b/Sources/Sentry/SentryDependencyContainer.m index 9299104dcc2..8d639353b17 100644 --- a/Sources/Sentry/SentryDependencyContainer.m +++ b/Sources/Sentry/SentryDependencyContainer.m @@ -8,7 +8,7 @@ #import "SentryNSTimerFactory.h" #import "SentryRandom.h" #import "SentrySystemWrapper.h" -#import "SentryUIApplication.h" +#import "SentryUIDeviceWrapper.h" #import #import #import @@ -17,17 +17,22 @@ #import #import #import -#import #import #import #import #import -#import #if SENTRY_HAS_UIKIT # import "SentryFramesTracker.h" +# import "SentryUIApplication.h" +# import +# import #endif // SENTRY_HAS_UIKIT +#if TARGET_OS_IOS +# import "SentryUIDeviceWrapper.h" +#endif // TARGET_OS_IOS + @implementation SentryDependencyContainer static SentryDependencyContainer *instance; @@ -152,6 +157,20 @@ - (SentryBinaryImageCache *)binaryImageCache return _binaryImageCache; } +#if TARGET_OS_IOS +- (SentryUIDeviceWrapper *)uiDeviceWrapper +{ + if (_uiDeviceWrapper == nil) { + @synchronized(sentryDependencyContainerLock) { + if (_uiDeviceWrapper == nil) { + _uiDeviceWrapper = [[SentryUIDeviceWrapper alloc] init]; + } + } + } + return _uiDeviceWrapper; +} +#endif // TARGET_OS_IOS + #if SENTRY_HAS_UIKIT - (SentryScreenshot *)screenshot { diff --git a/Sources/Sentry/SentryExtraContextProvider.h b/Sources/Sentry/SentryExtraContextProvider.h index fbf1d3f1b3e..cd0df847989 100644 --- a/Sources/Sentry/SentryExtraContextProvider.h +++ b/Sources/Sentry/SentryExtraContextProvider.h @@ -1,6 +1,5 @@ #import "SentryCrashWrapper.h" #import "SentryNSProcessInfoWrapper.h" -#import "SentryUIDeviceWrapper.h" #import NS_ASSUME_NONNULL_BEGIN @@ -13,7 +12,6 @@ NS_ASSUME_NONNULL_BEGIN + (instancetype)sharedInstance; - (instancetype)initWithCrashWrapper:(SentryCrashWrapper *)crashWrapper - deviceWrapper:(SentryUIDeviceWrapper *)deviceWrapper processInfoWrapper:(SentryNSProcessInfoWrapper *)processInfoWrapper; - (NSDictionary *)getExtraContext; diff --git a/Sources/Sentry/SentryExtraContextProvider.m b/Sources/Sentry/SentryExtraContextProvider.m index 1ed102cf6dd..ea04e717e79 100644 --- a/Sources/Sentry/SentryExtraContextProvider.m +++ b/Sources/Sentry/SentryExtraContextProvider.m @@ -9,7 +9,6 @@ SentryExtraContextProvider () @property (nonatomic, strong) SentryCrashWrapper *crashWrapper; -@property (nonatomic, strong) SentryUIDeviceWrapper *deviceWrapper; @property (nonatomic, strong) SentryNSProcessInfoWrapper *processInfoWrapper; @end @@ -28,17 +27,13 @@ - (instancetype)init { return [self initWithCrashWrapper:[SentryCrashWrapper sharedInstance] - deviceWrapper:[[SentryUIDeviceWrapper alloc] init] processInfoWrapper:[SentryDependencyContainer.sharedInstance processInfoWrapper]]; } -- (instancetype)initWithCrashWrapper:(id)crashWrapper - deviceWrapper:(id)deviceWrapper - processInfoWrapper:(id)processInfoWrapper +- (instancetype)initWithCrashWrapper:(id)crashWrapper processInfoWrapper:(id)processInfoWrapper { if (self = [super init]) { self.crashWrapper = crashWrapper; - self.deviceWrapper = deviceWrapper; self.processInfoWrapper = processInfoWrapper; } return self; @@ -58,16 +53,16 @@ - (NSDictionary *)getExtraDeviceContext extraDeviceContext[@"processor_count"] = @([self.processInfoWrapper processorCount]); #if TARGET_OS_IOS - if (self.deviceWrapper.orientation != UIDeviceOrientationUnknown) { + SentryUIDeviceWrapper *deviceWrapper = SentryDependencyContainer.sharedInstance.uiDeviceWrapper; + if (deviceWrapper.orientation != UIDeviceOrientationUnknown) { extraDeviceContext[@"orientation"] - = UIDeviceOrientationIsPortrait(self.deviceWrapper.orientation) ? @"portrait" - : @"landscape"; + = UIDeviceOrientationIsPortrait(deviceWrapper.orientation) ? @"portrait" : @"landscape"; } - if (self.deviceWrapper.isBatteryMonitoringEnabled) { + if (deviceWrapper.isBatteryMonitoringEnabled) { extraDeviceContext[@"charging"] - = self.deviceWrapper.batteryState == UIDeviceBatteryStateCharging ? @(YES) : @(NO); - extraDeviceContext[@"battery_level"] = @((int)(self.deviceWrapper.batteryLevel * 100)); + = deviceWrapper.batteryState == UIDeviceBatteryStateCharging ? @(YES) : @(NO); + extraDeviceContext[@"battery_level"] = @((int)(deviceWrapper.batteryLevel * 100)); } #endif return extraDeviceContext; diff --git a/Sources/Sentry/SentryUIDeviceWrapper.m b/Sources/Sentry/SentryUIDeviceWrapper.m index cb394500aaf..e77c9303b54 100644 --- a/Sources/Sentry/SentryUIDeviceWrapper.m +++ b/Sources/Sentry/SentryUIDeviceWrapper.m @@ -8,7 +8,6 @@ SentryUIDeviceWrapper () @property (nonatomic) BOOL cleanupDeviceOrientationNotifications; @property (nonatomic) BOOL cleanupBatteryMonitoring; -@property (strong, nonatomic) SentryDispatchQueueWrapper *dispatchQueueWrapper; @end @implementation SentryUIDeviceWrapper @@ -16,16 +15,9 @@ @implementation SentryUIDeviceWrapper #if TARGET_OS_IOS - (instancetype)init -{ - return [self initWithDispatchQueueWrapper:[SentryDependencyContainer sharedInstance] - .dispatchQueueWrapper]; -} - -- (instancetype)initWithDispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper { if (self = [super init]) { - self.dispatchQueueWrapper = dispatchQueueWrapper; - [self.dispatchQueueWrapper dispatchSyncOnMainQueue:^{ + [SentryDependencyContainer.sharedInstance.dispatchQueueWrapper dispatchSyncOnMainQueue:^{ // Needed to read the device orientation on demand if (!UIDevice.currentDevice.isGeneratingDeviceOrientationNotifications) { self.cleanupDeviceOrientationNotifications = YES; @@ -44,7 +36,7 @@ - (instancetype)initWithDispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispa - (void)stop { - [self.dispatchQueueWrapper dispatchSyncOnMainQueue:^{ + [SentryDependencyContainer.sharedInstance.dispatchQueueWrapper dispatchSyncOnMainQueue:^{ if (self.cleanupDeviceOrientationNotifications) { [UIDevice.currentDevice endGeneratingDeviceOrientationNotifications]; } diff --git a/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h b/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h index 07da41cabef..3506801d310 100644 --- a/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h +++ b/Sources/Sentry/include/HybridPublic/SentryDependencyContainer.h @@ -26,7 +26,11 @@ @class SentryScreenshot; @class SentryUIApplication; @class SentryViewHierarchy; -#endif +#endif // SENTRY_HAS_UIKIT + +#if TARGET_OS_IOS +@class SentryUIDeviceWrapper; +#endif // TARGET_OS_IOS NS_ASSUME_NONNULL_BEGIN @@ -62,7 +66,11 @@ SENTRY_NO_INIT @property (nonatomic, strong) SentryScreenshot *screenshot; @property (nonatomic, strong) SentryViewHierarchy *viewHierarchy; @property (nonatomic, strong) SentryUIApplication *application; -#endif +#endif // SENTRY_HAS_UIKIT + +#if TARGET_OS_IOS +@property (nonatomic, strong) SentryUIDeviceWrapper *uiDeviceWrapper; +#endif // TARGET_OS_IOS - (SentryANRTracker *)getANRTracker:(NSTimeInterval)timeout; diff --git a/Sources/Sentry/include/SentryUIDeviceWrapper.h b/Sources/Sentry/include/SentryUIDeviceWrapper.h index 211f4ef0b12..3b1a4e82d78 100644 --- a/Sources/Sentry/include/SentryUIDeviceWrapper.h +++ b/Sources/Sentry/include/SentryUIDeviceWrapper.h @@ -12,13 +12,12 @@ NS_ASSUME_NONNULL_BEGIN #if TARGET_OS_IOS - (instancetype)init; -- (instancetype)initWithDispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper; - (void)stop; - (UIDeviceOrientation)orientation; - (BOOL)isBatteryMonitoringEnabled; - (UIDeviceBatteryState)batteryState; - (float)batteryLevel; -#endif +#endif // TARGET_OS_IOS @end diff --git a/Tests/SentryTests/Helper/SentryExtraContextProviderTests.swift b/Tests/SentryTests/Helper/SentryExtraContextProviderTests.swift index 8c8267bd3a6..502d3c3d51f 100644 --- a/Tests/SentryTests/Helper/SentryExtraContextProviderTests.swift +++ b/Tests/SentryTests/Helper/SentryExtraContextProviderTests.swift @@ -5,13 +5,17 @@ final class SentryExtraContextProviderTests: XCTestCase { private class Fixture { let crashWrapper = TestSentryCrashWrapper.sharedInstance() +#if os(iOS) || targetEnvironment(macCatalyst) let deviceWrapper = TestSentryUIDeviceWrapper() +#endif // os(iOS) || targetEnvironment(macCatalyst) let processWrapper = TestSentryNSProcessInfoWrapper() func getSut() -> SentryExtraContextProvider { + #if os(iOS) || targetEnvironment(macCatalyst) + SentryDependencyContainer.sharedInstance().uiDeviceWrapper = deviceWrapper + #endif // os(iOS) || targetEnvironment(macCatalyst) return SentryExtraContextProvider( crashWrapper: crashWrapper, - deviceWrapper: deviceWrapper, processInfoWrapper: processWrapper) } } @@ -39,7 +43,7 @@ final class SentryExtraContextProviderTests: XCTestCase { } func testExtraDeviceInfo() { -#if os(iOS) +#if os(iOS) || targetEnvironment(macCatalyst) let sut = fixture.getSut() fixture.deviceWrapper.internalOrientation = .landscapeLeft fixture.deviceWrapper.internalBatteryState = .full @@ -51,7 +55,7 @@ final class SentryExtraContextProviderTests: XCTestCase { XCTAssertEqual(device?["orientation"] as? String, "landscape") XCTAssertEqual(device?["charging"] as? Bool, false) XCTAssertEqual(device?["battery_level"] as? UInt, 44) -#endif +#endif // os(iOS) || targetEnvironment(macCatalyst) } func testExtraProcessInfo() { diff --git a/Tests/SentryTests/SentryClient+TestInit.h b/Tests/SentryTests/SentryClient+TestInit.h index 8cd8aebe153..b2b1dcff963 100644 --- a/Tests/SentryTests/SentryClient+TestInit.h +++ b/Tests/SentryTests/SentryClient+TestInit.h @@ -2,7 +2,10 @@ #import "SentryRandom.h" #import "SentryTransport.h" -@class SentryCrashWrapper, SentryThreadInspector, SentryTransportAdapter, SentryUIDeviceWrapper; +@class SentryCrashWrapper; +@class SentryDispatchQueueWrapper; +@class SentryThreadInspector; +@class SentryTransportAdapter; NS_ASSUME_NONNULL_BEGIN diff --git a/Tests/SentryTests/SentryClientTests.swift b/Tests/SentryTests/SentryClientTests.swift index 7d834609d2f..44605b96c96 100644 --- a/Tests/SentryTests/SentryClientTests.swift +++ b/Tests/SentryTests/SentryClientTests.swift @@ -29,7 +29,9 @@ class SentryClientTest: XCTestCase { let trace = SentryTracer(transactionContext: TransactionContext(name: "SomeTransaction", operation: "SomeOperation"), hub: nil) let transaction: Transaction let crashWrapper = TestSentryCrashWrapper.sharedInstance() + #if os(iOS) || targetEnvironment(macCatalyst) let deviceWrapper = TestSentryUIDeviceWrapper() + #endif // os(iOS) || targetEnvironment(macCatalyst) let processWrapper = TestSentryNSProcessInfoWrapper() let extraContentProvider: SentryExtraContextProvider let locale = Locale(identifier: "en_US") @@ -62,8 +64,12 @@ class SentryClientTest: XCTestCase { crashWrapper.internalFreeMemorySize = 123_456 crashWrapper.internalAppMemorySize = 234_567 crashWrapper.internalFreeStorageSize = 345_678 + + #if os(iOS) || targetEnvironment(macCatalyst) + SentryDependencyContainer.sharedInstance().uiDeviceWrapper = deviceWrapper +#endif // os(iOS) || targetEnvironment(macCatalyst) - extraContentProvider = SentryExtraContextProvider(crashWrapper: crashWrapper, deviceWrapper: deviceWrapper, processInfoWrapper: processWrapper) + extraContentProvider = SentryExtraContextProvider(crashWrapper: crashWrapper, processInfoWrapper: processWrapper) } func getSut(configureOptions: (Options) -> Void = { _ in }) -> SentryClient { @@ -708,7 +714,7 @@ class SentryClientTest: XCTestCase { } func testCaptureEvent_DeviceProperties_OtherValues() { -#if os(iOS) +#if os(iOS) || targetEnvironment(macCatalyst) fixture.deviceWrapper.internalOrientation = .landscapeLeft fixture.deviceWrapper.internalBatteryState = .full @@ -721,7 +727,7 @@ class SentryClientTest: XCTestCase { let charging = actual.context?["device"]?["charging"] as? Bool XCTAssertEqual(charging, false) } -#endif +#endif // os(iOS) || targetEnvironment(macCatalyst) } func testCaptureEvent_AddCurrentCulture() { diff --git a/Tests/SentryTests/SentryCrash/SentryUIDeviceWrapperTests.swift b/Tests/SentryTests/SentryCrash/SentryUIDeviceWrapperTests.swift index b19952f3260..24b0cc10f66 100644 --- a/Tests/SentryTests/SentryCrash/SentryUIDeviceWrapperTests.swift +++ b/Tests/SentryTests/SentryCrash/SentryUIDeviceWrapperTests.swift @@ -5,7 +5,8 @@ import XCTest class SentryUIDeviceWrapperTests: XCTestCase { func testExecutesLogicViaDispatchQueue() { let dispatchQueue = TestSentryDispatchQueueWrapper() - let sut = SentryUIDeviceWrapper(dispatchQueueWrapper: dispatchQueue) + SentryDependencyContainer.sharedInstance().dispatchQueueWrapper = dispatchQueue + let sut = SentryUIDeviceWrapper() XCTAssertEqual(dispatchQueue.blockOnMainInvocations.count, 1) sut.stop() diff --git a/Tests/SentryTests/SentryCrash/TestSentryUIDeviceWrapper.swift b/Tests/SentryTests/SentryCrash/TestSentryUIDeviceWrapper.swift index dcb9a2378d2..e10b5f8d80f 100644 --- a/Tests/SentryTests/SentryCrash/TestSentryUIDeviceWrapper.swift +++ b/Tests/SentryTests/SentryCrash/TestSentryUIDeviceWrapper.swift @@ -1,7 +1,7 @@ import Sentry +#if os(iOS) || targetEnvironment(macCatalyst) class TestSentryUIDeviceWrapper: SentryUIDeviceWrapper { -#if os(iOS) var internalOrientation = UIDeviceOrientation.portrait var internalIsBatteryMonitoringEnabled = true var internalBatteryLevel: Float = 0.6 @@ -22,5 +22,5 @@ class TestSentryUIDeviceWrapper: SentryUIDeviceWrapper { override func batteryState() -> UIDevice.BatteryState { return internalBatteryState } -#endif } +#endif // os(iOS) || targetEnvironment(macCatalyst) From 87e0836f31ad165e05576a46cc9cb6b251ebd54d Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Tue, 29 Aug 2023 15:33:26 -0400 Subject: [PATCH 10/13] feat: add more db info on span data (#3231) --- CHANGELOG.md | 2 + Sources/Sentry/SentryCoreDataTracker.m | 69 ++++---- .../CoreData/SentryCoreDataTrackerTest.swift | 160 +++++++----------- .../CoreData/TestCoreDataStack.swift | 50 +++++- 4 files changed, 146 insertions(+), 135 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1de993546ca..05ce7d88c74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ ### Features +- Report database backing store information for Core Data (#3231) + ## 8.10.0 ### Features diff --git a/Sources/Sentry/SentryCoreDataTracker.m b/Sources/Sentry/SentryCoreDataTracker.m index df75fd8c8c1..fea6e6fbd95 100644 --- a/Sources/Sentry/SentryCoreDataTracker.m +++ b/Sources/Sentry/SentryCoreDataTracker.m @@ -44,23 +44,18 @@ - (NSArray *)managedObjectContext:(NSManagedObjectContext *)context }]; if (fetchSpan) { - [SentryLog - logWithMessage:[NSString stringWithFormat: - @"SentryCoreDataTracker automatically " - @"started a new span with description: %@, operation: %@", - fetchSpan.description, SENTRY_COREDATA_FETCH_OPERATION] - andLevel:kSentryLevelDebug]; + SENTRY_LOG_DEBUG(@"SentryCoreDataTracker automatically started a new span with " + @"description: %@, operation: %@", + fetchSpan.description, fetchSpan.operation); } else { - [SentryLog - logWithMessage: - @"managedObjectContext:executeFetchRequest:error:originalImp: fetchSpan is nil." - andLevel:kSentryLevelError]; + SENTRY_LOG_ERROR( + @"managedObjectContext:executeFetchRequest:error:originalImp: fetchSpan is nil."); } NSArray *result = original(request, error); if (fetchSpan) { - [self mainThreadExtraInfo:fetchSpan]; + [self addExtraInfoToSpan:fetchSpan withContext:context]; [fetchSpan setDataValue:[NSNumber numberWithInteger:result.count] forKey:@"read_count"]; [fetchSpan @@ -78,35 +73,34 @@ - (BOOL)managedObjectContext:(NSManagedObjectContext *)context originalImp:(BOOL(NS_NOESCAPE ^)(NSError **))original { - __block id fetchSpan = nil; + __block id saveSpan = nil; if (context.hasChanges) { __block NSDictionary *operations = [self groupEntitiesOperations:context]; [SentrySDK.currentHub.scope useSpan:^(id _Nullable span) { - fetchSpan = [span startChildWithOperation:SENTRY_COREDATA_SAVE_OPERATION - description:[self descriptionForOperations:operations - inContext:context]]; - fetchSpan.origin = SentryTraceOriginAutoDBCoreData; - if (fetchSpan) { - [SentryLog - logWithMessage:[NSString - stringWithFormat:@"SentryCoreDataTracker automatically " - @"started a new span with description: %@, " - @"operation: %@", - fetchSpan.description, SENTRY_COREDATA_FETCH_OPERATION] - andLevel:kSentryLevelDebug]; - - [fetchSpan setDataValue:operations forKey:@"operations"]; - } + saveSpan = [span startChildWithOperation:SENTRY_COREDATA_SAVE_OPERATION + description:[self descriptionForOperations:operations + inContext:context]]; + saveSpan.origin = SentryTraceOriginAutoDBCoreData; }]; + + if (saveSpan) { + SENTRY_LOG_DEBUG(@"SentryCoreDataTracker automatically started a new span with " + @"description: %@, operation: %@", + saveSpan.description, saveSpan.operation); + + [saveSpan setDataValue:operations forKey:@"operations"]; + } else { + SENTRY_LOG_ERROR(@"managedObjectContext:save:originalImp: saveSpan is nil"); + } } BOOL result = original(error); - if (fetchSpan) { - [self mainThreadExtraInfo:fetchSpan]; - [fetchSpan finishWithStatus:result ? kSentrySpanStatusOk : kSentrySpanStatusInternalError]; + if (saveSpan) { + [self addExtraInfoToSpan:saveSpan withContext:context]; + [saveSpan finishWithStatus:result ? kSentrySpanStatusOk : kSentrySpanStatusInternalError]; SENTRY_LOG_DEBUG(@"SentryCoreDataTracker automatically finished span with status: %@", result ? @"ok" : @"error"); @@ -115,11 +109,24 @@ - (BOOL)managedObjectContext:(NSManagedObjectContext *)context return result; } -- (void)mainThreadExtraInfo:(SentrySpan *)span +- (void)addExtraInfoToSpan:(SentrySpan *)span withContext:(NSManagedObjectContext *)context { BOOL isMainThread = [NSThread isMainThread]; [span setDataValue:@(isMainThread) forKey:BLOCKED_MAIN_THREAD]; + NSMutableArray *systems = [NSMutableArray array]; + NSMutableArray *names = [NSMutableArray array]; + [context.persistentStoreCoordinator.persistentStores enumerateObjectsUsingBlock:^( + __kindof NSPersistentStore *_Nonnull obj, NSUInteger idx, BOOL *_Nonnull stop) { + [systems addObject:obj.type]; + if (obj.URL != nil) { + [names addObject:obj.URL.path]; + } else { + [names addObject:@"(null)"]; + } + }]; + [span setDataValue:[systems componentsJoinedByString:@";"] forKey:@"db.system"]; + [span setDataValue:[names componentsJoinedByString:@";"] forKey:@"db.name"]; if (!isMainThread) { return; diff --git a/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackerTest.swift b/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackerTest.swift index 803c813d747..3b517cc9f25 100644 --- a/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackerTest.swift +++ b/Tests/SentryTests/Integrations/Performance/CoreData/SentryCoreDataTrackerTest.swift @@ -5,7 +5,10 @@ import XCTest class SentryCoreDataTrackerTests: XCTestCase { private class Fixture { - let context = TestNSManagedObjectContext() + let coreDataStack = TestCoreDataStack() + lazy var context: TestNSManagedObjectContext = { + coreDataStack.managedObjectContext + }() let threadInspector = TestThreadInspector.instance let imageProvider = TestDebugImageProvider() @@ -51,121 +54,121 @@ class SentryCoreDataTrackerTests: XCTestCase { XCTAssertEqual(SENTRY_COREDATA_SAVE_OPERATION, "db.sql.transaction") } - func testFetchRequest() { + func testFetchRequest() throws { let fetch = NSFetchRequest(entityName: "TestEntity") - assertRequest(fetch, expectedDescription: "SELECT 'TestEntity'") + try assertRequest(fetch, expectedDescription: "SELECT 'TestEntity'") } func testFetchRequestBackgroundThread() { let expect = expectation(description: "Operation in background thread") DispatchQueue.global(qos: .default).async { let fetch = NSFetchRequest(entityName: "TestEntity") - self.assertRequest(fetch, expectedDescription: "SELECT 'TestEntity'", mainThread: false) + try? self.assertRequest(fetch, expectedDescription: "SELECT 'TestEntity'", mainThread: false) expect.fulfill() } wait(for: [expect], timeout: 1.0) } - func test_FetchRequest_WithPredicate() { + func test_FetchRequest_WithPredicate() throws { let fetch = NSFetchRequest(entityName: "TestEntity") fetch.predicate = NSPredicate(format: "field1 = %@ and field2 = %@", argumentArray: ["First Argument", 2]) - assertRequest(fetch, expectedDescription: "SELECT 'TestEntity' WHERE field1 == %@ AND field2 == %@") + try assertRequest(fetch, expectedDescription: "SELECT 'TestEntity' WHERE field1 == %@ AND field2 == %@") } - func test_FetchRequest_WithSortAscending() { + func test_FetchRequest_WithSortAscending() throws { let fetch = NSFetchRequest(entityName: "TestEntity") fetch.sortDescriptors = [NSSortDescriptor(key: "field1", ascending: true)] - assertRequest(fetch, expectedDescription: "SELECT 'TestEntity' SORT BY field1") + try assertRequest(fetch, expectedDescription: "SELECT 'TestEntity' SORT BY field1") } - func test_FetchRequest_WithSortDescending() { + func test_FetchRequest_WithSortDescending() throws { let fetch = NSFetchRequest(entityName: "TestEntity") fetch.sortDescriptors = [NSSortDescriptor(key: "field1", ascending: false)] - assertRequest(fetch, expectedDescription: "SELECT 'TestEntity' SORT BY field1 DESCENDING") + try assertRequest(fetch, expectedDescription: "SELECT 'TestEntity' SORT BY field1 DESCENDING") } - func test_FetchRequest_WithSortTwoFields() { + func test_FetchRequest_WithSortTwoFields() throws { let fetch = NSFetchRequest(entityName: "TestEntity") fetch.sortDescriptors = [NSSortDescriptor(key: "field1", ascending: false), NSSortDescriptor(key: "field2", ascending: true)] - assertRequest(fetch, expectedDescription: "SELECT 'TestEntity' SORT BY field1 DESCENDING, field2") + try assertRequest(fetch, expectedDescription: "SELECT 'TestEntity' SORT BY field1 DESCENDING, field2") } - func test_FetchRequest_WithPredicateAndSort() { + func test_FetchRequest_WithPredicateAndSort() throws { let fetch = NSFetchRequest(entityName: "TestEntity") fetch.predicate = NSPredicate(format: "field1 = %@", argumentArray: ["First Argument"]) fetch.sortDescriptors = [NSSortDescriptor(key: "field1", ascending: false)] - assertRequest(fetch, expectedDescription: "SELECT 'TestEntity' WHERE field1 == %@ SORT BY field1 DESCENDING") + try assertRequest(fetch, expectedDescription: "SELECT 'TestEntity' WHERE field1 == %@ SORT BY field1 DESCENDING") } - func test_Save_1Insert_1Entity() { + func test_Save_1Insert_1Entity() throws { fixture.context.inserted = [fixture.testEntity()] - assertSave("INSERTED 1 'TestEntity'") + try assertSave("INSERTED 1 'TestEntity'") } func testSaveBackgroundThread() { let expect = expectation(description: "Operation in background thread") DispatchQueue.global(qos: .default).async { self.fixture.context.inserted = [self.fixture.testEntity()] - self.assertSave("INSERTED 1 'TestEntity'", mainThread: false) + try? self.assertSave("INSERTED 1 'TestEntity'", mainThread: false) expect.fulfill() } wait(for: [expect], timeout: 1.0) } - func test_Save_2Insert_1Entity() { + func test_Save_2Insert_1Entity() throws { fixture.context.inserted = [fixture.testEntity(), fixture.testEntity()] - assertSave("INSERTED 2 'TestEntity'") + try assertSave("INSERTED 2 'TestEntity'") } - func test_Save_2Insert_2Entity() { + func test_Save_2Insert_2Entity() throws { fixture.context.inserted = [fixture.testEntity(), fixture.secondTestEntity()] - assertSave("INSERTED 2 items") + try assertSave("INSERTED 2 items") } - func test_Save_1Update_1Entity() { + func test_Save_1Update_1Entity() throws { fixture.context.updated = [fixture.testEntity()] - assertSave("UPDATED 1 'TestEntity'") + try assertSave("UPDATED 1 'TestEntity'") } - func test_Save_2Update_1Entity() { + func test_Save_2Update_1Entity() throws { fixture.context.updated = [fixture.testEntity(), fixture.testEntity()] - assertSave("UPDATED 2 'TestEntity'") + try assertSave("UPDATED 2 'TestEntity'") } - func test_Save_2Update_2Entity() { + func test_Save_2Update_2Entity() throws { fixture.context.updated = [fixture.testEntity(), fixture.secondTestEntity()] - assertSave("UPDATED 2 items") + try assertSave("UPDATED 2 items") } - func test_Save_1Delete_1Entity() { + func test_Save_1Delete_1Entity() throws { fixture.context.deleted = [fixture.testEntity()] - assertSave("DELETED 1 'TestEntity'") + try assertSave("DELETED 1 'TestEntity'") } - func test_Save_2Delete_1Entity() { + func test_Save_2Delete_1Entity() throws { fixture.context.deleted = [fixture.testEntity(), fixture.testEntity()] - assertSave("DELETED 2 'TestEntity'") + try assertSave("DELETED 2 'TestEntity'") } - func test_Save_2Delete_2Entity() { + func test_Save_2Delete_2Entity() throws { fixture.context.deleted = [fixture.testEntity(), fixture.secondTestEntity()] - assertSave("DELETED 2 items") + try assertSave("DELETED 2 items") } - func test_Save_Insert_Update_Delete_1Entity() { + func test_Save_Insert_Update_Delete_1Entity() throws { fixture.context.inserted = [fixture.testEntity()] fixture.context.updated = [fixture.testEntity()] fixture.context.deleted = [fixture.testEntity()] - assertSave("INSERTED 1 'TestEntity', UPDATED 1 'TestEntity', DELETED 1 'TestEntity'") + try assertSave("INSERTED 1 'TestEntity', UPDATED 1 'TestEntity', DELETED 1 'TestEntity'") } - func test_Save_Insert_Update_Delete_2Entity() { + func test_Save_Insert_Update_Delete_2Entity() throws { fixture.context.inserted = [fixture.testEntity(), fixture.secondTestEntity()] fixture.context.updated = [fixture.testEntity(), fixture.secondTestEntity()] fixture.context.deleted = [fixture.testEntity(), fixture.secondTestEntity()] - assertSave("INSERTED 2 items, UPDATED 2 items, DELETED 2 items") + try assertSave("INSERTED 2 items, UPDATED 2 items, DELETED 2 items") } func test_Operation_InData() { @@ -288,8 +291,12 @@ class SentryCoreDataTrackerTests: XCTestCase { XCTAssertEqual(transaction.children.count, 0) } - - func assertSave(_ expectedDescription: String, mainThread: Bool = true) { + +} + +private extension SentryCoreDataTrackerTests { + + func assertSave(_ expectedDescription: String, mainThread: Bool = true) throws { let sut = fixture.getSut() let transaction = startTransaction() @@ -298,26 +305,12 @@ class SentryCoreDataTrackerTests: XCTestCase { return true }) - guard let dbSpan = try? XCTUnwrap(transaction.children.first) else { - XCTFail("Span for DB operation don't exist.") - return - } - - XCTAssertEqual(dbSpan.operation, SENTRY_COREDATA_SAVE_OPERATION) - XCTAssertEqual(dbSpan.spanDescription, expectedDescription) - XCTAssertEqual(dbSpan.data["blocked_main_thread"] as? Bool ?? false, mainThread) - - if mainThread { - guard let frames = (dbSpan as? SentrySpan)?.frames else { - XCTFail("File IO Span in the main thread has no frames") - return - } - XCTAssertEqual(frames.first, TestData.mainFrame) - XCTAssertEqual(frames.last, TestData.testFrame) - } + let dbSpan = try XCTUnwrap(transaction.children.first) + + assertDataAndFrames(dbSpan: dbSpan, expectedOperation: SENTRY_COREDATA_SAVE_OPERATION, expectedDescription: expectedDescription, mainThread: mainThread) } - func assertRequest(_ fetch: NSFetchRequest, expectedDescription: String, mainThread: Bool = true) { + func assertRequest(_ fetch: NSFetchRequest, expectedDescription: String, mainThread: Bool = true) throws { let transaction = startTransaction() let sut = fixture.getSut() @@ -325,21 +318,25 @@ class SentryCoreDataTrackerTests: XCTestCase { let someEntity = fixture.testEntity() - let result = try? sut.fetchManagedObjectContext(context, request: fetch) { _, _ in + let result = try? sut.fetchManagedObjectContext(context, request: fetch) { _, _ in return [someEntity] } - guard let dbSpan = try? XCTUnwrap(transaction.children.first) else { - XCTFail("Span for DB operation don't exist.") - return - } - XCTAssertEqual(result?.count, 1) - XCTAssertEqual(dbSpan.operation, SENTRY_COREDATA_FETCH_OPERATION) + + let dbSpan = try XCTUnwrap(transaction.children.first) + XCTAssertEqual(dbSpan.data["read_count"] as? Int, 1) + + assertDataAndFrames(dbSpan: dbSpan, expectedOperation: SENTRY_COREDATA_FETCH_OPERATION, expectedDescription: expectedDescription, mainThread: mainThread) + } + + func assertDataAndFrames(dbSpan: Span, expectedOperation: String, expectedDescription: String, mainThread: Bool) { + XCTAssertEqual(dbSpan.operation, expectedOperation) XCTAssertEqual(dbSpan.origin, "auto.db.core_data") XCTAssertEqual(dbSpan.spanDescription, expectedDescription) - XCTAssertEqual(dbSpan.data["read_count"] as? Int, 1) XCTAssertEqual(dbSpan.data["blocked_main_thread"] as? Bool ?? false, mainThread) + XCTAssertEqual(try XCTUnwrap(dbSpan.data["db.system"] as? String), "SQLite") + XCTAssert(try XCTUnwrap(dbSpan.data["db.name"] as? NSString).contains(TestCoreDataStack.databaseFilename)) if mainThread { guard let frames = (dbSpan as? SentrySpan)?.frames else { @@ -358,36 +355,3 @@ class SentryCoreDataTrackerTests: XCTestCase { } } - -class TestNSManagedObjectContext: NSManagedObjectContext { - - var inserted: Set? - var updated: Set? - var deleted: Set? - - override var insertedObjects: Set { - inserted ?? [] - } - - override var updatedObjects: Set { - updated ?? [] - } - - override var deletedObjects: Set { - deleted ?? [] - } - - init() { - super.init(concurrencyType: .mainQueueConcurrencyType) - } - - required init?(coder: NSCoder) { - super.init(coder: coder) - } - - override var hasChanges: Bool { - return ((inserted?.count ?? 0) > 0) || - ((deleted?.count ?? 0) > 0) || - ((updated?.count ?? 0) > 0) - } -} diff --git a/Tests/SentryTests/Integrations/Performance/CoreData/TestCoreDataStack.swift b/Tests/SentryTests/Integrations/Performance/CoreData/TestCoreDataStack.swift index b01e8ec9b8e..ed62e2862a5 100644 --- a/Tests/SentryTests/Integrations/Performance/CoreData/TestCoreDataStack.swift +++ b/Tests/SentryTests/Integrations/Performance/CoreData/TestCoreDataStack.swift @@ -56,9 +56,10 @@ class TestCoreDataStack { return model }() - + + static let databaseFilename = "SingleViewCoreData.sqlite" + lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = { - guard let tempDir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else { return nil } if !FileManager.default.fileExists(atPath: tempDir.path) { @@ -66,22 +67,22 @@ class TestCoreDataStack { } let coordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel) - let url = tempDir.appendingPathComponent("SingleViewCoreData.sqlite") + let url = tempDir.appendingPathComponent(TestCoreDataStack.databaseFilename) let _ = try? coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil) return coordinator }() - lazy var managedObjectContext: NSManagedObjectContext = { - var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) + lazy var managedObjectContext: TestNSManagedObjectContext = { + var managedObjectContext = TestNSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType) managedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator return managedObjectContext }() func reset() { guard let tempDir = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else { return } - let url = tempDir.appendingPathComponent("SingleViewCoreData.sqlite") + let url = tempDir.appendingPathComponent(TestCoreDataStack.databaseFilename) try? FileManager.default.removeItem(at: url) } @@ -99,3 +100,40 @@ class TestCoreDataStack { } } } + +class TestNSManagedObjectContext: NSManagedObjectContext { + + var inserted: Set? + var updated: Set? + var deleted: Set? + + override var insertedObjects: Set { + inserted ?? [] + } + + override var updatedObjects: Set { + updated ?? [] + } + + override var deletedObjects: Set { + deleted ?? [] + } + + init() { + super.init(concurrencyType: .mainQueueConcurrencyType) + } + + override init(concurrencyType ct: NSManagedObjectContextConcurrencyType) { + super.init(concurrencyType: ct) + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + } + + override var hasChanges: Bool { + return ((inserted?.count ?? 0) > 0) || + ((deleted?.count ?? 0) > 0) || + ((updated?.count ?? 0) > 0) || super.hasChanges + } +} From 881764d0171a34a6e3a6f1e9fd5643794e01b537 Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Wed, 30 Aug 2023 08:26:06 -0400 Subject: [PATCH 11/13] ci: install/cache bundle for other jobs needing it (#3260) --- .github/workflows/benchmarking.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/benchmarking.yml b/.github/workflows/benchmarking.yml index 6c2a0a71acf..d95e502565f 100644 --- a/.github/workflows/benchmarking.yml +++ b/.github/workflows/benchmarking.yml @@ -104,6 +104,9 @@ jobs: - name: Git checkout uses: actions/checkout@v3 - run: ./scripts/ci-select-xcode.sh + - uses: ruby/setup-ruby@v1 + with: + bundler-cache: true - uses: actions/cache@v3 id: app-plain-cache with: From df2986b1b42cc83f32d8f9acb0139bf2f5f6c09f Mon Sep 17 00:00:00 2001 From: Andrew McKnight Date: Wed, 30 Aug 2023 08:26:20 -0400 Subject: [PATCH 12/13] fix changelog (#3261) --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05ce7d88c74..019c1320e5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,9 @@ ## Unreleased -- Distributed tracing without performance (#3196) - ### Features +- Distributed tracing without performance (#3196) - Report database backing store information for Core Data (#3231) ## 8.10.0 From 4b1a58e564042467c35c85839ac92aaa7a1c1c74 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Thu, 31 Aug 2023 08:37:37 +0200 Subject: [PATCH 13/13] feat: Add data use in privacy manifests (#3259) * feat: Add data use in privacy manifests * Update CHANGELOG.md --- CHANGELOG.md | 1 + Sources/Resources/PrivacyInfo.xcprivacy | 63 +++++++++++++++++++------ 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 019c1320e5f..0ab5d3cf880 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Distributed tracing without performance (#3196) - Report database backing store information for Core Data (#3231) +- Add "data use" in privacy manifests (#3259) ## 8.10.0 diff --git a/Sources/Resources/PrivacyInfo.xcprivacy b/Sources/Resources/PrivacyInfo.xcprivacy index 2433f73fdba..c1a5eca2b7e 100644 --- a/Sources/Resources/PrivacyInfo.xcprivacy +++ b/Sources/Resources/PrivacyInfo.xcprivacy @@ -2,24 +2,57 @@ - NSPrivacyAccessedAPITypes - - + NSPrivacyCollectedDataTypes + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeCrashData + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypePerformanceData + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + NSPrivacyCollectedDataType + NSPrivacyCollectedDataTypeOtherDiagnosticData + NSPrivacyCollectedDataTypeLinked + + NSPrivacyCollectedDataTypeTracking + + NSPrivacyCollectedDataTypePurposes + NSPrivacyCollectedDataTypePurposeAppFunctionality + + + NSPrivacyAccessedAPITypes + + NSPrivacyAccessedAPIType NSPrivacyAccessedAPICategoryUserDefaults - NSPrivacyAccessedAPITypeReasons - - CA92.1 - - - + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + NSPrivacyAccessedAPIType NSPrivacyAccessedAPICategorySystemBootTime - NSPrivacyAccessedAPITypeReasons - - 35F9.1 - - - + NSPrivacyAccessedAPITypeReasons + + 35F9.1 + + +