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.0
or 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
sessionReplay
module 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 thesessionReplay
module immediately processes to remove sensitive data. The frames are then complied to make the session recording. The representation of the recording is video.Note: IfRenderingMode
isnative
, 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
RecordingMask
set at a time, but it can contain a list ofMaskElement
objects to cover multiple areas at once.The
MaskElement
can be one of two types:MaskElement.MaskType.covering
: The area defined by the elementRect
is not recorded.MaskElement.MaskType.erasing
: The area defined by the elementRect
is recorded even if a previousRecordingMask.Element
inside a list wascovering
the area.
The following screenshots describe a
RecordingMask
in action.On the left:
The blue box represents a
video_item
element.The red box represents a
video_item_image
element.
On the right:
The
video_item
element (blue box) has a.covering
value. The.covering
value masks the element in the session recording.The
video_item_image
element (red box) has an.erasing
value. The image is visible in the session recording because the.erasing
value cancels the.covering
value.
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
UIView
instance:- 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
Class
that extends aUIView
rather 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
,UITextField
andWKWebView
classes are set as sensitive. To override the sensitivity on the class or instance level, set the class or instance sensitivity tofalse
ornil
.Sensitivity prioritization
When determining if the
UIView
instance is sensitive, the resolution process checks the sensitivity in a strict order.UIView
instances are not recorded if:The
sensitivity
is set totrue
.The
Class
sensitivity 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
UITextView
class descendant (class MyCustomTextView: UITextView
) and mark it as non-sensitive, thenMyCustomTextView
and 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
WKWebView
and you want record them, you need to enableWKWebView
recording. You can enableWKWebView
recording by removing the sensitivity:- Swift
SplunkRum.shared.sessionReplay.sensitivity[WKWebView.self] = false
- ObjC
[SplunkRum.shared.sessionReplay setViewClassSensitivityWithViewClass:[WKWebView class] isSensitive:@NO];
If
WKWebView
is 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-hide
class:<div class='session-replay-hide'> This will be hidden. </div>
All inputs are hidden by default except
button
andsubmit
. If some hidden inputs should be recorded, make them part of the CSS.session-replay-show
class:<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
sessionReplay
module 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
wireframe
rendering 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
View
with the correspondingViewModifier
:Text("Example") .sessionReplaySensitive()
If you need to control the sensitivity of
View
dynamically, 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
UIView
descendant 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
View
that encapsulates a descendant ofUIView
with defined sensitivity does not carry over to the encapsulatedUIView
. To fully control the sensitivity on such aView
, you must disable sensitivity on the encapsulatedUIView
using the UIKit API and then set the sensitivity on theView
.Enabling sensitivity on the
View
item that encapsulates theUIView
descendant 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.