From 51e09ec82f6ab383fc88a4103e5108746d628661 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Thu, 15 Feb 2024 11:32:06 +0100 Subject: [PATCH 01/10] backup --- Samples/iOS-Swift/iOS-Swift/AppDelegate.swift | 1 + Sentry.xcodeproj/project.pbxproj | 6 ++ Sources/Sentry/Public/SentryOptions.h | 18 +++- Sources/Sentry/SentryClient.m | 6 +- Sources/Sentry/SentryNSURLRequest.m | 23 +++++ Sources/Sentry/SentryNSURLRequestBuilder.m | 11 +++ Sources/Sentry/SentryOptions.m | 9 ++ Sources/Sentry/SentrySpotlightTransport.m | 86 +++++++++++++++++++ Sources/Sentry/SentryTransportAdapter.m | 19 ++-- Sources/Sentry/SentryTransportFactory.m | 33 +++++-- Sources/Sentry/include/SentryNSURLRequest.h | 5 ++ .../include/SentryNSURLRequestBuilder.h | 4 + .../Sentry/include/SentrySpotlightTransport.h | 19 ++++ .../Sentry/include/SentryTransportAdapter.h | 3 +- .../Sentry/include/SentryTransportFactory.h | 4 +- Tests/SentryTests/SentryOptionsTest.m | 11 ++- 16 files changed, 235 insertions(+), 23 deletions(-) create mode 100644 Sources/Sentry/SentrySpotlightTransport.m create mode 100644 Sources/Sentry/include/SentrySpotlightTransport.h diff --git a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift index 9379c6e4f8a..46f89b0be3f 100644 --- a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift +++ b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift @@ -55,6 +55,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { options.sessionTrackingIntervalMillis = 5_000 options.attachScreenshot = true options.attachViewHierarchy = true + options.enableSpotlight = true #if targetEnvironment(simulator) options.environment = "test-app" #else diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index 4fa5d95953f..377800adc90 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -92,6 +92,7 @@ 62A456E32B0370AA003F19A1 /* SentryUIEventTrackerTransactionMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 62A456E22B0370AA003F19A1 /* SentryUIEventTrackerTransactionMode.h */; }; 62A456E52B0370E0003F19A1 /* SentryUIEventTrackerTransactionMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 62A456E42B0370E0003F19A1 /* SentryUIEventTrackerTransactionMode.m */; }; 62B86CFC29F052BB008F3947 /* SentryTestLogConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 62B86CFB29F052BB008F3947 /* SentryTestLogConfig.m */; }; + 62C1AFAB2B7E10EA0038C5F7 /* SentrySpotlightTransport.m in Sources */ = {isa = PBXBuildFile; fileRef = 62C1AFAA2B7E10EA0038C5F7 /* SentrySpotlightTransport.m */; }; 62C25C862B075F4900C68CBD /* TestOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62C25C852B075F4900C68CBD /* TestOptions.swift */; }; 62C316812B1F2E93000D7031 /* SentryDelayedFramesTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 62C316802B1F2E93000D7031 /* SentryDelayedFramesTracker.h */; }; 62C316832B1F2EA1000D7031 /* SentryDelayedFramesTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = 62C316822B1F2EA1000D7031 /* SentryDelayedFramesTracker.m */; }; @@ -1010,6 +1011,8 @@ 62A456E22B0370AA003F19A1 /* SentryUIEventTrackerTransactionMode.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryUIEventTrackerTransactionMode.h; path = include/SentryUIEventTrackerTransactionMode.h; sourceTree = ""; }; 62A456E42B0370E0003F19A1 /* SentryUIEventTrackerTransactionMode.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryUIEventTrackerTransactionMode.m; sourceTree = ""; }; 62B86CFB29F052BB008F3947 /* SentryTestLogConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryTestLogConfig.m; sourceTree = ""; }; + 62C1AFA92B7E10D30038C5F7 /* SentrySpotlightTransport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentrySpotlightTransport.h; path = include/SentrySpotlightTransport.h; sourceTree = ""; }; + 62C1AFAA2B7E10EA0038C5F7 /* SentrySpotlightTransport.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentrySpotlightTransport.m; sourceTree = ""; }; 62C25C852B075F4900C68CBD /* TestOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestOptions.swift; sourceTree = ""; }; 62C316802B1F2E93000D7031 /* SentryDelayedFramesTracker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryDelayedFramesTracker.h; path = include/SentryDelayedFramesTracker.h; sourceTree = ""; }; 62C316822B1F2EA1000D7031 /* SentryDelayedFramesTracker.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDelayedFramesTracker.m; sourceTree = ""; }; @@ -1923,6 +1926,8 @@ 7BAF3DB8243C9777008A5414 /* SentryTransport.h */, 6383953523ABA42C000C1594 /* SentryHttpTransport.h */, 7DB3A684238EA75E00A2D442 /* SentryHttpTransport.m */, + 62C1AFA92B7E10D30038C5F7 /* SentrySpotlightTransport.h */, + 62C1AFAA2B7E10EA0038C5F7 /* SentrySpotlightTransport.m */, 7BA0C04528055F8E003E0326 /* SentryTransportAdapter.h */, 7BA0C0472805600A003E0326 /* SentryTransportAdapter.m */, 7BC8523624588115005A70F0 /* SentryDataCategory.h */, @@ -4183,6 +4188,7 @@ 63FE711D20DA4C1000CDBAE8 /* SentryCrashCPU_arm64.c in Sources */, 844EDC77294144DB00C86F34 /* SentrySystemWrapper.mm in Sources */, 630435FF1EBCA9D900C4D3FA /* SentryNSURLRequest.m in Sources */, + 62C1AFAB2B7E10EA0038C5F7 /* SentrySpotlightTransport.m in Sources */, 7B5CAF7727F5A68C00ED0DB6 /* SentryNSURLRequestBuilder.m in Sources */, 639FCFA11EBC804600778193 /* SentryException.m in Sources */, 33042A0D29DAF79A00C60085 /* SentryExtraContextProvider.m in Sources */, diff --git a/Sources/Sentry/Public/SentryOptions.h b/Sources/Sentry/Public/SentryOptions.h index c7714a631ae..4f085b5dd32 100644 --- a/Sources/Sentry/Public/SentryOptions.h +++ b/Sources/Sentry/Public/SentryOptions.h @@ -166,7 +166,8 @@ NS_SWIFT_NAME(Options) * The maximum size for each attachment in bytes. * @note Default is 20 MiB (20 ✕ 1024 ✕ 1024 bytes). * @note Please also check the maximum attachment size of relay to make sure your attachments don't - * get discarded there: https://docs.sentry.io/product/relay/options/ + * get discarded there: + * https://docs.sentry.io/product/relay/options/ */ @property (nonatomic, assign) NSUInteger maxAttachmentSize; @@ -523,6 +524,21 @@ NS_SWIFT_NAME(Options) YES)`. */ @property (nonatomic, copy) NSString *cacheDirectoryPath; + +/** + * Whether to enable Spotlight for local development. For more information see + * https://spotlightjs.com/. + * + * @note Only set this option to `true` while developing, not in production! + */ +@property (nonatomic, assign) BOOL enableSpotlight; + +/** + * The Spotlight URL. Defaults to http://localhost:8969/stream. For more information see + * https://spotlightjs.com/ + */ +@property (nonatomic, copy) NSString *spotlightUrl; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryClient.m b/Sources/Sentry/SentryClient.m index a93836b2372..d7435185011 100644 --- a/Sources/Sentry/SentryClient.m +++ b/Sources/Sentry/SentryClient.m @@ -98,11 +98,11 @@ - (instancetype)initWithOptions:(SentryOptions *)options fileManager:(SentryFileManager *)fileManager deleteOldEnvelopeItems:(BOOL)deleteOldEnvelopeItems { - id transport = [SentryTransportFactory initTransport:options - sentryFileManager:fileManager]; + NSArray> *transports = [SentryTransportFactory initTransports:options + sentryFileManager:fileManager]; SentryTransportAdapter *transportAdapter = - [[SentryTransportAdapter alloc] initWithTransport:transport options:options]; + [[SentryTransportAdapter alloc] initWithTransports:transports options:options]; return [self initWithOptions:options fileManager:fileManager diff --git a/Sources/Sentry/SentryNSURLRequest.m b/Sources/Sentry/SentryNSURLRequest.m index 89f69ed171e..47f6a0fa4d6 100644 --- a/Sources/Sentry/SentryNSURLRequest.m +++ b/Sources/Sentry/SentryNSURLRequest.m @@ -87,6 +87,29 @@ - (_Nullable instancetype)initEnvelopeRequestWithDsn:(SentryDsn *)dsn return self; } +- (instancetype)initEnvelopeRequestWithURL:(NSURL *)url + andData:(NSData *)data + authHeader:(nullable NSString *)authHeader + didFailWithError:(NSError *_Nullable *_Nullable)error +{ + self = [super initWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:SentryRequestTimeout]; + if (self) { + self.HTTPMethod = @"POST"; + + if (authHeader) { + [self setValue:authHeader forHTTPHeaderField:@"X-Sentry-Auth"]; + } + [self setValue:@"application/x-sentry-envelope" forHTTPHeaderField:@"Content-Type"]; + [self setValue:SentryMeta.sdkName forHTTPHeaderField:@"User-Agent"]; + [self setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"]; + self.HTTPBody = [data sentry_gzippedWithCompressionLevel:-1 error:error]; + } + + return self; +} + static NSString * newHeaderPart(NSString *key, id value) { diff --git a/Sources/Sentry/SentryNSURLRequestBuilder.m b/Sources/Sentry/SentryNSURLRequestBuilder.m index 54d23d8027e..78e3f58e435 100644 --- a/Sources/Sentry/SentryNSURLRequestBuilder.m +++ b/Sources/Sentry/SentryNSURLRequestBuilder.m @@ -18,6 +18,17 @@ - (NSURLRequest *)createEnvelopeRequest:(SentryEnvelope *)envelope didFailWithError:error]; } +- (NSURLRequest *)createEnvelopeRequest:(SentryEnvelope *)envelope + url:(NSURL *)url + didFailWithError:(NSError *_Nullable *_Nullable)error +{ + return [[SentryNSURLRequest alloc] + initEnvelopeRequestWithURL:url + andData:[SentrySerialization dataWithEnvelope:envelope error:error] + authHeader:nil + didFailWithError:error]; +} + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryOptions.m b/Sources/Sentry/SentryOptions.m index 82a1e4a506e..130e1251e18 100644 --- a/Sources/Sentry/SentryOptions.m +++ b/Sources/Sentry/SentryOptions.m @@ -141,6 +141,8 @@ - (instancetype)init _enableSwizzling = YES; self.sendClientReports = YES; self.swiftAsyncStacktraces = NO; + self.enableSpotlight = NO; + self.spotlightUrl = @"http://localhost:8969/stream"; #if TARGET_OS_OSX NSString *dsn = [[[NSProcessInfo processInfo] environment] objectForKey:@"SENTRY_DSN"]; @@ -496,6 +498,13 @@ - (BOOL)validateOptions:(NSDictionary *)options } #endif // SENTRY_HAS_METRIC_KIT + [self setBool:options[@"enableSpotlight"] + block:^(BOOL value) { self->_enableSpotlight = value; }]; + + if ([options[@"spotlightUrl"] isKindOfClass:[NSString class]]) { + self.spotlightUrl = options[@"spotlightUrl"]; + } + return YES; } diff --git a/Sources/Sentry/SentrySpotlightTransport.m b/Sources/Sentry/SentrySpotlightTransport.m new file mode 100644 index 00000000000..f305d337b35 --- /dev/null +++ b/Sources/Sentry/SentrySpotlightTransport.m @@ -0,0 +1,86 @@ +#import "SentrySpotlightTransport.h" +#import "SentryDispatchQueueWrapper.h" +#import "SentryEnvelope.h" +#import "SentryEnvelopeItemHeader.h" +#import "SentryEnvelopeItemType.h" +#import "SentryNSURLRequest.h" +#import "SentryNSURLRequestBuilder.h" +#import "SentryOptions.h" +#import "SentrySerialization.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface +SentrySpotlightTransport () + +@property (nonatomic, strong) id requestManager; +@property (nonatomic, strong) SentryNSURLRequestBuilder *requestBuilder; +@property (nonatomic, strong) SentryOptions *options; +@property (nonatomic, strong) SentryDispatchQueueWrapper *dispatchQueue; + +@end + +@implementation SentrySpotlightTransport + +- (id)initWithOptions:(SentryOptions *)options + requestManager:(id)requestManager + requestBuilder:(SentryNSURLRequestBuilder *)requestBuilder + dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper +{ + + if (self = [super init]) { + self.options = options; + self.requestManager = requestManager; + self.requestBuilder = requestBuilder; + self.dispatchQueue = dispatchQueueWrapper; + } + + return self; +} + +- (void)sendEnvelope:(SentryEnvelope *)envelope +{ + + NSMutableArray *envelopeItems = [NSMutableArray new]; + for (SentryEnvelopeItem *item in envelope.items) { + if ([item.header.type isEqualToString:SentryEnvelopeItemTypeEvent]) { + [envelopeItems addObject:item]; + } + if ([item.header.type isEqualToString:SentryEnvelopeItemTypeTransaction]) { + [envelopeItems addObject:item]; + } + } + + SentryEnvelope *envelopeWithoutAttachments = + [[SentryEnvelope alloc] initWithHeader:envelope.header items:envelopeItems]; + + [self.dispatchQueue dispatchAsyncWithBlock:^{ + NSURL *apiURL = [[NSURL alloc] initWithString:@"http://localhost:8969/stream"]; + + NSURLRequest *request = + [self.requestBuilder createEnvelopeRequest:envelopeWithoutAttachments + url:apiURL + didFailWithError:nil]; + + [self.requestManager + addRequest:request + completionHandler:^(NSHTTPURLResponse *_Nullable response, NSError *_Nullable error) { + + }]; + }]; +} + +- (SentryFlushResult)flush:(NSTimeInterval)timeout +{ + // Empty on purpose + return kSentryFlushResultSuccess; +} + +- (void)recordLostEvent:(SentryDataCategory)category reason:(SentryDiscardReason)reason +{ + // Empty on purpose +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/SentryTransportAdapter.m b/Sources/Sentry/SentryTransportAdapter.m index 829886da2a1..06c14609ee9 100644 --- a/Sources/Sentry/SentryTransportAdapter.m +++ b/Sources/Sentry/SentryTransportAdapter.m @@ -10,17 +10,18 @@ @interface SentryTransportAdapter () -@property (nonatomic, strong) id transport; +@property (nonatomic, strong) NSArray> *transports; @property (nonatomic, strong) SentryOptions *options; @end @implementation SentryTransportAdapter -- (instancetype)initWithTransport:(id)transport options:(SentryOptions *)options +- (instancetype)initWithTransports:(NSArray> *)transports + options:(SentryOptions *)options { if (self = [super init]) { - self.transport = transport; + self.transports = transports; self.options = options; } @@ -89,17 +90,23 @@ - (void)sendUserFeedback:(SentryUserFeedback *)userFeedback - (void)sendEnvelope:(SentryEnvelope *)envelope { - [self.transport sendEnvelope:envelope]; + for (id transport in self.transports) { + [transport sendEnvelope:envelope]; + } } - (void)recordLostEvent:(SentryDataCategory)category reason:(SentryDiscardReason)reason { - [self.transport recordLostEvent:category reason:reason]; + for (id transport in self.transports) { + [transport recordLostEvent:category reason:reason]; + } } - (void)flush:(NSTimeInterval)timeout { - [self.transport flush:timeout]; + for (id transport in self.transports) { + [transport flush:timeout]; + } } - (NSMutableArray *)buildEnvelopeItems:(SentryEvent *)event diff --git a/Sources/Sentry/SentryTransportFactory.m b/Sources/Sentry/SentryTransportFactory.m index caf47bdde30..e83862480cb 100644 --- a/Sources/Sentry/SentryTransportFactory.m +++ b/Sources/Sentry/SentryTransportFactory.m @@ -11,6 +11,7 @@ #import "SentryRateLimits.h" #import "SentryRetryAfterHeaderParser.h" +#import "SentrySpotlightTransport.h" #import "SentryTransport.h" #import @@ -23,8 +24,8 @@ @implementation SentryTransportFactory -+ (id)initTransport:(SentryOptions *)options - sentryFileManager:(SentryFileManager *)sentryFileManager ++ (NSArray> *)initTransports:(SentryOptions *)options + sentryFileManager:(SentryFileManager *)sentryFileManager { NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; @@ -51,13 +52,27 @@ @implementation SentryTransportFactory [[SentryDispatchQueueWrapper alloc] initWithName:"sentry-http-transport" attributes:attributes]; - return [[SentryHttpTransport alloc] initWithOptions:options - fileManager:sentryFileManager - requestManager:requestManager - requestBuilder:[[SentryNSURLRequestBuilder alloc] init] - rateLimits:rateLimits - envelopeRateLimit:envelopeRateLimit - dispatchQueueWrapper:dispatchQueueWrapper]; + SentryNSURLRequestBuilder *requestBuilder = [[SentryNSURLRequestBuilder alloc] init]; + + SentryHttpTransport *httpTransport = + [[SentryHttpTransport alloc] initWithOptions:options + fileManager:sentryFileManager + requestManager:requestManager + requestBuilder:requestBuilder + rateLimits:rateLimits + envelopeRateLimit:envelopeRateLimit + dispatchQueueWrapper:dispatchQueueWrapper]; + + if (options.enableSpotlight) { + SentrySpotlightTransport *spotlightTransport = + [[SentrySpotlightTransport alloc] initWithOptions:options + requestManager:requestManager + requestBuilder:requestBuilder + dispatchQueueWrapper:dispatchQueueWrapper]; + return @[ httpTransport, spotlightTransport ]; + } else { + return @[ httpTransport ]; + } } @end diff --git a/Sources/Sentry/include/SentryNSURLRequest.h b/Sources/Sentry/include/SentryNSURLRequest.h index 7b42695fc4f..5b6db8f50e3 100644 --- a/Sources/Sentry/include/SentryNSURLRequest.h +++ b/Sources/Sentry/include/SentryNSURLRequest.h @@ -18,6 +18,11 @@ NS_ASSUME_NONNULL_BEGIN andData:(NSData *)data didFailWithError:(NSError *_Nullable *_Nullable)error; +- (instancetype)initEnvelopeRequestWithURL:(NSURL *)url + andData:(NSData *)data + authHeader:(nullable NSString *)authHeader + didFailWithError:(NSError *_Nullable *_Nullable)error; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryNSURLRequestBuilder.h b/Sources/Sentry/include/SentryNSURLRequestBuilder.h index 1a46ea6a58b..26bc4d6174c 100644 --- a/Sources/Sentry/include/SentryNSURLRequestBuilder.h +++ b/Sources/Sentry/include/SentryNSURLRequestBuilder.h @@ -13,6 +13,10 @@ NS_ASSUME_NONNULL_BEGIN dsn:(SentryDsn *)dsn didFailWithError:(NSError *_Nullable *_Nullable)error; +- (NSURLRequest *)createEnvelopeRequest:(SentryEnvelope *)envelope + url:(NSURL *)url + didFailWithError:(NSError *_Nullable *_Nullable)error; + @end NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentrySpotlightTransport.h b/Sources/Sentry/include/SentrySpotlightTransport.h new file mode 100644 index 00000000000..37e5e2723f3 --- /dev/null +++ b/Sources/Sentry/include/SentrySpotlightTransport.h @@ -0,0 +1,19 @@ +#import "SentryDefines.h" +#import "SentryRequestManager.h" +#import "SentryTransport.h" + +@class SentryOptions, SentryDispatchQueueWrapper, SentryNSURLRequestBuilder; + +NS_ASSUME_NONNULL_BEGIN + +@interface SentrySpotlightTransport : NSObject +SENTRY_NO_INIT + +- (id)initWithOptions:(SentryOptions *)options + requestManager:(id)requestManager + requestBuilder:(SentryNSURLRequestBuilder *)requestBuilder + dispatchQueueWrapper:(SentryDispatchQueueWrapper *)dispatchQueueWrapper; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Sources/Sentry/include/SentryTransportAdapter.h b/Sources/Sentry/include/SentryTransportAdapter.h index 276e3e3adfe..d0a00f28062 100644 --- a/Sources/Sentry/include/SentryTransportAdapter.h +++ b/Sources/Sentry/include/SentryTransportAdapter.h @@ -16,7 +16,8 @@ NS_ASSUME_NONNULL_BEGIN @interface SentryTransportAdapter : NSObject SENTRY_NO_INIT -- (instancetype)initWithTransport:(id)transport options:(SentryOptions *)options; +- (instancetype)initWithTransports:(NSArray> *)transports + options:(SentryOptions *)options; - (void)sendEvent:(SentryEvent *)event session:(SentrySession *)session diff --git a/Sources/Sentry/include/SentryTransportFactory.h b/Sources/Sentry/include/SentryTransportFactory.h index 3170a2f0644..8f9c0213b0a 100644 --- a/Sources/Sentry/include/SentryTransportFactory.h +++ b/Sources/Sentry/include/SentryTransportFactory.h @@ -9,8 +9,8 @@ NS_ASSUME_NONNULL_BEGIN NS_SWIFT_NAME(TransportInitializer) @interface SentryTransportFactory : NSObject -+ (id)initTransport:(SentryOptions *)options - sentryFileManager:(SentryFileManager *)sentryFileManager; ++ (NSArray> *)initTransports:(SentryOptions *)options + sentryFileManager:(SentryFileManager *)sentryFileManager; @end diff --git a/Tests/SentryTests/SentryOptionsTest.m b/Tests/SentryTests/SentryOptionsTest.m index e9025655764..342085cc900 100644 --- a/Tests/SentryTests/SentryOptionsTest.m +++ b/Tests/SentryTests/SentryOptionsTest.m @@ -4,6 +4,7 @@ #import "SentrySDK.h" #import "SentryTests-Swift.h" #import +@import Nimble; @interface SentryOptionsTest : XCTestCase @@ -560,7 +561,8 @@ - (void)testNSNull_SetsDefaultValue @"failedRequestStatusCodes" : [NSNull null], @"enableTimeToFullDisplayTracing" : [NSNull null], @"enableTracing" : [NSNull null], - @"swiftAsyncStacktraces" : [NSNull null] + @"swiftAsyncStacktraces" : [NSNull null], + @"spotlightUrl" : [NSNull null] } didFailWithError:nil]; @@ -644,6 +646,8 @@ - (void)assertDefaultValues:(SentryOptions *)options XCTAssertNil(options.profilesSampleRate); XCTAssertNil(options.profilesSampler); #endif + + XCTAssertTrue([options.spotlightUrl isEqualToString:@"http://localhost:8969/stream"]); } - (void)testSetValidDsn @@ -1246,6 +1250,11 @@ - (void)testOptionsDebugDescription XCTAssert([debugDescription containsString:@"tracesSampler: <__NSGlobalBlock__: "]); } +- (void)testEnableSpotlight +{ + [self testBooleanField:@"enableSpotlight" defaultValue:NO]; +} + #pragma mark - Private - (void)assertArrayEquals:(NSArray *)expected actual:(NSArray *)actual From 177ffcf80ee053375239f7e3ad2aea8705291230 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Thu, 15 Feb 2024 12:02:05 +0100 Subject: [PATCH 02/10] ref: Add multiple transports to TransportAdapter Add the possibility to add multiple transports in the TransportAdapter, which is internal. This is a preparation for adding support for Spotlight. --- SentryTestUtils/TestClient.swift | 4 +- Sources/Sentry/SentryClient.m | 6 +-- Sources/Sentry/SentryTransportAdapter.m | 19 ++++++--- Sources/Sentry/SentryTransportFactory.m | 21 +++++----- .../Sentry/include/SentryTransportAdapter.h | 3 +- .../Sentry/include/SentryTransportFactory.h | 4 +- .../SentryCrashIntegrationTests.swift | 2 +- .../SentryTransportAdapterTests.swift | 39 +++++++++++-------- .../SentryTransportFactoryTests.swift | 5 ++- .../SentryTransportInitializerTests.swift | 9 +++-- Tests/SentryTests/SentryClientTests.swift | 2 +- Tests/SentryTests/SentrySDKTests.swift | 4 +- 12 files changed, 69 insertions(+), 49 deletions(-) diff --git a/SentryTestUtils/TestClient.swift b/SentryTestUtils/TestClient.swift index 7d5e9119727..b30faa95ced 100644 --- a/SentryTestUtils/TestClient.swift +++ b/SentryTestUtils/TestClient.swift @@ -2,11 +2,11 @@ import Foundation public class TestClient: SentryClient { public override init?(options: Options) { - super.init(options: options, fileManager: try! TestFileManager(options: options), deleteOldEnvelopeItems: false, transportAdapter: TestTransportAdapter(transport: TestTransport(), options: options)) + super.init(options: options, fileManager: try! TestFileManager(options: options), deleteOldEnvelopeItems: false, transportAdapter: TestTransportAdapter(transports: [TestTransport()], options: options)) } public override init?(options: Options, fileManager: SentryFileManager, deleteOldEnvelopeItems: Bool) { - super.init(options: options, fileManager: fileManager, deleteOldEnvelopeItems: deleteOldEnvelopeItems, transportAdapter: TestTransportAdapter(transport: TestTransport(), options: options)) + super.init(options: options, fileManager: fileManager, deleteOldEnvelopeItems: deleteOldEnvelopeItems, transportAdapter: TestTransportAdapter(transports: [TestTransport()], options: options)) } public override init(options: Options, fileManager: SentryFileManager, deleteOldEnvelopeItems: Bool, transportAdapter: SentryTransportAdapter) { diff --git a/Sources/Sentry/SentryClient.m b/Sources/Sentry/SentryClient.m index a93836b2372..d7435185011 100644 --- a/Sources/Sentry/SentryClient.m +++ b/Sources/Sentry/SentryClient.m @@ -98,11 +98,11 @@ - (instancetype)initWithOptions:(SentryOptions *)options fileManager:(SentryFileManager *)fileManager deleteOldEnvelopeItems:(BOOL)deleteOldEnvelopeItems { - id transport = [SentryTransportFactory initTransport:options - sentryFileManager:fileManager]; + NSArray> *transports = [SentryTransportFactory initTransports:options + sentryFileManager:fileManager]; SentryTransportAdapter *transportAdapter = - [[SentryTransportAdapter alloc] initWithTransport:transport options:options]; + [[SentryTransportAdapter alloc] initWithTransports:transports options:options]; return [self initWithOptions:options fileManager:fileManager diff --git a/Sources/Sentry/SentryTransportAdapter.m b/Sources/Sentry/SentryTransportAdapter.m index 829886da2a1..06c14609ee9 100644 --- a/Sources/Sentry/SentryTransportAdapter.m +++ b/Sources/Sentry/SentryTransportAdapter.m @@ -10,17 +10,18 @@ @interface SentryTransportAdapter () -@property (nonatomic, strong) id transport; +@property (nonatomic, strong) NSArray> *transports; @property (nonatomic, strong) SentryOptions *options; @end @implementation SentryTransportAdapter -- (instancetype)initWithTransport:(id)transport options:(SentryOptions *)options +- (instancetype)initWithTransports:(NSArray> *)transports + options:(SentryOptions *)options { if (self = [super init]) { - self.transport = transport; + self.transports = transports; self.options = options; } @@ -89,17 +90,23 @@ - (void)sendUserFeedback:(SentryUserFeedback *)userFeedback - (void)sendEnvelope:(SentryEnvelope *)envelope { - [self.transport sendEnvelope:envelope]; + for (id transport in self.transports) { + [transport sendEnvelope:envelope]; + } } - (void)recordLostEvent:(SentryDataCategory)category reason:(SentryDiscardReason)reason { - [self.transport recordLostEvent:category reason:reason]; + for (id transport in self.transports) { + [transport recordLostEvent:category reason:reason]; + } } - (void)flush:(NSTimeInterval)timeout { - [self.transport flush:timeout]; + for (id transport in self.transports) { + [transport flush:timeout]; + } } - (NSMutableArray *)buildEnvelopeItems:(SentryEvent *)event diff --git a/Sources/Sentry/SentryTransportFactory.m b/Sources/Sentry/SentryTransportFactory.m index caf47bdde30..c119346f2e7 100644 --- a/Sources/Sentry/SentryTransportFactory.m +++ b/Sources/Sentry/SentryTransportFactory.m @@ -23,8 +23,8 @@ @implementation SentryTransportFactory -+ (id)initTransport:(SentryOptions *)options - sentryFileManager:(SentryFileManager *)sentryFileManager ++ (NSArray> *)initTransports:(SentryOptions *)options + sentryFileManager:(SentryFileManager *)sentryFileManager { NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration ephemeralSessionConfiguration]; @@ -51,13 +51,16 @@ @implementation SentryTransportFactory [[SentryDispatchQueueWrapper alloc] initWithName:"sentry-http-transport" attributes:attributes]; - return [[SentryHttpTransport alloc] initWithOptions:options - fileManager:sentryFileManager - requestManager:requestManager - requestBuilder:[[SentryNSURLRequestBuilder alloc] init] - rateLimits:rateLimits - envelopeRateLimit:envelopeRateLimit - dispatchQueueWrapper:dispatchQueueWrapper]; + SentryHttpTransport *httpTransport = + [[SentryHttpTransport alloc] initWithOptions:options + fileManager:sentryFileManager + requestManager:requestManager + requestBuilder:[[SentryNSURLRequestBuilder alloc] init] + rateLimits:rateLimits + envelopeRateLimit:envelopeRateLimit + dispatchQueueWrapper:dispatchQueueWrapper]; + + return @[ httpTransport ]; } @end diff --git a/Sources/Sentry/include/SentryTransportAdapter.h b/Sources/Sentry/include/SentryTransportAdapter.h index 276e3e3adfe..d0a00f28062 100644 --- a/Sources/Sentry/include/SentryTransportAdapter.h +++ b/Sources/Sentry/include/SentryTransportAdapter.h @@ -16,7 +16,8 @@ NS_ASSUME_NONNULL_BEGIN @interface SentryTransportAdapter : NSObject SENTRY_NO_INIT -- (instancetype)initWithTransport:(id)transport options:(SentryOptions *)options; +- (instancetype)initWithTransports:(NSArray> *)transports + options:(SentryOptions *)options; - (void)sendEvent:(SentryEvent *)event session:(SentrySession *)session diff --git a/Sources/Sentry/include/SentryTransportFactory.h b/Sources/Sentry/include/SentryTransportFactory.h index 3170a2f0644..8f9c0213b0a 100644 --- a/Sources/Sentry/include/SentryTransportFactory.h +++ b/Sources/Sentry/include/SentryTransportFactory.h @@ -9,8 +9,8 @@ NS_ASSUME_NONNULL_BEGIN NS_SWIFT_NAME(TransportInitializer) @interface SentryTransportFactory : NSObject -+ (id)initTransport:(SentryOptions *)options - sentryFileManager:(SentryFileManager *)sentryFileManager; ++ (NSArray> *)initTransports:(SentryOptions *)options + sentryFileManager:(SentryFileManager *)sentryFileManager; @end diff --git a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift index 762972338bf..6c1bc61ffbd 100644 --- a/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift +++ b/Tests/SentryTests/Integrations/SentryCrash/SentryCrashIntegrationTests.swift @@ -248,7 +248,7 @@ class SentryCrashIntegrationTests: NotificationCenterTestCase { let transport = TestTransport() let client = SentryClient(options: fixture.options, fileManager: try TestFileManager(options: fixture.options), deleteOldEnvelopeItems: false) - Dynamic(client).transportAdapter = TestTransportAdapter(transport: transport, options: fixture.options) + Dynamic(client).transportAdapter = TestTransportAdapter(transports: [transport], options: fixture.options) hub.bindClient(client) delayNonBlocking(timeout: 0.01) diff --git a/Tests/SentryTests/Networking/SentryTransportAdapterTests.swift b/Tests/SentryTests/Networking/SentryTransportAdapterTests.swift index c2df58430e2..a270a838fc9 100644 --- a/Tests/SentryTests/Networking/SentryTransportAdapterTests.swift +++ b/Tests/SentryTests/Networking/SentryTransportAdapterTests.swift @@ -1,3 +1,4 @@ +import Nimble import Sentry import SentryTestUtils import XCTest @@ -6,13 +7,14 @@ class SentryTransportAdapterTests: XCTestCase { private class Fixture { - let transport = TestTransport() + let transport1 = TestTransport() + let transport2 = TestTransport() let options = Options() let faultyAttachment = Attachment(path: "") let attachment = Attachment(data: Data(), filename: "test.txt") var sut: SentryTransportAdapter { - return SentryTransportAdapter(transport: transport, options: options) + return SentryTransportAdapter(transports: [transport1, transport2], options: options) } } @@ -44,10 +46,10 @@ class SentryTransportAdapterTests: XCTestCase { SentryEnvelopeItem(session: session) ]) - assertEnvelope(expected: expectedEnvelope) + try assertEnvelope(expected: expectedEnvelope) } - func testSendFaultyAttachment_FaultyAttachmentGetsDropped() { + func testSendFaultyAttachment_FaultyAttachmentGetsDropped() throws { let event = TestData.event sut.send(event: event, traceContext: nil, attachments: [fixture.faultyAttachment, fixture.attachment]) @@ -56,26 +58,28 @@ class SentryTransportAdapterTests: XCTestCase { SentryEnvelopeItem(attachment: fixture.attachment, maxAttachmentSize: fixture.options.maxAttachmentSize)! ]) - assertEnvelope(expected: expectedEnvelope) + try assertEnvelope(expected: expectedEnvelope) } - func testSendUserFeedback_SendsUserFeedbackEnvelope() { + func testSendUserFeedback_SendsUserFeedbackEnvelope() throws { let userFeedback = TestData.userFeedback sut.send(userFeedback: userFeedback) let expectedEnvelope = SentryEnvelope(userFeedback: userFeedback) - assertEnvelope(expected: expectedEnvelope) + try assertEnvelope(expected: expectedEnvelope) } - private func assertEnvelope(expected: SentryEnvelope) { - XCTAssertEqual(1, fixture.transport.sentEnvelopes.count) - let actual = fixture.transport.sentEnvelopes.first! - XCTAssertNotNil(actual) + private func assertEnvelope(expected: SentryEnvelope) throws { + expect(self.fixture.transport1.sentEnvelopes.count) == 1 + expect(self.fixture.transport2.sentEnvelopes.count) == 1 - XCTAssertEqual(expected.header.eventId, actual.header.eventId) - XCTAssertEqual(expected.header.sdkInfo, actual.header.sdkInfo) - XCTAssertEqual(expected.items.count, actual.items.count) + let actual = fixture.transport1.sentEnvelopes.first! + expect(actual) != nil + + expect(expected.header.eventId) == actual.header.eventId + expect(expected.header.sdkInfo) == actual.header.sdkInfo + expect(expected.items.count) == actual.items.count expected.items.forEach { expectedItem in let expectedHeader = expectedItem.header @@ -84,15 +88,16 @@ class SentryTransportAdapterTests: XCTestCase { expectedHeader.contentType == expectedItem.header.contentType } - XCTAssertTrue(containsHeader, "Envelope doesn't contain item with type:\(expectedHeader.type).") + expect(containsHeader).to(beTrue(), description: "Envelope doesn't contain item with type:\(expectedHeader.type).") let containsData = actual.items.contains { actualItem in actualItem.data == expectedItem.data } - XCTAssertTrue(containsData, "Envelope data with type:\(expectedHeader.type) doesn't match.") + expect(containsData).to(beTrue(), description: "Envelope data with type:\(expectedHeader.type) doesn't match.") } - XCTAssertEqual(try SentrySerialization.data(with: expected), try SentrySerialization.data(with: actual)) + let actualSerialized = try SentrySerialization.data(with: actual) + expect(try SentrySerialization.data(with: expected)) == actualSerialized } } diff --git a/Tests/SentryTests/Networking/SentryTransportFactoryTests.swift b/Tests/SentryTests/Networking/SentryTransportFactoryTests.swift index 09c55f77d5f..1216c744037 100644 --- a/Tests/SentryTests/Networking/SentryTransportFactoryTests.swift +++ b/Tests/SentryTests/Networking/SentryTransportFactoryTests.swift @@ -19,8 +19,9 @@ class SentryTransportFactoryTests: XCTestCase { options.urlSessionDelegate = urlSessionDelegateSpy let fileManager = try! SentryFileManager(options: options, dispatchQueueWrapper: TestSentryDispatchQueueWrapper()) - let transport = TransportInitializer.initTransport(options, sentryFileManager: fileManager) - let requestManager = Dynamic(transport).requestManager.asObject as! SentryQueueableRequestManager + let transports = TransportInitializer.initTransports(options, sentryFileManager: fileManager) + let httpTransport = transports.first + let requestManager = Dynamic(httpTransport).requestManager.asObject as! SentryQueueableRequestManager let imgUrl = URL(string: "https://github.com")! let request = URLRequest(url: imgUrl) diff --git a/Tests/SentryTests/Networking/SentryTransportInitializerTests.swift b/Tests/SentryTests/Networking/SentryTransportInitializerTests.swift index a2b2755b341..53acba9eb40 100644 --- a/Tests/SentryTests/Networking/SentryTransportInitializerTests.swift +++ b/Tests/SentryTests/Networking/SentryTransportInitializerTests.swift @@ -1,3 +1,4 @@ +import Nimble @testable import Sentry import SentryTestUtils import XCTest @@ -17,9 +18,11 @@ class SentryTransportInitializerTests: XCTestCase { func testDefault() throws { let options = try Options(dict: ["dsn": SentryTransportInitializerTests.dsnAsString]) + + let result = TransportInitializer.initTransports(options, sentryFileManager: fileManager) + expect(result.count) == 1 - let result = TransportInitializer.initTransport(options, sentryFileManager: fileManager) - - XCTAssertTrue(result.isKind(of: SentryHttpTransport.self)) + let firstTransport = result.first + expect(firstTransport?.isKind(of: SentryHttpTransport.self)) == true } } diff --git a/Tests/SentryTests/SentryClientTests.swift b/Tests/SentryTests/SentryClientTests.swift index fcc7afb8e17..8cccc5efde7 100644 --- a/Tests/SentryTests/SentryClientTests.swift +++ b/Tests/SentryTests/SentryClientTests.swift @@ -60,7 +60,7 @@ class SentryClientTest: XCTestCase { transaction = Transaction(trace: trace, children: []) transport = TestTransport() - transportAdapter = TestTransportAdapter(transport: transport, options: options) + transportAdapter = TestTransportAdapter(transports: [transport], options: options) crashWrapper.internalFreeMemorySize = 123_456 crashWrapper.internalAppMemorySize = 234_567 diff --git a/Tests/SentryTests/SentrySDKTests.swift b/Tests/SentryTests/SentrySDKTests.swift index ed7fb639975..ef58f48a969 100644 --- a/Tests/SentryTests/SentrySDKTests.swift +++ b/Tests/SentryTests/SentrySDKTests.swift @@ -668,7 +668,7 @@ class SentrySDKTests: XCTestCase { let transport = TestTransport() let client = SentryClient(options: fixture.options, fileManager: try TestFileManager(options: fixture.options), deleteOldEnvelopeItems: false) - Dynamic(client).transportAdapter = TestTransportAdapter(transport: transport, options: fixture.options) + Dynamic(client).transportAdapter = TestTransportAdapter(transports: [transport], options: fixture.options) SentrySDK.currentHub().bindClient(client) SentrySDK.close() @@ -683,7 +683,7 @@ class SentrySDKTests: XCTestCase { let transport = TestTransport() let client = SentryClient(options: fixture.options, fileManager: try TestFileManager(options: fixture.options), deleteOldEnvelopeItems: false) - Dynamic(client).transportAdapter = TestTransportAdapter(transport: transport, options: fixture.options) + Dynamic(client).transportAdapter = TestTransportAdapter(transports: [transport], options: fixture.options) SentrySDK.currentHub().bindClient(client) let flushTimeout = 10.0 From 456c7280e948c8f6d1363498b540bb5006ff093e Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Thu, 15 Feb 2024 14:23:39 +0100 Subject: [PATCH 03/10] changelog and cleanup --- CHANGELOG.md | 5 +++++ Sources/Sentry/Public/SentryOptions.h | 2 +- Sources/Sentry/SentryNSURLRequest.m | 21 ++++++------------- .../SentryTransportFactoryTests.swift | 16 ++++++++++++++ 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 842aff2a95d..9e35310e107 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +### Features + +- Add support for Sentry [Spotlight](https://spotlightjs.com/) (#3642), which is basically Sentry +for development. Read our [blog post](https://blog.sentry.io/sentry-for-development/) to find out more. + ### Improvements - Cache installationID async to avoid file IO on the main thread when starting the SDK (#3601) diff --git a/Sources/Sentry/Public/SentryOptions.h b/Sources/Sentry/Public/SentryOptions.h index 4f085b5dd32..2d6c6f8e643 100644 --- a/Sources/Sentry/Public/SentryOptions.h +++ b/Sources/Sentry/Public/SentryOptions.h @@ -529,7 +529,7 @@ NS_SWIFT_NAME(Options) * Whether to enable Spotlight for local development. For more information see * https://spotlightjs.com/. * - * @note Only set this option to `true` while developing, not in production! + * @note Only set this option to @c YES while developing, not in production! */ @property (nonatomic, assign) BOOL enableSpotlight; diff --git a/Sources/Sentry/SentryNSURLRequest.m b/Sources/Sentry/SentryNSURLRequest.m index 47f6a0fa4d6..be6bc9b3dae 100644 --- a/Sources/Sentry/SentryNSURLRequest.m +++ b/Sources/Sentry/SentryNSURLRequest.m @@ -70,21 +70,12 @@ - (_Nullable instancetype)initEnvelopeRequestWithDsn:(SentryDsn *)dsn didFailWithError:(NSError *_Nullable *_Nullable)error { NSURL *apiURL = [dsn getEnvelopeEndpoint]; - self = [super initWithURL:apiURL - cachePolicy:NSURLRequestReloadIgnoringLocalCacheData - timeoutInterval:SentryRequestTimeout]; - if (self) { - NSString *authHeader = newAuthHeader(dsn.url); - - self.HTTPMethod = @"POST"; - [self setValue:authHeader forHTTPHeaderField:@"X-Sentry-Auth"]; - [self setValue:@"application/x-sentry-envelope" forHTTPHeaderField:@"Content-Type"]; - [self setValue:SentryMeta.sdkName forHTTPHeaderField:@"User-Agent"]; - [self setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"]; - self.HTTPBody = [data sentry_gzippedWithCompressionLevel:-1 error:error]; - } + NSString *authHeader = newAuthHeader(dsn.url); - return self; + return [self initEnvelopeRequestWithURL:apiURL + andData:data + authHeader:authHeader + didFailWithError:error]; } - (instancetype)initEnvelopeRequestWithURL:(NSURL *)url @@ -98,7 +89,7 @@ - (instancetype)initEnvelopeRequestWithURL:(NSURL *)url if (self) { self.HTTPMethod = @"POST"; - if (authHeader) { + if (authHeader != nil) { [self setValue:authHeader forHTTPHeaderField:@"X-Sentry-Auth"]; } [self setValue:@"application/x-sentry-envelope" forHTTPHeaderField:@"Content-Type"]; diff --git a/Tests/SentryTests/Networking/SentryTransportFactoryTests.swift b/Tests/SentryTests/Networking/SentryTransportFactoryTests.swift index 1216c744037..c946f850c42 100644 --- a/Tests/SentryTests/Networking/SentryTransportFactoryTests.swift +++ b/Tests/SentryTests/Networking/SentryTransportFactoryTests.swift @@ -1,3 +1,4 @@ +import Nimble import Sentry import SentryTestUtils import XCTest @@ -29,4 +30,19 @@ class SentryTransportFactoryTests: XCTestCase { requestManager.add(request) { _, _ in /* We don't care about the result */ } wait(for: [expect], timeout: 10) } + + func testShouldReturnTwoTransports_WhenSpotlightEnabled() throws { + let options = Options() + options.enableSpotlight = true + let transports = TransportInitializer.initTransports(options, sentryFileManager: try SentryFileManager(options: options)) + + expect(transports.contains { + $0.isKind(of: SentrySpotlightTransport.self) + }) == true + + expect(transports.contains { + $0.isKind(of: SentryHttpTransport.self) + }) == true + } + } From 754ef901afdb91ca63449989d6250a66c3a95fb6 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Thu, 15 Feb 2024 14:25:15 +0100 Subject: [PATCH 04/10] enable onl for simulator --- Samples/iOS-Swift/iOS-Swift/AppDelegate.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift index 46f89b0be3f..f101146c065 100644 --- a/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift +++ b/Samples/iOS-Swift/iOS-Swift/AppDelegate.swift @@ -55,8 +55,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { options.sessionTrackingIntervalMillis = 5_000 options.attachScreenshot = true options.attachViewHierarchy = true - options.enableSpotlight = true + #if targetEnvironment(simulator) + options.enableSpotlight = true options.environment = "test-app" #else options.environment = "device-tests" From 9e3463b0d4fc62f410293da2195565de4f2f47ea Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Thu, 15 Feb 2024 14:26:50 +0100 Subject: [PATCH 05/10] more cleanpu --- Tests/SentryTests/Networking/SentrySpotlightTransportTests.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/SentryTests/Networking/SentrySpotlightTransportTests.swift b/Tests/SentryTests/Networking/SentrySpotlightTransportTests.swift index 3fa37f68f09..872aaab16d4 100644 --- a/Tests/SentryTests/Networking/SentrySpotlightTransportTests.swift +++ b/Tests/SentryTests/Networking/SentrySpotlightTransportTests.swift @@ -34,7 +34,6 @@ final class SentrySpotlightTransportTests: XCTestCase { let attachmentEnvelopeItem = try XCTUnwrap( SentryEnvelopeItem(attachment: TestData.dataAttachment, maxAttachmentSize: 5 * 1_024 * 1_024)) let envelopeItems = if withAttachment { - [SentryEnvelopeItem(event: event), attachmentEnvelopeItem] } else { [SentryEnvelopeItem(event: event)] From 381e8bd816b43974a88a6dc0c43f452ac9c3ac1b Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Thu, 15 Feb 2024 14:52:56 +0100 Subject: [PATCH 06/10] try to fix tests --- .../Networking/SentrySpotlightTransportTests.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Tests/SentryTests/Networking/SentrySpotlightTransportTests.swift b/Tests/SentryTests/Networking/SentrySpotlightTransportTests.swift index 872aaab16d4..4d84abe5c68 100644 --- a/Tests/SentryTests/Networking/SentrySpotlightTransportTests.swift +++ b/Tests/SentryTests/Networking/SentrySpotlightTransportTests.swift @@ -33,10 +33,11 @@ final class SentrySpotlightTransportTests: XCTestCase { let attachmentEnvelopeItem = try XCTUnwrap( SentryEnvelopeItem(attachment: TestData.dataAttachment, maxAttachmentSize: 5 * 1_024 * 1_024)) - let envelopeItems = if withAttachment { - [SentryEnvelopeItem(event: event), attachmentEnvelopeItem] + var envelopeItems: [SentryEnvelopeItem] + if withAttachment { + envelopeItems = [SentryEnvelopeItem(event: event), attachmentEnvelopeItem] } else { - [SentryEnvelopeItem(event: event)] + envelopeItems = [SentryEnvelopeItem(event: event)] } return SentryEnvelope(id: event.eventId, items: envelopeItems) From a8b14899deea6241f32d2f768ed45b984324b26b Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Mon, 19 Feb 2024 09:13:56 +0100 Subject: [PATCH 07/10] add release build warning --- Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj | 1 + Sentry.xcodeproj/project.pbxproj | 6 +++++- Sources/Sentry/SentryOptions.m | 11 +++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj b/Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj index b722db68955..0b2fc7e7a32 100644 --- a/Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj +++ b/Samples/iOS-Swift/iOS-Swift.xcodeproj/project.pbxproj @@ -1219,6 +1219,7 @@ ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = "RELEASE=1"; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; diff --git a/Sentry.xcodeproj/project.pbxproj b/Sentry.xcodeproj/project.pbxproj index e47b1cb7372..18a239c32b9 100644 --- a/Sentry.xcodeproj/project.pbxproj +++ b/Sentry.xcodeproj/project.pbxproj @@ -4834,6 +4834,7 @@ ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = "RELEASE=1"; GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -5698,7 +5699,10 @@ ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = "SENTRY_NO_UIKIT=1"; + GCC_PREPROCESSOR_DEFINITIONS = ( + "SENTRY_NO_UIKIT=1", + "RELEASE=1", + ); GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; GCC_TREAT_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; diff --git a/Sources/Sentry/SentryOptions.m b/Sources/Sentry/SentryOptions.m index ea32ebdc15f..296718bcea7 100644 --- a/Sources/Sentry/SentryOptions.m +++ b/Sources/Sentry/SentryOptions.m @@ -702,6 +702,17 @@ - (void)setEnablePreWarmedAppStartTracing:(BOOL)enablePreWarmedAppStartTracing #endif // SENTRY_UIKIT_AVAILABLE +- (void)setEnableSpotlight:(BOOL)value +{ + _enableSpotlight = value; +#if defined(RELEASE) + if (value) { + SENTRY_LOG_WARN(@"Enabling Spotlight for a release build. We only recommend running " + @"Spotlight for local development"); + } +#endif // defined(RELEASE) +} + #if defined(DEBUG) || defined(TEST) || defined(TESTCI) - (NSString *)debugDescription { From 715e697dfc621b2dc0afc8ae600e9470e8a79153 Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Mon, 19 Feb 2024 09:21:16 +0100 Subject: [PATCH 08/10] spotlightUrl tests --- Tests/SentryTests/SentryOptionsTest.m | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/SentryTests/SentryOptionsTest.m b/Tests/SentryTests/SentryOptionsTest.m index 9e95545bea6..088b09f21f3 100644 --- a/Tests/SentryTests/SentryOptionsTest.m +++ b/Tests/SentryTests/SentryOptionsTest.m @@ -1264,6 +1264,18 @@ - (void)testEnableSpotlight [self testBooleanField:@"enableSpotlight" defaultValue:NO]; } +- (void)testSpotlightUrl +{ + SentryOptions *options = [self getValidOptions:@{ @"spotlightUrl" : @"http://localhost:1010" }]; + XCTAssertEqualObjects(options.spotlightUrl, @"http://localhost:1010"); + + SentryOptions *options2 = [self getValidOptions:@{ @"spotlightUrl" : @"" }]; + XCTAssertEqualObjects(options2.spotlightUrl, @""); + + SentryOptions *options3 = [self getValidOptions:@{ @"spotlightUrl" : @2 }]; + XCTAssertEqualObjects(options3.spotlightUrl, @"http://localhost:8969/stream"); +} + #pragma mark - Private - (void)assertArrayEquals:(NSArray *)expected actual:(NSArray *)actual From fbc659cc70a776567bc0f6d4e5a65549dab4261f Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Mon, 19 Feb 2024 09:26:29 +0100 Subject: [PATCH 09/10] remove async --- Sources/Sentry/SentrySpotlightTransport.m | 56 +++++++++++------------ 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/Sources/Sentry/SentrySpotlightTransport.m b/Sources/Sentry/SentrySpotlightTransport.m index ca4b13916e6..a4e3754c077 100644 --- a/Sources/Sentry/SentrySpotlightTransport.m +++ b/Sources/Sentry/SentrySpotlightTransport.m @@ -51,40 +51,38 @@ - (void)sendEnvelope:(SentryEnvelope *)envelope return; } - [self.dispatchQueue dispatchAsyncWithBlock:^{ - // Spotlight can only handle the following envelope items. - // Not removing them leads to an error and events won't get displayed. - NSMutableArray *allowedEnvelopeItems = [NSMutableArray new]; - for (SentryEnvelopeItem *item in envelope.items) { - if ([item.header.type isEqualToString:SentryEnvelopeItemTypeEvent]) { - [allowedEnvelopeItems addObject:item]; - } - if ([item.header.type isEqualToString:SentryEnvelopeItemTypeTransaction]) { - [allowedEnvelopeItems addObject:item]; - } + // Spotlight can only handle the following envelope items. + // Not removing them leads to an error and events won't get displayed. + NSMutableArray *allowedEnvelopeItems = [NSMutableArray new]; + for (SentryEnvelopeItem *item in envelope.items) { + if ([item.header.type isEqualToString:SentryEnvelopeItemTypeEvent]) { + [allowedEnvelopeItems addObject:item]; } + if ([item.header.type isEqualToString:SentryEnvelopeItemTypeTransaction]) { + [allowedEnvelopeItems addObject:item]; + } + } - SentryEnvelope *envelopeToSend = - [[SentryEnvelope alloc] initWithHeader:envelope.header items:allowedEnvelopeItems]; + SentryEnvelope *envelopeToSend = [[SentryEnvelope alloc] initWithHeader:envelope.header + items:allowedEnvelopeItems]; - NSError *requestError = nil; - NSURLRequest *request = [self.requestBuilder createEnvelopeRequest:envelopeToSend - url:self.apiURL - didFailWithError:&requestError]; + NSError *requestError = nil; + NSURLRequest *request = [self.requestBuilder createEnvelopeRequest:envelopeToSend + url:self.apiURL + didFailWithError:&requestError]; - if (requestError) { - SENTRY_LOG_ERROR(@"Unable to build envelope request with error %@", requestError); - return; - } + if (requestError) { + SENTRY_LOG_ERROR(@"Unable to build envelope request with error %@", requestError); + return; + } - [self.requestManager - addRequest:request - completionHandler:^(NSHTTPURLResponse *_Nullable response, NSError *_Nullable error) { - if (error) { - SENTRY_LOG_ERROR(@"Error while performing request %@", requestError); - } - }]; - }]; + [self.requestManager + addRequest:request + completionHandler:^(NSHTTPURLResponse *_Nullable response, NSError *_Nullable error) { + if (error) { + SENTRY_LOG_ERROR(@"Error while performing request %@", requestError); + } + }]; } - (SentryFlushResult)flush:(NSTimeInterval)timeout From c29978fe8fcd6ae93b7244a3ac852ba733f2afea Mon Sep 17 00:00:00 2001 From: Philipp Hofmann Date: Mon, 19 Feb 2024 09:49:34 +0100 Subject: [PATCH 10/10] log message --- Sources/Sentry/SentryOptions.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Sentry/SentryOptions.m b/Sources/Sentry/SentryOptions.m index 296718bcea7..a1b6f0958a5 100644 --- a/Sources/Sentry/SentryOptions.m +++ b/Sources/Sentry/SentryOptions.m @@ -707,8 +707,8 @@ - (void)setEnableSpotlight:(BOOL)value _enableSpotlight = value; #if defined(RELEASE) if (value) { - SENTRY_LOG_WARN(@"Enabling Spotlight for a release build. We only recommend running " - @"Spotlight for local development"); + SENTRY_LOG_WARN(@"Enabling Spotlight for a release build. We recommend running Spotlight " + @"only for local development."); } #endif // defined(RELEASE) }