Skip to content

Commit f4e0299

Browse files
authored
Add name and geo to User (#2710)
1 parent e5ac362 commit f4e0299

File tree

11 files changed

+258
-1
lines changed

11 files changed

+258
-1
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## Unreleased
44

5+
### Features
6+
7+
- Add `name` and `geo` to User (#2710)
58
### Fixes
69

710
- Correctly track and send GPU frame render data in profiles (#2823)

Sentry.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -692,6 +692,9 @@
692692
8ED2D28026A6581C00CA8329 /* NSURLProtocolSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 8ED2D27F26A6581C00CA8329 /* NSURLProtocolSwizzle.m */; };
693693
8ED3D306264DFE700049393B /* SwiftDescriptorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8ED3D305264DFE700049393B /* SwiftDescriptorTests.swift */; };
694694
8EE017A126704CD500470616 /* SentryUIViewControllerPerformanceTrackerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EA1ED0E2669152F00E62B98 /* SentryUIViewControllerPerformanceTrackerTests.swift */; };
695+
9286059529A5096600F96038 /* SentryGeo.h in Headers */ = {isa = PBXBuildFile; fileRef = 9286059429A5096600F96038 /* SentryGeo.h */; settings = {ATTRIBUTES = (Public, ); }; };
696+
9286059729A5098900F96038 /* SentryGeo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9286059629A5098900F96038 /* SentryGeo.m */; };
697+
9286059929A50BAB00F96038 /* SentryGeoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9286059829A50BAA00F96038 /* SentryGeoTests.swift */; };
695698
A2475E1325FB63A3007D9080 /* fishhook.h in Headers */ = {isa = PBXBuildFile; fileRef = A2475E1225FB63A3007D9080 /* fishhook.h */; };
696699
A2475E1725FB63AF007D9080 /* SentryHook.h in Headers */ = {isa = PBXBuildFile; fileRef = A2475E1625FB63AF007D9080 /* SentryHook.h */; };
697700
A2475E1B25FB63D7007D9080 /* SentryHook.c in Sources */ = {isa = PBXBuildFile; fileRef = A2475E1A25FB63D7007D9080 /* SentryHook.c */; };
@@ -1589,6 +1592,9 @@
15891592
8ED2D27E26A6581C00CA8329 /* NSURLProtocolSwizzle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSURLProtocolSwizzle.h; sourceTree = "<group>"; };
15901593
8ED2D27F26A6581C00CA8329 /* NSURLProtocolSwizzle.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSURLProtocolSwizzle.m; sourceTree = "<group>"; };
15911594
8ED3D305264DFE700049393B /* SwiftDescriptorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftDescriptorTests.swift; sourceTree = "<group>"; };
1595+
9286059429A5096600F96038 /* SentryGeo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryGeo.h; path = Public/SentryGeo.h; sourceTree = "<group>"; };
1596+
9286059629A5098900F96038 /* SentryGeo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryGeo.m; sourceTree = "<group>"; };
1597+
9286059829A50BAA00F96038 /* SentryGeoTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SentryGeoTests.swift; sourceTree = "<group>"; };
15921598
A2475E1225FB63A3007D9080 /* fishhook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fishhook.h; sourceTree = "<group>"; };
15931599
A2475E1625FB63AF007D9080 /* SentryHook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentryHook.h; sourceTree = "<group>"; };
15941600
A2475E1A25FB63D7007D9080 /* SentryHook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SentryHook.c; sourceTree = "<group>"; };
@@ -1836,6 +1842,8 @@
18361842
639FCF9B1EBC7F9500778193 /* SentryThread.m */,
18371843
639FCFAA1EBC811400778193 /* SentryUser.h */,
18381844
639FCFAB1EBC811400778193 /* SentryUser.m */,
1845+
9286059429A5096600F96038 /* SentryGeo.h */,
1846+
9286059629A5098900F96038 /* SentryGeo.m */,
18391847
63B818F71EC34639002FDF4C /* SentryDebugMeta.h */,
18401848
63B818F81EC34639002FDF4C /* SentryDebugMeta.m */,
18411849
6360850B1ED2AFE100E8599E /* SentryBreadcrumb.h */,
@@ -2507,6 +2515,7 @@
25072515
7B6D98E824C6D336005502FA /* SentrySdkInfo+Equality.m */,
25082516
7B82D54824E2A2D400EE670F /* SentryIdTests.swift */,
25092517
7B04A9AA24EA5F8D00E710B1 /* SentryUserTests.swift */,
2518+
9286059829A50BAA00F96038 /* SentryGeoTests.swift */,
25102519
7BB42EEF24F3B7B700D7B39A /* SentrySession+Equality.h */,
25112520
7BB42EF024F3B7B700D7B39A /* SentrySession+Equality.m */,
25122521
7B0A5451252311CE00A71716 /* SentryBreadcrumbTests.swift */,
@@ -3519,6 +3528,7 @@
35193528
63FE714F20DA4C1100CDBAE8 /* NSError+SentrySimpleConstructor.h in Headers */,
35203529
7BC5B6FA290BCDE500D99477 /* SentryHttpStatusCodeRange+Private.h in Headers */,
35213530
7B04A9AF24EAC02C00E710B1 /* SentryRetryAfterHeaderParser.h in Headers */,
3531+
9286059529A5096600F96038 /* SentryGeo.h in Headers */,
35223532
7DC83100239826280043DD9A /* SentryIntegrationProtocol.h in Headers */,
35233533
7B98D7BC25FB607300C5A389 /* SentryWatchdogTerminationTracker.h in Headers */,
35243534
7BA61CB9247BC57B00C130A8 /* SentryCrashDefaultBinaryImageProvider.h in Headers */,
@@ -3974,6 +3984,7 @@
39743984
7B98D7CF25FB650F00C5A389 /* SentryWatchdogTerminationTrackingIntegration.m in Sources */,
39753985
8E5D38DD261D4A3E000D363D /* SentryPerformanceTrackingIntegration.m in Sources */,
39763986
7B4E23C2251A2C2B00060D68 /* SentrySessionCrashedHandler.m in Sources */,
3987+
9286059729A5098900F96038 /* SentryGeo.m in Sources */,
39773988
7B42C48227E08F4B009B58C2 /* SentryDependencyContainer.m in Sources */,
39783989
7BA61E9225F21AF80008CAA2 /* SentryLogOutput.m in Sources */,
39793990
639FCFAD1EBC811400778193 /* SentryUser.m in Sources */,
@@ -4076,6 +4087,7 @@
40764087
0A5370A128A3EC2400B2DCDE /* SentryViewHierarchyTests.swift in Sources */,
40774088
D8FFE50C2703DBB400607131 /* SwizzlingCallTests.swift in Sources */,
40784089
7BFAA6E7297AA16A00E7E02E /* SentryCrashMonitor_CppException_Tests.mm in Sources */,
4090+
9286059929A50BAB00F96038 /* SentryGeoTests.swift in Sources */,
40794091
D8B76B0828081461000A58C4 /* TestSentryScreenShot.swift in Sources */,
40804092
A8AFFCD22907DA7600967CD7 /* SentryHttpStatusCodeRangeTests.swift in Sources */,
40814093
7BE2C7F8257000A4003B66C7 /* SentryTestIntegration.m in Sources */,

Sources/Sentry/Public/Sentry.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ FOUNDATION_EXPORT const unsigned char SentryVersionString[];
1919
#import "SentryEvent.h"
2020
#import "SentryException.h"
2121
#import "SentryFrame.h"
22+
#import "SentryGeo.h"
2223
#import "SentryHttpStatusCodeRange.h"
2324
#import "SentryHub.h"
2425
#import "SentryId.h"

Sources/Sentry/Public/SentryDebugMeta.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ NS_SWIFT_NAME(DebugMeta)
3535
/**
3636
* Name of the image. Use @c codeFile when using "macho" as the @c type .
3737
*/
38-
@property (nonatomic, copy) NSString *_Nullable name;
38+
@property (nullable, nonatomic, copy) NSString *name;
3939

4040
/**
4141
* The size of the image in virtual memory. If missing, Sentry will assume that the image spans up

Sources/Sentry/Public/SentryGeo.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#import "SentryDefines.h"
2+
#import "SentrySerializable.h"
3+
#import <Foundation/Foundation.h>
4+
5+
NS_ASSUME_NONNULL_BEGIN
6+
7+
/// Approximate geographical location of the end user or device.
8+
///
9+
/// Example of serialized data:
10+
/// {
11+
/// "geo": {
12+
/// "country_code": "US",
13+
/// "city": "Ashburn",
14+
/// "region": "San Francisco"
15+
/// }
16+
/// }
17+
NS_SWIFT_NAME(Geo)
18+
@interface SentryGeo : NSObject <SentrySerializable, NSCopying>
19+
20+
/**
21+
* Optional: Human readable city name.
22+
*/
23+
@property (nullable, atomic, copy) NSString *city;
24+
25+
/**
26+
* Optional: Two-letter country code (ISO 3166-1 alpha-2).
27+
*/
28+
@property (nullable, atomic, copy) NSString *countryCode;
29+
30+
/**
31+
* Optional: Human readable region name or code.
32+
*/
33+
@property (nullable, atomic, copy) NSString *region;
34+
35+
- (BOOL)isEqual:(id _Nullable)other;
36+
37+
- (BOOL)isEqualToGeo:(SentryGeo *)geo;
38+
39+
- (NSUInteger)hash;
40+
41+
@end
42+
43+
NS_ASSUME_NONNULL_END

Sources/Sentry/Public/SentryUser.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
#import "SentryDefines.h"
2+
#import "SentryGeo.h"
23
#import "SentrySerializable.h"
34

45
NS_ASSUME_NONNULL_BEGIN
56

7+
@class SentryGeo;
8+
69
NS_SWIFT_NAME(User)
710
@interface SentryUser : NSObject <SentrySerializable, NSCopying>
811

@@ -31,6 +34,16 @@ NS_SWIFT_NAME(User)
3134
*/
3235
@property (atomic, copy) NSString *_Nullable segment;
3336

37+
/**
38+
* Optional: Human readable name
39+
*/
40+
@property (atomic, copy) NSString *_Nullable name;
41+
42+
/**
43+
* Optional: Geo location of user
44+
*/
45+
@property (nullable, nonatomic, strong) SentryGeo *geo;
46+
3447
/**
3548
* Optional: Additional data
3649
*/

Sources/Sentry/SentryGeo.m

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#import "SentryGeo.h"
2+
3+
#import <Foundation/Foundation.h>
4+
5+
NS_ASSUME_NONNULL_BEGIN
6+
7+
@implementation SentryGeo
8+
9+
- (id)copyWithZone:(nullable NSZone *)zone
10+
{
11+
SentryGeo *copy = [[[self class] allocWithZone:zone] init];
12+
13+
if (copy != nil) {
14+
copy.city = self.city;
15+
copy.countryCode = self.countryCode;
16+
copy.region = self.region;
17+
}
18+
19+
return copy;
20+
}
21+
22+
- (NSDictionary<NSString *, id> *)serialize
23+
{
24+
return @{ @"city" : self.city, @"country_code" : self.countryCode, @"region" : self.region };
25+
}
26+
27+
- (BOOL)isEqual:(id _Nullable)other
28+
{
29+
if (other == self) {
30+
return YES;
31+
}
32+
if (!other || ![[other class] isEqual:[self class]]) {
33+
return NO;
34+
}
35+
36+
return [self isEqualToGeo:other];
37+
}
38+
39+
- (BOOL)isEqualToGeo:(SentryGeo *)geo
40+
{
41+
if (self == geo) {
42+
return YES;
43+
}
44+
if (geo == nil) {
45+
return NO;
46+
}
47+
48+
NSString *otherCity = geo.city;
49+
if (self.city != otherCity && ![self.city isEqualToString:otherCity]) {
50+
return NO;
51+
}
52+
53+
NSString *otherCountryCode = geo.countryCode;
54+
if (self.countryCode != otherCountryCode
55+
&& ![self.countryCode isEqualToString:otherCountryCode]) {
56+
return NO;
57+
}
58+
59+
NSString *otherRegion = geo.region;
60+
if (self.region != otherRegion && ![self.region isEqualToString:otherRegion]) {
61+
return NO;
62+
}
63+
64+
return YES;
65+
}
66+
67+
- (NSUInteger)hash
68+
{
69+
NSUInteger hash = 17;
70+
71+
hash = hash * 23 + [self.city hash];
72+
hash = hash * 23 + [self.countryCode hash];
73+
hash = hash * 23 + [self.region hash];
74+
75+
return hash;
76+
}
77+
78+
@end
79+
80+
NS_ASSUME_NONNULL_END

Sources/Sentry/SentryUser.m

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ - (id)copyWithZone:(nullable NSZone *)zone
2929
copy.username = self.username;
3030
copy.ipAddress = self.ipAddress;
3131
copy.segment = self.segment;
32+
copy.name = self.name;
33+
copy.geo = self.geo.copy;
3234
copy.data = self.data.copy;
3335
}
3436

@@ -44,6 +46,8 @@ - (id)copyWithZone:(nullable NSZone *)zone
4446
[serializedData setValue:self.username forKey:@"username"];
4547
[serializedData setValue:self.ipAddress forKey:@"ip_address"];
4648
[serializedData setValue:self.segment forKey:@"segment"];
49+
[serializedData setValue:self.name forKey:@"name"];
50+
[serializedData setValue:[self.geo serialize] forKey:@"geo"];
4751
[serializedData setValue:[self.data sentry_sanitize] forKey:@"data"];
4852

4953
return serializedData;
@@ -96,6 +100,16 @@ - (BOOL)isEqualToUser:(SentryUser *)user
96100
return NO;
97101
}
98102

103+
NSString *otherName = user.name;
104+
if (self.name != otherName && ![self.name isEqualToString:otherName]) {
105+
return NO;
106+
}
107+
108+
SentryGeo *otherGeo = user.geo;
109+
if (self.geo != otherGeo && ![self.geo isEqualToGeo:otherGeo]) {
110+
return NO;
111+
}
112+
99113
NSDictionary<NSString *, id> *otherUserData = user.data;
100114
if (self.data != otherUserData && ![self.data isEqualToDictionary:otherUserData]) {
101115
return NO;
@@ -113,6 +127,8 @@ - (NSUInteger)hash
113127
hash = hash * 23 + [self.username hash];
114128
hash = hash * 23 + [self.ipAddress hash];
115129
hash = hash * 23 + [self.segment hash];
130+
hash = hash * 23 + [self.name hash];
131+
hash = hash * 23 + [self.geo hash];
116132
hash = hash * 23 + [self.data hash];
117133

118134
return hash;
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import XCTest
2+
3+
class SentryGeoTests: XCTestCase {
4+
func testSerializationWithAllProperties() {
5+
let geo = TestData.geo.copy() as! Geo
6+
let actual = geo.serialize()
7+
8+
// Changing the original doesn't modify the serialized
9+
geo.city = ""
10+
geo.countryCode = ""
11+
geo.region = ""
12+
13+
XCTAssertEqual(TestData.geo.city, actual["city"] as? String)
14+
XCTAssertEqual(TestData.geo.countryCode, actual["country_code"] as? String)
15+
XCTAssertEqual(TestData.geo.region, actual["region"] as? String)
16+
}
17+
18+
func testHash() {
19+
XCTAssertEqual(TestData.geo.hash(), TestData.geo.hash())
20+
21+
let geo2 = TestData.geo
22+
geo2.city = "Berlin"
23+
XCTAssertNotEqual(TestData.geo.hash(), geo2.hash())
24+
}
25+
26+
func testIsEqualToSelf() {
27+
XCTAssertEqual(TestData.geo, TestData.geo)
28+
XCTAssertTrue(TestData.geo.isEqual(to: TestData.geo))
29+
}
30+
31+
func testIsNotEqualToOtherClass() {
32+
XCTAssertFalse(TestData.geo.isEqual(1))
33+
}
34+
35+
func testIsEqualToCopy() {
36+
XCTAssertEqual(TestData.geo, TestData.geo.copy() as! Geo)
37+
}
38+
39+
func testNotIsEqual() {
40+
testIsNotEqual { geo in geo.city = "" }
41+
testIsNotEqual { geo in geo.countryCode = "" }
42+
testIsNotEqual { geo in geo.region = "" }
43+
}
44+
45+
func testIsNotEqual(block: (Geo) -> Void ) {
46+
let geo = TestData.geo.copy() as! Geo
47+
block(geo)
48+
XCTAssertNotEqual(TestData.geo, geo)
49+
}
50+
51+
func testCopyWithZone_CopiesDeepCopy() {
52+
let geo = TestData.geo
53+
let copiedGeo = geo.copy() as! Geo
54+
55+
// Modifying the original does not change the copy
56+
geo.city = ""
57+
geo.countryCode = ""
58+
geo.region = ""
59+
60+
XCTAssertEqual(TestData.geo, copiedGeo)
61+
}
62+
}

0 commit comments

Comments
 (0)