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

ref: Moving session replay public API and default quality #4326

Merged
merged 17 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

- Added `thermal_state` to device context (#4305)

### Refactoring

- Moved session replay API to `SentrySDK.replay` (#4326)
- Changed default session replay quality to `medium` (#4326)

### Fixes

- Resumes replay when the app becomes active (#4303)
Expand Down
8 changes: 8 additions & 0 deletions Sentry.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -867,6 +867,8 @@
D88817DA26D72AB800BF2251 /* SentryTraceContext.h in Headers */ = {isa = PBXBuildFile; fileRef = D88817D926D72AB800BF2251 /* SentryTraceContext.h */; settings = {ATTRIBUTES = (Public, ); }; };
D88817DD26D72BA500BF2251 /* SentryTraceStateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D88817DB26D72B7B00BF2251 /* SentryTraceStateTests.swift */; };
D8918B222849FA6D00701F9A /* SentrySDKIntegrationTestsBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8918B212849FA6D00701F9A /* SentrySDKIntegrationTestsBase.swift */; };
D8A3649C2C91AA3300AC569B /* SentryReplayApi.m in Sources */ = {isa = PBXBuildFile; fileRef = D8A3649B2C91AA3300AC569B /* SentryReplayApi.m */; };
D8A3649D2C91AA3300AC569B /* SentryReplayApi.h in Headers */ = {isa = PBXBuildFile; fileRef = D8A3649A2C91AA3300AC569B /* SentryReplayApi.h */; settings = {ATTRIBUTES = (Public, ); }; };
D8AB40DB2806EC1900E5E9F7 /* SentryScreenshotIntegration.h in Headers */ = {isa = PBXBuildFile; fileRef = D8AB40DA2806EC1900E5E9F7 /* SentryScreenshotIntegration.h */; };
D8ACE3C72762187200F5A213 /* SentryNSDataSwizzling.m in Sources */ = {isa = PBXBuildFile; fileRef = D8ACE3C42762187200F5A213 /* SentryNSDataSwizzling.m */; };
D8ACE3C82762187200F5A213 /* SentryNSDataTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = D8ACE3C52762187200F5A213 /* SentryNSDataTracker.m */; };
Expand Down Expand Up @@ -1936,6 +1938,8 @@
D88817DB26D72B7B00BF2251 /* SentryTraceStateTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryTraceStateTests.swift; sourceTree = "<group>"; };
D88D25E92B8E0BAC0073C3D5 /* module.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = module.modulemap; sourceTree = "<group>"; };
D8918B212849FA6D00701F9A /* SentrySDKIntegrationTestsBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentrySDKIntegrationTestsBase.swift; sourceTree = "<group>"; };
D8A3649A2C91AA3300AC569B /* SentryReplayApi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryReplayApi.h; path = Public/SentryReplayApi.h; sourceTree = "<group>"; };
D8A3649B2C91AA3300AC569B /* SentryReplayApi.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryReplayApi.m; sourceTree = "<group>"; };
D8AB40DA2806EC1900E5E9F7 /* SentryScreenshotIntegration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SentryScreenshotIntegration.h; path = include/SentryScreenshotIntegration.h; sourceTree = "<group>"; };
D8ACE3C42762187200F5A213 /* SentryNSDataSwizzling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryNSDataSwizzling.m; sourceTree = "<group>"; };
D8ACE3C52762187200F5A213 /* SentryNSDataTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SentryNSDataTracker.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3645,6 +3649,8 @@
D820CDB62BB1895F00BA339D /* SentrySessionReplayIntegration.m */,
D82859412C3E753C009A28AA /* SentrySessionReplaySyncC.h */,
D82859422C3E753C009A28AA /* SentrySessionReplaySyncC.c */,
D8A3649A2C91AA3300AC569B /* SentryReplayApi.h */,
D8A3649B2C91AA3300AC569B /* SentryReplayApi.m */,
);
name = SessionReplay;
sourceTree = "<group>";
Expand Down Expand Up @@ -4209,6 +4215,7 @@
63FE70ED20DA4C1000CDBAE8 /* SentryCrashMonitor_NSException.h in Headers */,
7BA61CB4247BC3EB00C130A8 /* SentryCrashBinaryImageProvider.h in Headers */,
63FE713D20DA4C1100CDBAE8 /* SentryAsyncSafeLog.h in Headers */,
D8A3649D2C91AA3300AC569B /* SentryReplayApi.h in Headers */,
15E0A8E1240C41CE00F044E3 /* SentryEnvelope.h in Headers */,
630435FE1EBCA9D900C4D3FA /* SentryNSURLRequest.h in Headers */,
7BC852392458830A005A70F0 /* SentryEnvelopeItemType.h in Headers */,
Expand Down Expand Up @@ -4738,6 +4745,7 @@
D8F016B62B962548007B9AFB /* StringExtensions.swift in Sources */,
7B4E23C2251A2C2B00060D68 /* SentrySessionCrashedHandler.m in Sources */,
9286059729A5098900F96038 /* SentryGeo.m in Sources */,
D8A3649C2C91AA3300AC569B /* SentryReplayApi.m in Sources */,
7B42C48227E08F4B009B58C2 /* SentryDependencyContainer.m in Sources */,
639FCFAD1EBC811400778193 /* SentryUser.m in Sources */,
62B558B02C6B9C3C00C34FEC /* SentryFramesDelayResult.swift in Sources */,
Expand Down
1 change: 1 addition & 0 deletions Sources/Sentry/Public/Sentry.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ FOUNDATION_EXPORT const unsigned char SentryVersionString[];
# import <Sentry/SentryMessage.h>
# import <Sentry/SentryNSError.h>
# import <Sentry/SentryOptions.h>
# import <Sentry/SentryReplayApi.h>
# import <Sentry/SentryRequest.h>
# import <Sentry/SentrySDK.h>
# import <Sentry/SentrySampleDecision.h>
Expand Down
50 changes: 50 additions & 0 deletions Sources/Sentry/Public/SentryReplayApi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#import <Foundation/Foundation.h>

#if __has_include(<Sentry/SentryDefines.h>)
# import <Sentry/SentryDefines.h>
#else
# import <SentryWithoutUIKit/SentryDefines.h>
#endif

#if SENTRY_TARGET_REPLAY_SUPPORTED

@class UIView;

NS_ASSUME_NONNULL_BEGIN

@interface SentryReplayApi : NSObject

/**
* Marks this view to be redacted during replays.
*
* @warning This is an experimental feature and may still have bugs.
*/
- (void)redactView:(UIView *)view NS_SWIFT_NAME(redactView(_:));

/**
* Marks this view to be ignored during redact step of session replay.
* All its content will be visible in the replay.
*
* @warning This is an experimental feature and may still have bugs.
*/
- (void)ignoreView:(UIView *)view NS_SWIFT_NAME(ignoreView(_:));

/**
* Pauses the replay.
*
* @warning This is an experimental feature and may still have bugs.
*/
- (void)pause;

/**
* Resumes the ongoing replay.
*
* @warning This is an experimental feature and may still have bugs.
*/
- (void)resume;

@end

NS_ASSUME_NONNULL_END

#endif
27 changes: 8 additions & 19 deletions Sources/Sentry/Public/SentrySDK.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
SentryUserFeedback, SentryTransactionContext;
@class SentryMetricsAPI;
@class UIView;
@class SentryReplayApi;

NS_ASSUME_NONNULL_BEGIN

Expand All @@ -28,6 +29,13 @@ SENTRY_NO_INIT

@property (class, nonatomic, readonly) SentryMetricsAPI *metrics;

#if SENTRY_TARGET_REPLAY_SUPPORTED
/**
* API to control session replay
*/
@property (class, nonatomic, readonly) SentryReplayApi *replay;
#endif

/**
* Inits and configures Sentry (SentryHub, SentryClient) and sets up all integrations. Make sure to
* set a valid DSN.
Expand Down Expand Up @@ -334,25 +342,6 @@ SENTRY_NO_INIT
*/
+ (void)close;

#if SENTRY_TARGET_REPLAY_SUPPORTED

/**
* @warning This is an experimental feature and may still have bugs.
*
* Marks this view to be redacted during replays.
*/
+ (void)replayRedactView:(UIView *)view;

/**
* @warning This is an experimental feature and may still have bugs.
*
* Marks this view to be ignored during redact step
* of session replay. All its content will be visible in the replay.
*/
+ (void)replayIgnoreView:(UIView *)view;

#endif

#if SENTRY_TARGET_PROFILING_SUPPORTED
/**
* Start a new continuous profiling session if one is not already running.
Expand Down
1 change: 1 addition & 0 deletions Sources/Sentry/Public/SentryWithoutUIKit.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ FOUNDATION_EXPORT const unsigned char SentryVersionString[];
# import <SentryWithoutUIKit/SentryMessage.h>
# import <SentryWithoutUIKit/SentryNSError.h>
# import <SentryWithoutUIKit/SentryOptions.h>
# import <SentryWithoutUIKit/SentryReplayApi.h>
# import <SentryWithoutUIKit/SentryRequest.h>
# import <SentryWithoutUIKit/SentrySDK.h>
# import <SentryWithoutUIKit/SentrySampleDecision.h>
Expand Down
39 changes: 39 additions & 0 deletions Sources/Sentry/SentryReplayApi.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#import "SentryReplayApi.h"

#if SENTRY_TARGET_REPLAY_SUPPORTED

# import "SentryHub+Private.h"
# import "SentrySDK+Private.h"
# import "SentrySessionReplayIntegration.h"
# import "SentrySwift.h"
# import <UIKit/UIKit.h>

@implementation SentryReplayApi

- (void)redactView:(UIView *)view
{
[SentryRedactViewHelper redactView:view];
}

- (void)ignoreView:(UIView *)view
{
[SentryRedactViewHelper ignoreView:view];
}

- (void)pause
{
SentrySessionReplayIntegration *replayIntegration =
[SentrySDK.currentHub getInstalledIntegration:SentrySessionReplayIntegration.class];
[replayIntegration pause];
}

- (void)resume
{
SentrySessionReplayIntegration *replayIntegration =
[SentrySDK.currentHub getInstalledIntegration:SentrySessionReplayIntegration.class];
[replayIntegration resume];
}

@end

#endif
23 changes: 10 additions & 13 deletions Sources/Sentry/SentrySDK.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#import "SentryMeta.h"
#import "SentryOptions+Private.h"
#import "SentryProfilingConditionals.h"
#import "SentryReplayApi.h"
#import "SentrySamplingContext.h"
#import "SentryScope.h"
#import "SentrySerialization.h"
Expand Down Expand Up @@ -94,7 +95,15 @@ + (nullable SentryOptions *)options
return startOption;
}
}

#if SENTRY_TARGET_REPLAY_SUPPORTED
+ (SentryReplayApi *)replay
{
static SentryReplayApi *replay;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{ replay = [[SentryReplayApi alloc] init]; });
return replay;
}
#endif
/** Internal, only needed for testing. */
+ (void)setCurrentHub:(nullable SentryHub *)hub
{
Expand Down Expand Up @@ -576,18 +585,6 @@ + (void)stopProfiler
}
#endif // SENTRY_TARGET_PROFILING_SUPPORTED

#if SENTRY_TARGET_REPLAY_SUPPORTED
+ (void)replayRedactView:(UIView *)view
{
[SentryRedactViewHelper redactView:view];
}

+ (void)replayIgnoreView:(UIView *)view
{
[SentryRedactViewHelper ignoreView:view];
}
#endif

@end

NS_ASSUME_NONNULL_END
26 changes: 19 additions & 7 deletions Sources/Sentry/SentrySessionReplayIntegration.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
*/
static SentryTouchTracker *_touchTracker;

static SentrySessionReplayIntegration *_installedInstance;

@interface
SentrySessionReplayIntegration () <SentryReachabilityObserver>
- (void)newSceneActivate;
Expand All @@ -47,6 +49,11 @@ @implementation SentrySessionReplayIntegration {
SentryOnDemandReplay *_resumeReplayMaker;
}

+ (nullable SentrySessionReplayIntegration *)installed
brustolin marked this conversation as resolved.
Show resolved Hide resolved
{
return _installedInstance;
}

- (BOOL)installWithOptions:(nonnull SentryOptions *)options
{
if ([super installWithOptions:options] == NO) {
Expand Down Expand Up @@ -80,6 +87,7 @@ - (BOOL)installWithOptions:(nonnull SentryOptions *)options
[SentryViewPhotographer.shared addIgnoreClasses:_replayOptions.ignoreRedactViewTypes];
[SentryViewPhotographer.shared addRedactClasses:_replayOptions.redactViewTypes];

_installedInstance = self;
return YES;
}

Expand Down Expand Up @@ -190,7 +198,7 @@ - (void)captureVideo:(SentryVideoInfo *)video

- (void)startSession
{
[self.sessionReplay stop];
[self.sessionReplay pause];

_startedAsFullSession = [self shouldReplayFullSession:_replayOptions.sessionSampleRate];

Expand Down Expand Up @@ -266,7 +274,7 @@ - (void)startWithOptions:(SentryReplayOptions *)replayOptions
fullSession:[self shouldReplayFullSession:replayOptions.sessionSampleRate]];

[_notificationCenter addObserver:self
selector:@selector(stop)
selector:@selector(pause)
name:UIApplicationDidEnterBackgroundNotification
object:nil];

Expand Down Expand Up @@ -308,9 +316,9 @@ - (void)saveCurrentSessionInfo:(SentryId *)sessionId
cStringUsingEncoding:NSUTF8StringEncoding]);
}

- (void)stop
- (void)pause
{
[self.sessionReplay stop];
[self.sessionReplay pause];
}

- (void)resume
Expand All @@ -320,7 +328,7 @@ - (void)resume

- (void)sentrySessionEnded:(SentrySession *)session
{
[self stop];
[self pause];
[_notificationCenter removeObserver:self
name:UIApplicationDidEnterBackgroundNotification
object:nil];
Expand Down Expand Up @@ -361,7 +369,11 @@ - (void)uninstall
{
[SentrySDK.currentHub unregisterSessionListener:self];
_touchTracker = nil;
[self stop];
[self pause];

if (_installedInstance == self) {
_installedInstance = nil;
}
}

- (void)dealloc
Expand Down Expand Up @@ -475,7 +487,7 @@ - (void)connectivityChanged:(BOOL)connected typeDescription:(nonnull NSString *)
if (connected) {
[_sessionReplay resume];
} else {
[_sessionReplay pause];
[_sessionReplay pauseSessionMode];
}
}

Expand Down
9 changes: 9 additions & 0 deletions Sources/Sentry/include/SentrySessionReplayIntegration.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ NS_ASSUME_NONNULL_BEGIN

@interface SentrySessionReplayIntegration : SentryBaseIntegration

/**
* The last instance of the installed integration
*/
@property (class, nonatomic, readonly, nullable) SentrySessionReplayIntegration *installed;

/**
* Captures Replay. Used by the Hybrid SDKs.
*/
Expand All @@ -23,6 +28,10 @@ NS_ASSUME_NONNULL_BEGIN
- (void)configureReplayWith:(nullable id<SentryReplayBreadcrumbConverter>)breadcrumbConverter
screenshotProvider:(nullable id<SentryViewScreenshotProvider>)screenshotProvider;

- (void)pause;

- (void)resume;

@end
#endif // SENTRY_TARGET_REPLAY_SUPPORTED
NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public class SentryReplayOptions: NSObject, SentryRedactOptions {
* Indicates the quality of the replay.
* The higher the quality, the higher the CPU and bandwidth usage.
*/
public var quality = SentryReplayQuality.low
public var quality = SentryReplayQuality.medium

/**
* A list of custom UIView subclasses that need
Expand Down
Loading