Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Allow starting the SDK with an initial scope #2982

Merged
merged 13 commits into from
May 4, 2023
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

### Features

- Allow starting the SDK with an initial scope (#2982)
- Swift Error Names (#2960)

```Swift
Expand Down
10 changes: 9 additions & 1 deletion Sources/Sentry/Public/SentryOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

NS_ASSUME_NONNULL_BEGIN

@class SentryDsn, SentryMeasurementValue, SentryHttpStatusCodeRange;
@class SentryDsn, SentryMeasurementValue, SentryHttpStatusCodeRange, SentryScope;

NS_SWIFT_NAME(Options)
@interface SentryOptions : NSObject
Expand Down Expand Up @@ -191,6 +191,14 @@ NS_SWIFT_NAME(Options)
*/
@property (nonatomic, assign) BOOL enableAutoPerformanceTracing;

/**
* A block that configures the initial scope when starting the SDK.
* @discussion The block receives a suggested default scope. You can either
* configure and return this, or create your own scope instead.
* @note The default simply returns the passed in scope.
*/
@property (nonatomic) SentryScope *(^initialScope)(SentryScope *);

#if SENTRY_HAS_UIKIT
/**
* When enabled, the SDK tracks performance for UIViewController subclasses.
Expand Down
7 changes: 7 additions & 0 deletions Sources/Sentry/SentryOptions.m
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#import "SentryLog.h"
#import "SentryMeta.h"
#import "SentrySDK.h"
#import "SentryScope.h"

@interface
SentryOptions ()
Expand Down Expand Up @@ -77,6 +78,8 @@ - (instancetype)init
self.environment = kSentryDefaultEnvironment;
self.enableTimeToFullDisplay = NO;

self.initialScope = ^SentryScope *(SentryScope *scope) { return scope; };

_enableTracing = NO;
_enableTracingManual = NO;
#if SENTRY_HAS_UIKIT
Expand Down Expand Up @@ -336,6 +339,10 @@ - (BOOL)validateOptions:(NSDictionary<NSString *, id> *)options
[self setBool:options[@"enableTimeToFullDisplay"]
block:^(BOOL value) { self->_enableTimeToFullDisplay = value; }];

if ([self isBlock:options[@"initialScope"]]) {
self.initialScope = options[@"initialScope"];
}

#if SENTRY_HAS_UIKIT
[self setBool:options[@"enableUIViewControllerTracing"]
block:^(BOOL value) { self->_enableUIViewControllerTracing = value; }];
Expand Down
3 changes: 2 additions & 1 deletion Sources/Sentry/SentrySDK.m
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,10 @@ + (void)startWithOptions:(SentryOptions *)options
[newClient.fileManager moveAppStateToPreviousAppState];
[newClient.fileManager moveBreadcrumbsToPreviousBreadcrumbs];

SentryScope *scope = options.initialScope([[SentryScope alloc] initWithMaxBreadcrumbs:options.maxBreadcrumbs]);
// The Hub needs to be initialized with a client so that closing a session
// can happen.
[SentrySDK setCurrentHub:[[SentryHub alloc] initWithClient:newClient andScope:nil]];
[SentrySDK setCurrentHub:[[SentryHub alloc] initWithClient:newClient andScope:scope]];
SENTRY_LOG_DEBUG(@"SDK initialized! Version: %@", SentryMeta.versionString);
[SentrySDK installIntegrations];
}
Expand Down
12 changes: 12 additions & 0 deletions Tests/SentryTests/SentryOptionsTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -1144,6 +1144,18 @@ - (void)testDefaultInAppExcludes
XCTAssertEqualObjects(@[], options.inAppExcludes);
}

- (void)testDefaultInitialScope {
SentryOptions *options = [self getValidOptions:@{}];
SentryScope *scope = [[SentryScope alloc] init];
XCTAssertIdentical(scope, options.initialScope(scope));
}

- (void)testInitialScope {
SentryScope *(^initialScope)(SentryScope *) = ^SentryScope * (SentryScope *scope) { return scope; };
SentryOptions *options = [self getValidOptions:@{ @"initialScope": initialScope }];
XCTAssertIdentical(initialScope, options.initialScope);
}

- (SentryOptions *)getValidOptions:(NSDictionary<NSString *, id> *)dict
{
NSError *error = nil;
Expand Down
15 changes: 15 additions & 0 deletions Tests/SentryTests/SentrySDKTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,21 @@ class SentrySDKTests: XCTestCase {

XCTAssertTrue(wasBeforeSendCalled, "beforeSend was not called.")
}

func testStartWithScope() {
let scope = Scope()
scope.setUser(User(userId: "me"))
SentrySDK.start { options in
options.dsn = SentrySDKTests.dsnAsString
options.maxBreadcrumbs = 123
options.initialScope = { suggested in
XCTAssertEqual(123, Dynamic(suggested).maxBreadcrumbs)
return scope
}
}
XCTAssertEqual("me", SentrySDK.currentHub().scope.userObject?.userId)
XCTAssertIdentical(scope, SentrySDK.currentHub().scope)
}

func testCrashedLastRun() {
XCTAssertEqual(SentryCrash.sharedInstance().crashedLastLaunch, SentrySDK.crashedLastRun)
Expand Down