Record iOS sessions
Use the sessionReplay module in iOS applications.
Prerequisites
You must have an enterprise subscription.
You must use Splunk RUM agent version
2.0.0or higher.
Introduction
This page explains how to use the sessionReplay module in Android applications. This module provides several APIs so that you can choose which ones work best for your application.
Supported languages Swift, Objective-C (ObjC) compileVersion 34 minVersion 21 targetVersion 31 Java version 1.8 Kotlin version 1.7.20 - APIs
- Most APIs are methods within
SplunkRum.instance.sessionReplay:In addition, there are some Kotlin-specific extensions (properties) of standard Android classes, such as:
SplunkRum.instance.sessionReplay
Get a sessionReplay instance, which is used to configure and start the recording.
The instance doesn't automatically start recording when you create it. To start recording, call its start() method.
- Swift
let sessionReplay = SplunkRum.shared.sessionReplay- ObjC
SessionReplayModule *sessionReplay = [[SplunkRum shared] sessionReplay];
Start recording
- Swift
SplunkRum.shared.sessionReplay.start()- ObjC
[[[SplunkRum shared] sessionReplay] start];
Stop recording
There is no need to manually stop the recording when the application enters the background; the recording process automatically stops, and the sessionReplay module provides the final data chunk. When the application returns to the foreground, the sessionReplay module resumes recording automatically, provided it was active before the application was previously suspended.
If the application is forcibly terminated (not just suspended to the background) or crashes, the behavior of the sessionReplay module depends upon the platform:
If the system permits some time to process the incident, the last data chunk is immediately made available.
If not, the most recent replay data chunk prior to the incident is reconstructed and published when the
sessionReplaymodule is re-initialized during the application's next run. This includes the corresponding metadata (the actual start and end time stamps of the reconstructed chunk).
After the incident, the sessionReplay module doesn't resume recording automatically.
- Swift
SplunkRum.shared.sessionReplay.stop()- ObjC
[[[SplunkRum shared] sessionReplay] stop];
Get preferences
- Swift
SplunkRum.shared.sessionReplay.preferences- ObjC
[[[SplunkRum shared] sessionReplay] preferences];
Set the rendering mode
When your application displays sensitive or unnecessary data that you don’t want to record, you can set a rendering mode to protect or hide that information. Valid values:
native: Regularly captures the application screen which thesessionReplaymodule immediately processes to remove sensitive data. The frames are then complied to make the session recording. The representation of the recording is video.Note: IfRenderingModeisnative, both the video and wireframe recordings operate simultaneously due to the nature of the implementation. Consequently, both modes are accessible to the player.wireframeOnly: Renders the application using only a wireframe representation of the screen data. No user data is recorded. The representation of the recording is in JSON format.
- Swift
enum class RenderingMode { native, wireframeOnly }SplunkRum.shared.sessionReplay.preferences.renderingMode = .native- ObjC
public enum RenderingMode { native, wireframeOnly }[SplunkRum.shared.sessionReplay.preferences setRenderingMode:RenderingMode.native];
Set the recording mask
In cases where areas of the app shouldn't be recorded, but cannot be defined by a UIView, you can use the RecordingMask object:
- Swift
var maskElements = [MaskElement]() maskElements.append(MaskElement(rect: CGRect(x: 0, y: 0, width: 100, height: 100), type: .covering)) maskElements.append(MaskElement(rect: CGRect(x: 50, y:120, width: 100, height: 100), type: .erasing)) let recordingMask = RecordingMask(elements: maskElements) SplunkRum.shared.sessionReplay.recordingMask = recordingMask- ObjC
CGRect coveringRect = CGRectMake(0, 0, 100, 100); CGRect erasingRect = CGRectMake(50, 120, 100, 100); MaskElement *coveringElement = [[MaskElement alloc] initWithRect:coveringRect maskType:MaskTypeCovering]; MaskElement *erasingElement = [[MaskElement alloc] initWithRect:erasingRect maskType:MaskTypeErasing]; RecordingMask *recordingMask = [[RecordingMask alloc] initWithElements:@[coveringElement, erasingElement]];You can only have one
RecordingMaskset at a time, but it can contain a list ofMaskElementobjects to cover multiple areas at once.The
MaskElementcan be one of two types:MaskElement.MaskType.covering: The area defined by the elementRectis not recorded.MaskElement.MaskType.erasing: The area defined by the elementRectis recorded even if a previousRecordingMask.Elementinside a list wascoveringthe area.
The following screenshots describe a
RecordingMaskin action.On the left:
The blue box represents a
video_itemelement.The red box represents a
video_item_imageelement.
On the right:
The
video_itemelement (blue box) has a.coveringvalue. The.coveringvalue masks the element in the session recording.The
video_item_imageelement (red box) has an.erasingvalue. The image is visible in the session recording because the.erasingvalue cancels the.coveringvalue.
Set the sensitivity of a UI element or view
When you mark UI elements or views as sensitive, the sessionReplay module masks them in the recording directly on the device. The way to mark elements as sensitive depends on the element type:
You can set the sensitivity on any
UIViewinstance:- Swift
SplunkRum.shared.sessionReplay.sensitivity.set(someView, true|false|nil) SplunkRum.shared.sessionReplay.sensitivity[someView] = true|false|nil- ObjC
[SplunkRum.shared.sessionReplay setViewInstanceSensitivityWithView:self.someView isSensitive:@YES|@NO|nil];
- You can also set the sensitivity on all instances of a
Classthat extends aUIViewrather than setting the sensitivity on a specificUIView:- Swift
SplunkRum.shared.sessionReplay.sensitivity[SomeViewSubclass.self] = true|false|nil- ObjC
[SplunkRum.shared.sessionReplay setViewClassSensitivityWithViewClass:[SomeViewSubclass class] isSensitive:@YES|@NO|nil];
Default sensitive classes
By default, the
UITextView,UITextFieldandWKWebViewclasses are set as sensitive. To override the sensitivity on the class or instance level, set the class or instance sensitivity tofalseornil.Sensitivity prioritization
When determining if the
UIViewinstance is sensitive, the resolution process checks the sensitivity in a strict order.UIViewinstances are not recorded if:The
sensitivityis set totrue.The
Classsensitivity is set totrue.
Class hierarchy and sensitivity
The sensitivity set on descendants has a higher priority than the sensitivity set on the ancestors. For example, if we have a custom
UITextViewclass descendant (class MyCustomTextView: UITextView) and mark it as non-sensitive, thenMyCustomTextViewand all its descendants will not be sensitive, no matter what sensitivity we set forUITextView.Similarly, if we set the sensitivity on an ancestor class, all its descendants take over that sensitivity.
WebView sensitivity
If an app uses
WKWebViewand you want record them, you need to enableWKWebViewrecording. You can enableWKWebViewrecording by removing the sensitivity:- Swift
SplunkRum.shared.sessionReplay.sensitivity[WKWebView.self] = false- ObjC
[SplunkRum.shared.sessionReplay setViewClassSensitivityWithViewClass:[WKWebView class] isSensitive:@NO];
If
WKWebViewis being recorded, all sensitive elements on the displayed website should be marked as sensitive so that they are hidden. You can mark sensitive elements as sensitive using HTML elements with the CSS.session-replay-hideclass:<div class='session-replay-hide'> This will be hidden. </div>All inputs are hidden by default except
buttonandsubmit. If some hidden inputs should be recorded, make them part of the CSS.session-replay-showclass:<input type="text" class='session-replay-show'>SwiftUI sensitivity
Note:Sensitivity support:
Support for sensitivity in SwiftUI is available from version 2.1 and is a standard part of the session replay module.
When using the native rendering mode, the
sessionReplaymodule can record sensitive data in your application. In order to protect user privacy, you can configure the module to not record sensitive data.The module attempts to hide selected sensitive UI elements automatically. You can also configure it to hide or show particular UI components. Alternatively, you can use one of the
wireframerendering modes to record the screen in a schematic way, showing no user data. The last possibility is to stop screen capturing altogether by using no rendering mode.Note:Locally hidden elements:
Sensitive elements are hidden locally on the device. No sensitive data is transferred to or stored in the dashboard.
View sensitivity
You can set the sensitivity of any
Viewwith the correspondingViewModifier:Text("Example") .sessionReplaySensitive()If you need to control the sensitivity of
Viewdynamically, you can set this with an optional parameter:Text("Example") .sessionReplaySensitive(true|false)Advanced sensitivity control
Because SwiftUI does not use class hierarchy like UIKit, but dynamically generates content, the use of inheritance is irrelevant. The corresponding functions for setting sensitivity based on a class, instance, or using a protocol are unavailable for
View.However, this is not a limitation because there are other, more appropriate ways to handle similar needs in SwiftUI.
For example, suppose you have an element aggregating multiple elements and want to set all contained elements as sensitive. You can use the
.sessionReplaySensitive()modifier directly on the aggregating element. Sensitivity set in this way will be propagated to all contained elements.Group { Text("First text") Text("Second text") } .sessionReplaySensitive()Similarly, if an element needs to be completely hidden (for example,
List), then we can set the appropriate sensitivity:struct NamesListView: View { let names = ["John", "Alena", "Kabir"] var body: some View { List(names, id: \.self) { name in Text("\(name)") .padding() } .sessionReplaySensitive() } }Default sensitivity
Some UI elements in UIKit are default sensitive. This setting causes potentially sensitive areas to be hidden and not visible even in SwiftUI.
If a
UIViewdescendant is used directly or indirectly in SwiftUI, its sensitivity will be propagated to the correspondingView.Note: Some SwiftUI elements, such asTextField, perform this encapsulation in the background.Interference with UIKit
Disabling sensitivity on a
Viewthat encapsulates a descendant ofUIViewwith defined sensitivity does not carry over to the encapsulatedUIView. To fully control the sensitivity on such aView, you must disable sensitivity on the encapsulatedUIViewusing the UIKit API and then set the sensitivity on theView.Enabling sensitivity on the
Viewitem that encapsulates theUIViewdescendant can be done at any time and always takes precedence over the settings for the encapsulatedUIView.Note: Disabling the default sensitivity: ForUITextEdit, etc. must be done outside the View, ideally in the main application's controller or another suitable place. It is strongly discouraged to do this directly inView.For applications combining SwiftUI and large parts in UIKit, remember that disabling default sensitivity is for the entire application. This will also affect parts in UIKit.
Get the state
- Swift
SplunkRum.shared.sessionReplay.state- ObjC
[[[SplunkRum shared] sessionReplay] state];
Get the rendering mode
- Swift
val state = SplunkRum.instance.sessionReplay.state val renderingMode: RenderingMode = state.renderingMode- ObjC
State state = SessionReplay.getInstance().getState(); RenderingMode renderingMode = state.getRenderingMode();
Get the recording status
- Swift
let recordingStatus = SplunkRum.shared.sessionReplay.state.status- ObjC
NSNumber *recordingStatus = SplunkRum.shared.sessionReplay.state.status;
Procedure
Set the module's rendering mode, recording mask, and sensitivity.
Results
The sessionReplay module autonomously captures session data at its own rate and periodically publishes the data, typically several times per minute, through its API. To replay a user session, use replay player in the Splunk RUM UI.