From bb67cef86bf7b9b87accf9a942770ca258bc2452 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Fri, 20 Sep 2024 13:13:01 +0300 Subject: [PATCH 01/10] Adds breadcrumb.origin field --- Sources/Sentry/Public/SentryBreadcrumb.h | 6 ++++++ Sources/Sentry/SentryBreadcrumb.m | 6 ++++++ Sources/Sentry/SentryCrashReportConverter.m | 1 + Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift | 7 +++++++ Tests/SentryTests/SentryInterfacesTests.m | 2 ++ Tests/SentryTests/SentryTests.m | 1 + 6 files changed, 23 insertions(+) diff --git a/Sources/Sentry/Public/SentryBreadcrumb.h b/Sources/Sentry/Public/SentryBreadcrumb.h index 8f21b721342..6d66ebfb823 100644 --- a/Sources/Sentry/Public/SentryBreadcrumb.h +++ b/Sources/Sentry/Public/SentryBreadcrumb.h @@ -34,6 +34,12 @@ NS_SWIFT_NAME(Breadcrumb) */ @property (nonatomic, copy) NSString *_Nullable type; +/** + * Origin of the breadcrumb that is used to identify source of the breadcrumb + * For example hybrid SDKs can identify native breadcrumbs from JS or Flutter + */ +@property (nonatomic, copy) NSString *_Nullable origin; + /** * Message for the breadcrumb */ diff --git a/Sources/Sentry/SentryBreadcrumb.m b/Sources/Sentry/SentryBreadcrumb.m index 6baf8ee8944..873039147e4 100644 --- a/Sources/Sentry/SentryBreadcrumb.m +++ b/Sources/Sentry/SentryBreadcrumb.m @@ -30,6 +30,8 @@ - (instancetype)initWithDictionary:(NSDictionary *)dictionary self.category = value; } else if ([key isEqualToString:@"type"] && isString) { self.type = value; + } else if ([key isEqualToString:@"origin"] && isString) { + self.origin = value; } else if ([key isEqualToString:@"message"] && isString) { self.message = value; } else if ([key isEqualToString:@"data"] && isDictionary) { @@ -69,6 +71,7 @@ - (instancetype)init [serializedData setValue:sentry_toIso8601String(self.timestamp) forKey:@"timestamp"]; [serializedData setValue:self.category forKey:@"category"]; [serializedData setValue:self.type forKey:@"type"]; + [serializedData setValue:self.origin forKey:@"origin"]; [serializedData setValue:self.message forKey:@"message"]; [serializedData setValue:sentry_sanitize(self.data) forKey:@"data"]; NSDictionary *unknown = self.unknown; @@ -106,6 +109,8 @@ - (BOOL)isEqualToBreadcrumb:(SentryBreadcrumb *)breadcrumb return NO; if (self.type != breadcrumb.type && ![self.type isEqualToString:breadcrumb.type]) return NO; + if (self.origin != breadcrumb.origin && ![self.origin isEqualToString:breadcrumb.origin]) + return NO; if (self.message != breadcrumb.message && ![self.message isEqualToString:breadcrumb.message]) return NO; if (self.data != breadcrumb.data && ![self.data isEqualToDictionary:breadcrumb.data]) @@ -123,6 +128,7 @@ - (NSUInteger)hash hash = hash * 23 + [self.category hash]; hash = hash * 23 + [self.timestamp hash]; hash = hash * 23 + [self.type hash]; + hash = hash * 23 + [self.origin hash]; hash = hash * 23 + [self.message hash]; hash = hash * 23 + [self.data hash]; hash = hash * 23 + [self.unknown hash]; diff --git a/Sources/Sentry/SentryCrashReportConverter.m b/Sources/Sentry/SentryCrashReportConverter.m index 0c5c3424c3a..f42fcd06fe1 100644 --- a/Sources/Sentry/SentryCrashReportConverter.m +++ b/Sources/Sentry/SentryCrashReportConverter.m @@ -170,6 +170,7 @@ - (SentryUser *_Nullable)convertUser category:storedCrumb[@"category"]]; crumb.message = storedCrumb[@"message"]; crumb.type = storedCrumb[@"type"]; + crumb.origin = storedCrumb[@"origin"]; crumb.timestamp = sentry_fromIso8601String(storedCrumb[@"timestamp"]); crumb.data = storedCrumb[@"data"]; [breadcrumbs addObject:crumb]; diff --git a/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift b/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift index 3e8a5effb56..ea1e879bcfd 100644 --- a/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift +++ b/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift @@ -8,6 +8,7 @@ class SentryBreadcrumbTests: XCTestCase { let category = "category" let type = "user" + let origin = "origin" let message = "Click something" init() { @@ -18,6 +19,7 @@ class SentryBreadcrumbTests: XCTestCase { breadcrumb.timestamp = date breadcrumb.category = category breadcrumb.type = type + breadcrumb.origin = origin breadcrumb.message = message breadcrumb.data = ["some": ["data": "data", "date": date] as [String: Any]] breadcrumb.setValue(["foo": "bar"], forKey: "unknown") @@ -36,6 +38,7 @@ class SentryBreadcrumbTests: XCTestCase { "timestamp": fixture.dateAs8601String, "category": fixture.category, "type": fixture.type, + "origin": fixture.origin, "message": fixture.message, "data": ["foo": "bar"], "foo": "bar" // Unknown @@ -46,6 +49,7 @@ class SentryBreadcrumbTests: XCTestCase { XCTAssertEqual(breadcrumb.timestamp, fixture.date) XCTAssertEqual(breadcrumb.category, fixture.category) XCTAssertEqual(breadcrumb.type, fixture.type) + XCTAssertEqual(breadcrumb.origin, fixture.origin) XCTAssertEqual(breadcrumb.message, fixture.message) XCTAssertEqual(breadcrumb.data as? [String: String], ["foo": "bar"]) XCTAssertEqual(breadcrumb.value(forKey: "unknown") as? NSDictionary, ["foo": "bar"]) @@ -79,6 +83,7 @@ class SentryBreadcrumbTests: XCTestCase { testIsNotEqual { breadcrumb in breadcrumb.category = "" } testIsNotEqual { breadcrumb in breadcrumb.timestamp = Date() } testIsNotEqual { breadcrumb in breadcrumb.type = "" } + testIsNotEqual { breadcrumb in breadcrumb.origin = "" } testIsNotEqual { breadcrumb in breadcrumb.message = "" } testIsNotEqual { breadcrumb in breadcrumb.data?.removeAll() } testIsNotEqual { breadcrumb in breadcrumb.setValue(nil, forKey: "unknown") } @@ -99,6 +104,7 @@ class SentryBreadcrumbTests: XCTestCase { crumb.timestamp = nil crumb.category = "" crumb.type = "" + crumb.origin = "" crumb.message = "" crumb.data = nil crumb.setValue(nil, forKey: "unknown") @@ -107,6 +113,7 @@ class SentryBreadcrumbTests: XCTestCase { XCTAssertEqual(fixture.dateAs8601String, actual["timestamp"] as? String) XCTAssertEqual(fixture.category, actual["category"] as? String) XCTAssertEqual(fixture.type, actual["type"] as? String) + XCTAssertEqual(fixture.origin, actual["origin"] as? String) XCTAssertEqual(fixture.message, actual["message"] as? String) XCTAssertEqual(["some": ["data": "data", "date": fixture.dateAs8601String]], actual["data"] as? Dictionary) XCTAssertEqual("bar", actual["foo"] as? String) diff --git a/Tests/SentryTests/SentryInterfacesTests.m b/Tests/SentryTests/SentryInterfacesTests.m index 34d1f9ccc90..278a9cdda16 100644 --- a/Tests/SentryTests/SentryInterfacesTests.m +++ b/Tests/SentryTests/SentryInterfacesTests.m @@ -378,10 +378,12 @@ - (void)testBreadcrumb crumb2.type = @"type"; crumb2.timestamp = date; crumb2.message = @"message"; + crumb2.origin = @"origin"; NSDictionary *serialized2 = @{ @"level" : @"info", @"type" : @"type", @"message" : @"message", + @"origin" : @"origin", @"timestamp" : sentry_toIso8601String(date), @"category" : @"http", @"data" : @ { @"bla" : @"1" }, diff --git a/Tests/SentryTests/SentryTests.m b/Tests/SentryTests/SentryTests.m index b4f06843310..ded7c52b418 100644 --- a/Tests/SentryTests/SentryTests.m +++ b/Tests/SentryTests/SentryTests.m @@ -78,6 +78,7 @@ - (void)testSDKBreadCrumbAdd SentryBreadcrumb *crumb = [[SentryBreadcrumb alloc] initWithLevel:kSentryLevelInfo category:@"testCategory"]; crumb.type = @"testType"; + crumb.origin = @"testOrigin"; crumb.message = @"testMessage"; crumb.data = @{ @"testDataKey" : @"testDataVaue" }; From d084b2bb216e8039b950cec9a4bcac87e45d9d52 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Fri, 20 Sep 2024 14:04:59 +0300 Subject: [PATCH 02/10] Adds changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 727bd1a403d..2696c341ff1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Features - Added `thermal_state` to device context (#4305) +- Added breadcrumb.origin field (#4358) ### Refactoring From 98ee07903fea159e2f8ffa91d8b64cc31256081d Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Mon, 23 Sep 2024 17:06:36 +0300 Subject: [PATCH 03/10] Moves changelog in the unreleased section --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c28ce5b6fa6..44cc87cdb84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,16 @@ # Changelog +## Unreleased + +### Features + +- Added breadcrumb.origin field (#4358) + ## 8.37.0-beta.1 ### Features - Added `thermal_state` to device context (#4305) -- Added breadcrumb.origin field (#4358) - Send envelopes that cannot be cached to disk (#4294) ### Refactoring From 5ea6526a81dd2d6a0480d0f2e324c0b1f41ccc19 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Mon, 23 Sep 2024 18:08:36 +0300 Subject: [PATCH 04/10] Adds nil equality test case --- Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift b/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift index ea1e879bcfd..bd24b8c2884 100644 --- a/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift +++ b/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift @@ -72,6 +72,10 @@ class SentryBreadcrumbTests: XCTestCase { func testIsNotEqualToOtherClass() { XCTAssertFalse(fixture.breadcrumb.isEqual(1)) } + + func testIsNotEqualToNil() { + XCTAssertFalse(fixture.breadcrumb.isEqual(nil)) + } func testIsEqualToOtherInstanceWithSameValues() { let fixture2 = Fixture() From 77cc8120a74ae34ac1820be529dd1c90a82aca67 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 24 Sep 2024 10:29:00 +0300 Subject: [PATCH 05/10] Adds test case validating inequality if the breadcrumb origin is different --- Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift b/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift index bd24b8c2884..53ac83159b4 100644 --- a/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift +++ b/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift @@ -76,6 +76,12 @@ class SentryBreadcrumbTests: XCTestCase { func testIsNotEqualToNil() { XCTAssertFalse(fixture.breadcrumb.isEqual(nil)) } + + func testIsNotEqualIfOriginDiffers() { + let fixture2 = Fixture() + fixture2.breadcrumb.origin = "origin2" + XCTAssertFalse(fixture.breadcrumb, fixture2.breadcrumb) + } func testIsEqualToOtherInstanceWithSameValues() { let fixture2 = Fixture() From fcfbff2d97580f233f92b2e4a87610c8c1499bd3 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 24 Sep 2024 10:36:04 +0300 Subject: [PATCH 06/10] Fixes broken test --- Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift b/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift index 53ac83159b4..bb78b609188 100644 --- a/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift +++ b/Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift @@ -80,7 +80,7 @@ class SentryBreadcrumbTests: XCTestCase { func testIsNotEqualIfOriginDiffers() { let fixture2 = Fixture() fixture2.breadcrumb.origin = "origin2" - XCTAssertFalse(fixture.breadcrumb, fixture2.breadcrumb) + XCTAssertNotEqual(fixture.breadcrumb, fixture2.breadcrumb) } func testIsEqualToOtherInstanceWithSameValues() { From 77b6372e7186c762c0418246d16536c3d576168d Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 24 Sep 2024 11:54:21 +0300 Subject: [PATCH 07/10] Use nullability annotation for origin Co-authored-by: Dhiogo Brustolin --- Sources/Sentry/Public/SentryBreadcrumb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Sentry/Public/SentryBreadcrumb.h b/Sources/Sentry/Public/SentryBreadcrumb.h index 6d66ebfb823..144031e9cef 100644 --- a/Sources/Sentry/Public/SentryBreadcrumb.h +++ b/Sources/Sentry/Public/SentryBreadcrumb.h @@ -38,7 +38,7 @@ NS_SWIFT_NAME(Breadcrumb) * Origin of the breadcrumb that is used to identify source of the breadcrumb * For example hybrid SDKs can identify native breadcrumbs from JS or Flutter */ -@property (nonatomic, copy) NSString *_Nullable origin; +@property (nonatomic, copy, nullable) NSString * origin; /** * Message for the breadcrumb From f03ae61242557114b7d89511dc7ab5677984a1ba Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Tue, 24 Sep 2024 08:55:24 +0000 Subject: [PATCH 08/10] Format code --- Sources/Sentry/Public/SentryBreadcrumb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Sentry/Public/SentryBreadcrumb.h b/Sources/Sentry/Public/SentryBreadcrumb.h index 144031e9cef..529c363e65c 100644 --- a/Sources/Sentry/Public/SentryBreadcrumb.h +++ b/Sources/Sentry/Public/SentryBreadcrumb.h @@ -38,7 +38,7 @@ NS_SWIFT_NAME(Breadcrumb) * Origin of the breadcrumb that is used to identify source of the breadcrumb * For example hybrid SDKs can identify native breadcrumbs from JS or Flutter */ -@property (nonatomic, copy, nullable) NSString * origin; +@property (nonatomic, copy, nullable) NSString *origin; /** * Message for the breadcrumb From c2f49e080b3e1a4470540dd5e79b8ab9df8cb40d Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Tue, 24 Sep 2024 12:02:57 +0300 Subject: [PATCH 09/10] Updates nullable field declarations to use annotations --- Sources/Sentry/Public/SentryBreadcrumb.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/Sentry/Public/SentryBreadcrumb.h b/Sources/Sentry/Public/SentryBreadcrumb.h index 529c363e65c..3c93cce99c5 100644 --- a/Sources/Sentry/Public/SentryBreadcrumb.h +++ b/Sources/Sentry/Public/SentryBreadcrumb.h @@ -26,13 +26,13 @@ NS_SWIFT_NAME(Breadcrumb) /** * @c NSDate when the breadcrumb happened */ -@property (nonatomic, strong) NSDate *_Nullable timestamp; +@property (nonatomic, strong, nullable) NSDate *timestamp; /** * Type of breadcrumb, can be e.g.: http, empty, user, navigation * This will be used as icon of the breadcrumb */ -@property (nonatomic, copy) NSString *_Nullable type; +@property (nonatomic, copy, nullable) NSString *type; /** * Origin of the breadcrumb that is used to identify source of the breadcrumb @@ -43,12 +43,12 @@ NS_SWIFT_NAME(Breadcrumb) /** * Message for the breadcrumb */ -@property (nonatomic, copy) NSString *_Nullable message; +@property (nonatomic, copy, nullable) NSString *message; /** * Arbitrary additional data that will be sent with the breadcrumb */ -@property (nonatomic, strong) NSDictionary *_Nullable data; +@property (nonatomic, strong, nullable) NSDictionary *data; /** * Initializer for @c SentryBreadcrumb From 5da364f4fa26229299a64950e0cf637fd5fea464 Mon Sep 17 00:00:00 2001 From: Antonis Lilis Date: Wed, 25 Sep 2024 15:35:30 +0300 Subject: [PATCH 10/10] Makes origin field private --- CHANGELOG.md | 2 +- Sources/Sentry/Public/SentryBreadcrumb.h | 6 ------ Sources/Sentry/SentryBreadcrumb.m | 1 + Sources/Sentry/SentryCrashReportConverter.m | 1 + .../include/HybridPublic/SentryBreadcrumb+Private.h | 8 +++++++- Tests/SentryTests/SentryInterfacesTests.m | 1 + Tests/SentryTests/SentryTests-Bridging-Header.h | 1 + Tests/SentryTests/SentryTests.m | 1 + 8 files changed, 13 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index daca21a507c..525f5d1b44f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Features -- Added breadcrumb.origin field (#4358) +- Added breadcrumb.origin private field (#4358) - Custom redact modifier for SwiftUI (#4362) ### Improvements diff --git a/Sources/Sentry/Public/SentryBreadcrumb.h b/Sources/Sentry/Public/SentryBreadcrumb.h index 3c93cce99c5..181cf8f9ad0 100644 --- a/Sources/Sentry/Public/SentryBreadcrumb.h +++ b/Sources/Sentry/Public/SentryBreadcrumb.h @@ -34,12 +34,6 @@ NS_SWIFT_NAME(Breadcrumb) */ @property (nonatomic, copy, nullable) NSString *type; -/** - * Origin of the breadcrumb that is used to identify source of the breadcrumb - * For example hybrid SDKs can identify native breadcrumbs from JS or Flutter - */ -@property (nonatomic, copy, nullable) NSString *origin; - /** * Message for the breadcrumb */ diff --git a/Sources/Sentry/SentryBreadcrumb.m b/Sources/Sentry/SentryBreadcrumb.m index 873039147e4..ad65cff2600 100644 --- a/Sources/Sentry/SentryBreadcrumb.m +++ b/Sources/Sentry/SentryBreadcrumb.m @@ -1,4 +1,5 @@ #import "SentryBreadcrumb.h" +#import "SentryBreadcrumb+Private.h" #import "SentryDateUtils.h" #import "SentryLevelMapper.h" #import "SentryNSDictionarySanitize.h" diff --git a/Sources/Sentry/SentryCrashReportConverter.m b/Sources/Sentry/SentryCrashReportConverter.m index f42fcd06fe1..2dbcc008335 100644 --- a/Sources/Sentry/SentryCrashReportConverter.m +++ b/Sources/Sentry/SentryCrashReportConverter.m @@ -1,4 +1,5 @@ #import "SentryCrashReportConverter.h" +#import "SentryBreadcrumb+Private.h" #import "SentryBreadcrumb.h" #import "SentryCrashStackCursor.h" #import "SentryDateUtils.h" diff --git a/Sources/Sentry/include/HybridPublic/SentryBreadcrumb+Private.h b/Sources/Sentry/include/HybridPublic/SentryBreadcrumb+Private.h index 4bfe80f68fd..21d2e10e787 100644 --- a/Sources/Sentry/include/HybridPublic/SentryBreadcrumb+Private.h +++ b/Sources/Sentry/include/HybridPublic/SentryBreadcrumb+Private.h @@ -2,10 +2,16 @@ @interface SentryBreadcrumb () +/** + * Origin of the breadcrumb that is used to identify source of the breadcrumb + * For example hybrid SDKs can identify native breadcrumbs from JS or Flutter + */ +@property (nonatomic, copy, nullable) NSString *origin; + /** * Initializes a SentryBreadcrumb from a JSON object. * @param dictionary The dictionary containing breadcrumb data. * @return The SentryBreadcrumb. */ -- (instancetype)initWithDictionary:(NSDictionary *)dictionary; +- (instancetype _Nonnull)initWithDictionary:(NSDictionary *_Nonnull)dictionary; @end diff --git a/Tests/SentryTests/SentryInterfacesTests.m b/Tests/SentryTests/SentryInterfacesTests.m index 278a9cdda16..581368aedfa 100644 --- a/Tests/SentryTests/SentryInterfacesTests.m +++ b/Tests/SentryTests/SentryInterfacesTests.m @@ -1,5 +1,6 @@ #import +#import "SentryBreadcrumb+Private.h" #import "SentryBreadcrumb.h" #import "SentryDateUtils.h" #import "SentryEvent.h" diff --git a/Tests/SentryTests/SentryTests-Bridging-Header.h b/Tests/SentryTests/SentryTests-Bridging-Header.h index 1f992477884..5b8265c9863 100644 --- a/Tests/SentryTests/SentryTests-Bridging-Header.h +++ b/Tests/SentryTests/SentryTests-Bridging-Header.h @@ -58,6 +58,7 @@ #import "SentryAutoBreadcrumbTrackingIntegration.h" #import "SentryAutoSessionTrackingIntegration.h" #import "SentryBooleanSerialization.h" +#import "SentryBreadcrumb+Private.h" #import "SentryBreadcrumbDelegate.h" #import "SentryBreadcrumbTracker.h" #import "SentryByteCountFormatter.h" diff --git a/Tests/SentryTests/SentryTests.m b/Tests/SentryTests/SentryTests.m index ded7c52b418..74162b2853c 100644 --- a/Tests/SentryTests/SentryTests.m +++ b/Tests/SentryTests/SentryTests.m @@ -10,6 +10,7 @@ #import "SentryMeta.h" #import "SentryOptions+HybridSDKs.h" #import "SentrySDK+Private.h" +#import #import @import Sentry;