Skip to content

Commit

Permalink
feat: Adds breadcrumb.origin field (#4358)
Browse files Browse the repository at this point in the history
* Adds breadcrumb.origin private field

* Adds changelog

* Adds nil equality test case

* Adds test case validating inequality if the breadcrumb origin is different

* Use nullability annotation for origin

Co-authored-by: Dhiogo Brustolin <[email protected]>

* Updates nullable field declarations to use annotations

---------

Co-authored-by: Dhiogo Brustolin <[email protected]>
Co-authored-by: Sentry Github Bot <[email protected]>
  • Loading branch information
3 people authored Sep 26, 2024
1 parent 3fda1c4 commit 3eb2070
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Features

- Added breadcrumb.origin private field (#4358)
- Custom redact modifier for SwiftUI (#4362)

### Improvements
Expand Down
8 changes: 4 additions & 4 deletions Sources/Sentry/Public/SentryBreadcrumb.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,23 @@ 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;

/**
* 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<NSString *, id> *_Nullable data;
@property (nonatomic, strong, nullable) NSDictionary<NSString *, id> *data;

/**
* Initializer for @c SentryBreadcrumb
Expand Down
7 changes: 7 additions & 0 deletions Sources/Sentry/SentryBreadcrumb.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#import "SentryBreadcrumb.h"
#import "SentryBreadcrumb+Private.h"
#import "SentryDateUtils.h"
#import "SentryLevelMapper.h"
#import "SentryNSDictionarySanitize.h"
Expand Down Expand Up @@ -30,6 +31,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) {
Expand Down Expand Up @@ -69,6 +72,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<NSString *, id> *unknown = self.unknown;
Expand Down Expand Up @@ -106,6 +110,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])
Expand All @@ -123,6 +129,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];
Expand Down
2 changes: 2 additions & 0 deletions Sources/Sentry/SentryCrashReportConverter.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#import "SentryCrashReportConverter.h"
#import "SentryBreadcrumb+Private.h"
#import "SentryBreadcrumb.h"
#import "SentryCrashStackCursor.h"
#import "SentryDateUtils.h"
Expand Down Expand Up @@ -170,6 +171,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];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
17 changes: 17 additions & 0 deletions Tests/SentryTests/Protocol/SentryBreadcrumbTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class SentryBreadcrumbTests: XCTestCase {

let category = "category"
let type = "user"
let origin = "origin"
let message = "Click something"

init() {
Expand All @@ -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")
Expand All @@ -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
Expand All @@ -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"])
Expand All @@ -68,6 +72,16 @@ class SentryBreadcrumbTests: XCTestCase {
func testIsNotEqualToOtherClass() {
XCTAssertFalse(fixture.breadcrumb.isEqual(1))
}

func testIsNotEqualToNil() {
XCTAssertFalse(fixture.breadcrumb.isEqual(nil))
}

func testIsNotEqualIfOriginDiffers() {
let fixture2 = Fixture()
fixture2.breadcrumb.origin = "origin2"
XCTAssertNotEqual(fixture.breadcrumb, fixture2.breadcrumb)
}

func testIsEqualToOtherInstanceWithSameValues() {
let fixture2 = Fixture()
Expand All @@ -79,6 +93,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") }
Expand All @@ -99,6 +114,7 @@ class SentryBreadcrumbTests: XCTestCase {
crumb.timestamp = nil
crumb.category = ""
crumb.type = ""
crumb.origin = ""
crumb.message = ""
crumb.data = nil
crumb.setValue(nil, forKey: "unknown")
Expand All @@ -107,6 +123,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)
Expand Down
3 changes: 3 additions & 0 deletions Tests/SentryTests/SentryInterfacesTests.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#import <XCTest/XCTest.h>

#import "SentryBreadcrumb+Private.h"
#import "SentryBreadcrumb.h"
#import "SentryDateUtils.h"
#import "SentryEvent.h"
Expand Down Expand Up @@ -378,10 +379,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" },
Expand Down
1 change: 1 addition & 0 deletions Tests/SentryTests/SentryTests-Bridging-Header.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
2 changes: 2 additions & 0 deletions Tests/SentryTests/SentryTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#import "SentryMeta.h"
#import "SentryOptions+HybridSDKs.h"
#import "SentrySDK+Private.h"
#import <SentryBreadcrumb+Private.h>
#import <XCTest/XCTest.h>
@import Sentry;

Expand Down Expand Up @@ -78,6 +79,7 @@ - (void)testSDKBreadCrumbAdd
SentryBreadcrumb *crumb = [[SentryBreadcrumb alloc] initWithLevel:kSentryLevelInfo
category:@"testCategory"];
crumb.type = @"testType";
crumb.origin = @"testOrigin";
crumb.message = @"testMessage";
crumb.data = @{ @"testDataKey" : @"testDataVaue" };

Expand Down

0 comments on commit 3eb2070

Please sign in to comment.