Configure Session Replay on crashes for iOS
This page describes how to enable and customize Session Replay on crashes for your iOS apps.
Session Replay on crashes gives you additional context for crash analysis in the form of video-like screen recordings that replay user actions immediately preceding a detected crash.
Prerequisites
Ensure that your system meets the following requirements:
- Dynatrace version 1.208+
- OneAgent version 1.207+
- Swift 5+
- iOS 11+
- Xcode 14+
-
Real User Monitoring enabled for your application
-
Active Dynatrace Digital Experience Monitoring license
-
The web UI URL has a trusted certificate
-
Dynatrace Managed only Secondary disk configured to store user session data
Starting with OneAgent for iOS version 8.257, Dynatrace stopped supporting iOS 9 and 10, Xcode 13, and bitcode-enabled builds. We only support iOS 11+ and Xcode 14+.
Also, following the Apple app submission guidelines, we'll only support apps built with Xcode 14.1+ starting April 2023.
Known limitations
- Session Replay on crashes is not available for tvOS and iPadOS.
- Session Replay is not available for Cordova, React Native, Flutter, or Xamarin.
- For a hybrid app, Session Replay on crashes is supported only for the native part of the app. Session Replay is not supported for the browser part of a hybrid app.
- We recommend that you not use other crash reporting tools together with Dynatrace Session Replay.
- Session Replay can capture only certain events. However, if you need to track a specific view or event that is not supported by default, you can capture a custom event.
- You can play back the user sessions recorded with Session Replay only in certain browsers.
See Technical restrictions for Session Replay for web applications for more information.
Enable Session Replay
If you haven't done so already, complete all steps described in the instrumentation wizard.
- In the Dynatrace menu, go to Mobile.
- Select the mobile application that you want to configure.
- Select More (…) > Edit in the upper-right corner of the tile with your application name.
- From the mobile app settings, go to General > Enablement and cost control.
- Turn on Enable Session Replay on crashes.
- From the mobile app settings, go to General > Data privacy.
- Turn on Enable user opt-in mode.
- From the mobile app settings, go to Instrumentation wizard, and select Android or iOS.
- Follow the steps in the instrumentation wizard.
Enable Session Replay for SwiftUI apps
OneAgent for iOS version 8.249+
If you've already instrumented your SwiftUI app, you can additionally enable Session Replay for such a mobile app.
To enable Session Replay for your instrumented SwiftUI app
-
Complete all the steps of the Enable Session Replay instruction above.
-
Set the
DTXSwiftUIEnableSessionReplayInstrumentation
configuration key totrue
in your project'sInfo.plist
file.<key>DTXSwiftUIEnableSessionReplayInstrumentation</key> <true/>
Supported SwiftUI containers
We support Session Replay for the following SwiftUI containers:
Known limitations for SwiftUI apps
Dynatrace doesn't instrument the following SwiftUI containers:
- Lists inside extensions
- Lists with static content
- Lists where the feeding object does not conform to the
Equatable
protocol
Mask sensitive data
Session Replay on crashes comes with three predefined masking levels:
- Safest—all the editable texts fields, images, labels, web views, and switches are masked.
- Safe—all the editable texts fields are masked.
- Custom—by default, masks the same elements as Safest, but you can decide exactly which app components or views should be masked.
To see what data Session Replay masks and what parts of the screen are captured, use the Session Replay screenshot debugger.
Change masking level
By default, OneAgent applies the Safest masking level. To change it to the Safe or Custom level, use the API to configure OneAgent.
-
Import the
DynatraceSessionReplay
framework to the class.import DynatraceSessionReplay
#import <DynatraceSessionReplay/DynatraceSessionReplay-Swift.h>
-
Set the required masking level.
let maskingConfiguration = MaskingConfiguration(maskingLevelType: .safe) // .safest or .custom AgentManager.setMaskingConfiguration(maskingConfiguration)
MaskingConfiguration *conf = [[MaskingConfiguration alloc] initWithMaskingLevelType: MaskingLevelTypeSafe]; // MaskingLevelTypeSafest // MaskingLevelTypeCustom [AgentManager setMaskingConfiguration: conf error: nil];
Configure custom masking
If you set the data masking level to Custom, you can use additional API methods to decide exactly which app components or views should be masked.
Enable or disable masking rules
You can enable or disable rules globally or for the selected components, such as texts fields, images, labels, web views, and switches.
try? maskingConfiguration.add(rule: .maskAllImages) // Adds one rule
try? maskingConfiguration.remove(rule: .maskAllSwitches) // Removes one rule
try? maskingConfiguration.addAllRules() // Adds all rules
try? maskingConfiguration.removeAllRules() // Removes all rules
[conf addWithRule:MaskingRuleMaskAllImages error:nil]; // Adds one rule
[conf removeWithRule:MaskingRuleMaskAllSwitches error:nil]; // Removes one rule
[conf addAllRulesAndReturnError:nil]; // Adds all rules
[conf removeAllRulesAndReturnError:nil]; // Removes all rules
If you remove all masking rules, Session Replay won't mask anything. If you enable all masking rules, it's equivalent to the Safest masking level.
Mask views using accessibilityIdentifier
You can enable or disable masking of the selected views based on their accessibilityIdentifier
.
try? maskingConfiguration.addMaskedView(viewIds: ["masked_view_id"])
try? maskingConfiguration.removeMaskedView(viewIds: ["masked_view_id"])
try? maskingConfiguration.addNonMaskedView(viewIds: ["nonMasked_view_id"])
try? maskingConfiguration.removeNonMaskedView(viewIds: ["nonMasked_view_id"])
[conf addMaskedViewWithViewIds:@[@"masked_view_id"] error:nil];
[conf removeMaskedViewWithViewIds:@[@"masked_view_id"] error:nil];
[conf addNonMaskedViewWithViewIds:@[@"nonMasked_view_id"] error:nil];
[conf removeNonMaskedViewWithViewIds:@[@"nonMasked_view_id"] error:nil];
Mask views using a masking tag
You can also mask a view by adding the data-dtrum-mask
masking tag to the view's accessibilityIdentifier
. A view with this masking tag is always masked.
Enable Session Replay logs
You can enable Session Replay logs the same way as for OneAgent. See OneAgent for iOS debug logging for more information.
Capture custom events
Session Replay records only certain events. You can additionally capture custom events that are not supported by default. You can capture a custom event with an included screenshot of a specific view, specific screen region, or full screen.
All methods for capturing custom events can throw a TrackCustomEventError.notInMainThread
error if you try to capture a custom event from a thread that is not the main thread. We suggest that you include a do-catch clause until everything works properly; then you can replace the clause with a simpler version that, even in case of an error, just doesn't capture the custom event.
do {
try AgentManager.trackCustomEvent(name: "my_event_name", view: nil)
} catch {
print(error)
}
try? AgentManager.trackCustomEvent(name: "my_event_name", view: nil)
With OneAgent for iOS version 8.239, we deprecated the following methods for capturing custom events:
trackCustomEvent(name:withFrame:)
trackCustomEvent(name:withView:takeScreenshot:)
takeScreenshot()
Use the following new methods for capturing custom events:
trackCustomEvent(name:view:) throws
trackCustomEvent(name:frame:) throws
trackCustomEvent(name:) throws
Specific view
OneAgent for iOS version 8.239+
Capture a custom event with a screenshot of the specific view.
try? AgentManager.trackCustomEvent(name: "my_view_name", view: myView)
[AgentManager trackCustomEventWithName:@"my_view_name" view:myView error:&error];
Specific screen region
OneAgent for iOS version 8.239+
Capture a custom event with a screenshot of the specific screen region.
try? AgentManager.trackCustomEvent(name: "my_view_name", frame: anyFrame)
[AgentManager trackCustomEventWithName:@"my_view_name" frame:myView.frame error:&error];
Full screen
OneAgent for iOS version 8.239+
Capture a custom event with a screenshot of the full screen.
You can use this method instead of the deprecated takeScreenshot()
method.
try? AgentManager.trackCustomEvent(name: "my_view_name")
[AgentManager trackCustomEventWithName:@"my_view_name" view:nil error:nil];
Change transmission mode to Wi-Fi for images
By default, all data—information on captured events and images—is sent over any connection. However, you can opt to transfer images only when the users are connected to Wi-Fi to save their mobile data.
AgentManager.setTransmissionMode(.wifi) // .data by default
[AgentManager setTransmissionMode: TransmissionModeWifi]; // TransmissionModeData by default
Screenshot debugger
OneAgent for iOS version 8.239+
The Session Replay screenshot debugger allows you to see when the screenshots are taken, which parts of the screen are captured, and what data—texts fields, images, labels, web views, and toggles—is masked.
You can use the Session Replay screenshot debugger when running your mobile app in the simulator, so you don't have to wait until the session is closed and uploaded to Dynatrace.
After you enable the Session Replay screenshot debugger, you can see the corresponding keys in your project. Note that these keys are not sent to the app code for release or archive compilations, so they are never included in the production code. These keys are used only for debug runs.
To enable the Session Replay screenshot debugger
-
In Xcode, select Edit Scheme from the Scheme menu to change your application scheme.
-
From your application scheme settings, select the Run action, and then switch to the Arguments tab.
-
Under Environment Variables, add one or both of the following keys:
DTXDebugMasking
. This key shows screenshots taken by Session Replay, including masked content and UI controls. For each captured screenshot, you see a brief flash.DTXDebugFrameHighlight
. This key highlights the captured part of the screen with a red frame so that you can know exactly what part of the screen is captured.
Troubleshooting
Ensure that your system meets the Session Replay requirements.
User sessions are not recorded at all
-
If you're using the Simulator in Xcode to test Session Replay, go to Edit Scheme… > Run | Debug, and clear the Debug executable checkbox for your Xcode scheme.
-
Verify that you completed the steps described in the mobile instrumentation wizard:
- You added Session Replay as a dependency to your Podfile.
- You included all mandatory application identification keys to your app's
Info.plist
file. - You enabled the user opt-in mode and added a privacy notice.
-
Ensure that you can import the Dynatrace libraries:
import Dynatrace import DynatraceSessionReplay
#import <Dynatrace/Dynatrace.h> #import <DynatraceSessionReplay/DynatraceSessionReplay-Swift.h>
-
In the running application console logs, find the following:
- Line stating the OneAgent version, for example,
Dynatrace OneAgent (iOS) 8.207.1.XXXX
- Line on the Session Replay version, for example,
Dynatrace Mobile Session Replay Agent (iOS) 1.207
- Line stating the OneAgent version, for example,
User sessions are recorded, but Session Replay is not available
- Verify that Session Replay is enabled. From the mobile app settings, go to General to check that.
- Verify that the user opt-in mode is enabled. From the mobile app settings, go to Instrumentation settings to check that.
- In the running application console logs, check for the following:
-
Line confirming that Session Replay is enabled:
FINEST Communications [DTXReplayAgentChannel.m:146-771-1] posted MRA notification: DTXServerConfigurationChangedNotification, userInfo:{ ... replayConfig = { // Session Replay config capture = 1; // 1 means Session Replay is enabled; 0 means Session Replay is disabled ...
-
Line on a new session, for example,
[DYNATRACE]: ℹ️ Info -> New sessionId:0003, visitorId:123456789101112, visitStore:1 and serverId:4 from DT agent <NSThread: 0x6000013fe800>{number = 1, name = main}
-