• Home
  • Platform modules
  • Digital Experience
  • Session Replay
  • Configure Session Replay for iOS

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

    Calculate secondary disk size

    To calculate the secondary disk size, consider the following:

    • The size of a regular mobile user session is around 300 KB
    • The default data retention period is 35 days
    • Having some buffer is always good Using these estimates, we recommend that you calculate the secondary disk size using the following formula:
      Secondary disk size = Sessions ended with a crash per day * Average session size (300 KB) * Retention period (35 days) * Buffer (1.5)

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.

  1. In the Dynatrace menu, go to Mobile.
  2. Select the mobile application that you want to configure.
  3. Select More (…) > Edit in the upper-right corner of the tile with your application name.
  1. From the mobile app settings, go to General > Enablement and cost control.
  2. Turn on Enable Session Replay on crashes.
  3. From the mobile app settings, go to General > Data privacy.
  4. Turn on Enable user opt-in mode.
  5. From the mobile app settings, go to Instrumentation wizard, and select Android or iOS.
  6. 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

  1. Complete all the steps of the Enable Session Replay instruction above.

  2. Set the DTXSwiftUIEnableSessionReplayInstrumentation configuration key to true in your project's Info.plist file.

    xml
    <key>DTXSwiftUIEnableSessionReplayInstrumentation</key> <true/>

Supported SwiftUI containers

We support Session Replay for the following SwiftUI containers:

  • List
  • LazyVGrid
  • LazyHGrid

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.

  1. Import the DynatraceSessionReplay framework to the class.

    swift
    import DynatraceSessionReplay
    objectivec
    #import <DynatraceSessionReplay/DynatraceSessionReplay-Swift.h>
  2. Set the required masking level.

    swift
    let maskingConfiguration = MaskingConfiguration(maskingLevelType: .safe) // .safest or .custom AgentManager.setMaskingConfiguration(maskingConfiguration)
    objectivec
    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.

swift
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
objectivec
[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.

swift
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"])
objectivec
[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.

swift
do { try AgentManager.trackCustomEvent(name: "my_event_name", view: nil) } catch { print(error) }
swift
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.

swift
try? AgentManager.trackCustomEvent(name: "my_view_name", view: myView)
objectivec
[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.

swift
try? AgentManager.trackCustomEvent(name: "my_view_name", frame: anyFrame)
objectivec
[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.

swift
try? AgentManager.trackCustomEvent(name: "my_view_name")
objectivec
[AgentManager trackCustomEventWithName:@"my_view_name" view:nil error:nil];
Capture custom events in earlier versions of OneAgent

OneAgent for iOS version 8.237 and earlier

swift
AgentManager.trackCustomEvent(name: my_name, withView: my_view, takeScreenshot: true)
objectivec
[AgentManager trackCustomEventWithName: my_name withView: my_view takeScreenshot:YES];
  • name is the custom event name shown in the timeline during the user session replay.
  • withView is an optional value referring to the UIView from which OneAgent takes the image. By default, OneAgent takes the application window.
  • takeScreenshot is an optional boolean value used to define if a custom event has a screenshot or not.

Alternatively, you can take a screenshot of the view. In this case, a custom event named "Custom Screenshot" is shown in the timeline during the user session replay.

swift
AgentManager.takeScreenshot()
objectivec
[AgentManager takeScreenshot];

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.

swift
AgentManager.setTransmissionMode(.wifi) // .data by default
objectivec
[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.

Session Replay screenshot debugger for iOS

To enable the Session Replay screenshot debugger

  1. In Xcode, select Edit Scheme from the Scheme menu to change your application scheme.

  2. From your application scheme settings, select the Run action, and then switch to the Arguments tab.

  3. 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.

    Add Session Replay screenshot debugger variables to your app scheme

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:

    swift
    import Dynatrace import DynatraceSessionReplay
    objectivec
    #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

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:

      plaintext
      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}

Frequently asked questions

What is the license consumption for a user session captured with Session Replay?

1.0 DEM unit per user session captured with Session Replay.

How much storage is consumed on the user's device?

We've set hard limits of 300 KB per session and 10 MB for all sessions. Anything exceeding these limits gets trimmed down to the limits as mentioned above.

When recording a user session, Dynatrace may consume up to 10 MB of the user's mobile device storage. However, Dynatrace won't send a session that's more than 300 KB.

Do all sessions consume the same amount of storage volume?

No. Session volume depends on a variety of factors, including the application size, session duration, and users' interactivity with the application.

Are sessions recorded as videos?

No. To record sessions, Session Replay on crashes takes screenshots of the mobile app screen and its parts.

Is the data sent once or several times?

The data is sent one time. This is performed in several requests according to the data collected.

How long does Dynatrace store images when the transmission mode is set to Wi-Fi?

If you've changed the transmission mode to Wi-Fi, the images are sent only when the users of your app are connected to Wi-Fi.

Currently, there is no time limit for storing images; only the 10 MB hard limit mentioned above is applied. However, in emergency stop situations, everything is deleted.

Is overhead observed during startup or runtime? Is overhead directly related to the complexity of the application?

The impact is very low, and overhead is mainly seen during runtime. In general, it's related to the complexity of the application, for instance, to how many views are displayed at a time.

What is the size of the Session Replay framework? How many MB will it add to my app?

It is difficult to answer this question precisely as the final size of the Session Replay framework depends on several factors.

Multiple architectures are included in a fat-framework binary: ARMv7, ATM64, i386, and x86-64. The ARM slices are used by physical iOS devices, while i386 and x86-64 parts are used by Simulator and removed from your app during the build and archive process. Moreover, when users download your app from App Store, they receive only the architecture that their device requires.

We also have bitcode, which is an unoptimized intermediate code representation. It is included for ARM architectures but does not affect the final size of your application. Apple uses bitcode for potential recompilation and re-optimization of your app binary after you've submitted your mobile application to App Store.

Due to all these factors, the best way to estimate the Session Replay framework size is to compile your app without this framework and generate an IPA file; then do the same but with the framework included and compare the sizes of these two IPA files. The difference is the Session Replay framework size.

For our test application, the Session Replay framework size is around 500 kB compressed.

When is the data sent to Dynatrace? Does the user need to reopen the app?

Data is sent only when the user reopens the app. However, if the user does not open the app within 10 minutes, the data is deleted.

Related topics
  • Session Replay

    Learn how you can use Session Replay to better understand and troubleshoot errors experienced by your customers.

  • View crash reports for mobile applications

    Check the latest crash reports for your mobile applications.