Mobile RUM - iOS SDK

Overview#

The Middleware iOS RUM SDK collects user activity, application performance data, and errors from iOS applications. It helps you investigate crashes, slow screens, and failed requests in the context of a user session.

Collected data includes crashes, slow or frozen frames, network requests, and sessions. Session Replay adds visual context; correlation with backend traces helps follow a request beyond the mobile application when backend instrumentation is configured.

Prerequisites#

Before installing the SDK, make sure you have:

  • iOS 13 or later.
  • Xcode with Swift Package Manager support.
  • A Middleware account and RUM application credentials.
  • Access to your iOS application source code.
  • HTTPS connectivity to your Middleware ingestion endpoint.

The SDK also supports macOS 10.15+ and tvOS 13+.

To check available SDKs in Xcode, run:

1xcodebuild -showsdks

Installation#

1 Create a RUM application#

  1. Log in to Middleware.
  2. Go to Installation → RUM.
  3. Select iOS as the platform.
  4. Click New Application.
  5. Enter your application name and click Create Application.
  6. Copy the generated RUM access token and target URL.

2 Install the iOS SDK#

You can install the Middleware iOS SDK using Swift Package Manager or CocoaPods.

In Xcode:

  1. Open your iOS project.
  2. Go to File → Add Package Dependencies.
  3. Enter the repository URL: https://github.com/middleware-labs/middleware-ios
  4. Select version 2.1.2 or a compatible newer version.
  5. Add the package to your application target.

For projects using Package.swift, add:

1.package(
2    url: "https://github.com/middleware-labs/middleware-ios",
3    from: "2.1.2"
4)

Add the following dependency to your Podfile:

1pod 'MiddlewareRum', '~> 2.1'

Install the dependency:

1pod install

Note: MiddlewareRum is a static framework. If your project uses use_frameworks!, ensure dependent pods are linked statically.

3 Initialize Middleware#

Initialize the SDK as early as possible in your application's lifecycle to capture initial screens and application activity.

Choose the setup based on your application architecture.

For SwiftUI applications, initialize Middleware in your application's App initializer.

1import SwiftUI
2import MiddlewareRum
3
4@main
5struct MyApp: App {
6
7    init() {
8        do {
9            try MiddlewareRumBuilder()
10                .target("https://<MW_UID>.middleware.io")
11                .rumAccessToken("<MW_RUM_ACCESS_TOKEN>")
12                .serviceName("my-ios-app")
13                .projectName("My-iOS-App")
14                .deploymentEnvironment("PROD")
15                .globalAttributes([
16                    "app.version": "1.0.0"
17                ])
18                .build()
19        } catch {
20            print("Middleware RUM initialization failed: \(error)")
21        }
22    }
23
24    var body: some Scene {
25        WindowGroup {
26            ContentView()
27        }
28    }
29}

For UIKit applications, initialize Middleware inside AppDelegate.

1import UIKit
2import MiddlewareRum
3
4@main
5class AppDelegate: UIResponder, UIApplicationDelegate {
6
7    func application(
8        _ application: UIApplication,
9        didFinishLaunchingWithOptions launchOptions:
10            [UIApplication.LaunchOptionsKey: Any]?
11    ) -> Bool {
12
13        do {
14            try MiddlewareRumBuilder()
15                .target("https://<MW_UID>.middleware.io")
16                .rumAccessToken("<MW_RUM_ACCESS_TOKEN>")
17                .serviceName("my-ios-app")
18                .projectName("My-iOS-App")
19                .deploymentEnvironment("PROD")
20                .globalAttributes([
21                    "app.version": Bundle.main.object(
22                        forInfoDictionaryKey: "CFBundleShortVersionString"
23                    ) as? String ?? ""
24                ])
25                .build()
26        } catch {
27            print("Middleware RUM initialization failed: \(error)")
28        }
29
30        return true
31    }
32}

Replace the placeholders with your Middleware credentials.

ParameterRequiredDescription
targetYesMiddleware ingestion endpoint
rumAccessTokenYesRUM access token generated during setup
serviceNameYesService name used to identify the application
projectNameYesProject name associated with the application
deploymentEnvironmentNoEnvironment, such as PROD or DEV
globalAttributesNoCustom attributes such as application version

Note: If your application requires user consent before collecting telemetry, initialize the SDK only after consent is granted.

4 Run and verify#

Build and run your application on an iOS simulator or physical device.

  1. Open the application.
  2. Navigate between screens and trigger a few network requests.
  3. Go to RUM → Session Explorer in Middleware.
  4. Verify that your application sessions appear.

Read more about RUM explorer and see what data to monitor for frontend performance.

Enable or disable monitoring features#

Crash reporting, HTTP instrumentation, and slow rendering detection are enabled by default.

To disable specific features, add the corresponding methods during initialization:

1try MiddlewareRumBuilder()
2    .target("https://<MW_UID>.middleware.io")
3    .rumAccessToken("<MW_RUM_ACCESS_TOKEN>")
4    .serviceName("my-ios-app")
5    .projectName("My-iOS-App")
6    .disableCrashReportingInstrumentation()
7    .disableNetworkMonitoring()
8    .disableSlowRenderingDetection()
9    .build()

Only include the disable methods for features you don't want to collect.

MethodDescription
disableCrashReportingInstrumentation()Disables automatic crash reporting
disableNetworkMonitoring()Disables HTTP request instrumentation
disableSlowRenderingDetection()Disables slow and frozen frame detection
slowFrameDetectionThresholdMs(Double)Configures the slow frame threshold; default is 16.7 ms
frozenFrameDetectionThresholdMs(Double)Configures the frozen frame threshold; default is 700 ms

Configure Session Replay#

Session Replay is enabled by default and starts automatically when the SDK initializes.

It records user activity and screen changes to help investigate application issues.

Configure recording quality and privacy#

Use RecordingOptions to configure recording frequency, quality, and masking.

1try MiddlewareRumBuilder()
2    .target("https://<MW_UID>.middleware.io")
3    .rumAccessToken("<MW_RUM_ACCESS_TOKEN>")
4    .serviceName("my-ios-app")
5    .projectName("My-iOS-App")
6    .recordingOptions(
7        RecordingOptions()
8            .setFrequency(.standard)
9            .setQuality(.standard)
10            .setMaskAllTextInputs(true)
11            .setMaskAllImages(true)
12    )
13    .build()
OptionDescription
setFrequency()Recording frequency: low, standard, or high
setQuality()Recording quality: low, standard, or high
setMaskAllTextInputs()Masks text input values; enabled by default
setMaskAllImages()Masks images; enabled by default

Disable Session Replay#

To collect RUM telemetry without recording user sessions, add:

1.disableRecording()

Session recording limits#

  • Maximum session duration: 4 hours.
  • Idle timeout: 15 minutes.
  • Default: Session Replay enabled.

After the idle timeout, new user activity starts a new session.

Mask sensitive information#

Middleware masks sensitive text inputs and images by default. You can also mask specific UI elements that contain payment details, authentication information, or other sensitive content.

SwiftUI#

Use the .sensitive() modifier:

1Text("Sensitive account information")
2    .sensitive()

UIKit#

Exclude a view from Session Replay:

1MiddlewareRum.addIgnoredView(sensitiveView)

Alternatively, mark a view using its accessibility identifier:

1cardNumberField.accessibilityIdentifier = "mw-no-capture"

Supported identifiers:

  • mw-no-capture — Always masks the view.
  • mw-no-mask — Excludes the view from masking.

Important: Secure text fields and sensitive textContentType fields, such as passwords, credit card details, and one-time codes, remain masked regardless of the configuration.

Masking is applied on the device before session recording data is uploaded.

Configure distributed tracing#

Distributed tracing connects iOS network requests with backend APM traces.

The SDK automatically instruments URLSession and injects W3C traceparent headers into outgoing requests.

No additional HTTP client instrumentation is required.

Prerequisites#

  • Middleware APM instrumentation must be enabled on your backend.
  • Backend services must support W3C Trace Context.
  • Network monitoring must be enabled in the iOS SDK.

Restrict trace propagation targets#

By default, trace headers are added to outgoing requests, excluding Middleware ingestion endpoints.

To restrict propagation to your backend domains:

1try MiddlewareRumBuilder()
2    .target("https://<MW_UID>.middleware.io")
3    .rumAccessToken("<MW_RUM_ACCESS_TOKEN>")
4    .serviceName("my-ios-app")
5    .projectName("My-iOS-App")
6    .tracePropagationTargets([
7        "api\\.example\\.com",
8        "checkout\\.example\\.com"
9    ])
10    .build()

Requests to other domains are still monitored but do not receive tracing headers.

Passing an empty array disables trace propagation.

Verify trace correlation#

  1. Open your application and trigger a backend API request.
  2. Go to RUM → Session Explorer.
  3. Open the session and select the network request.
  4. Follow the associated backend trace.

If the request has a trace ID but no backend spans, verify that your backend is instrumented and accepts W3C Trace Context.

Add custom logs and errors#

Custom logs#

Use the SDK to capture application-specific logs:

1MiddlewareRum.info("User opened checkout")
2MiddlewareRum.debug("Loading payment details")
3MiddlewareRum.warning("API response delayed")
4MiddlewareRum.error("Payment request failed")
5MiddlewareRum.critical("Unexpected application failure")

Report custom errors#

Record application errors for investigation:

1MiddlewareRum.addError("Unable to process payment")

Report handled exceptions#

Application crashes are captured automatically. You can report handled exceptions manually:

1MiddlewareRum.addException(
2    e: NSException(
3        name: NSExceptionName(rawValue: "RuntimeException"),
4        reason: "Payment processing failed"
5    )
6)

Add custom attributes#

Use global attributes to filter sessions by application version, environment, or user group.

1MiddlewareRum.setGlobalAttributes([
2    "app.version": "1.0.0",
3    "user.type": "premium"
4])

Prefer stable, non-sensitive values. Avoid sending passwords, tokens, or personal information.

Set a custom screen name#

To identify screens using application-specific names:

1MiddlewareRum.setScreenName("checkout")

This is useful when investigating navigation or grouping events by screen.

Instrument WebView content#

If your application uses a WKWebView, you can connect Browser RUM with Mobile RUM to investigate hybrid user journeys.

1MiddlewareRum.integrateWebViewWithBrowserRum(view: webView)

Use this on the active WebView instance.

The embedded web application should also have the Middleware Browser RUM SDK installed for browser-side telemetry.

Configuration reference#

All methods accepted by MiddlewareRumBuilder():

MethodDescription
target(String)Sets the Middleware ingestion endpoint
rumAccessToken(String)Sets the RUM access token
serviceName(String)Sets the application service name
projectName(String)Sets the project name
deploymentEnvironment(String)Sets the deployment environment
globalAttributes(...)Adds custom attributes during initialization
tracePropagationTargets([String])Restricts trace propagation to selected URLs
recordingOptions(...)Configures Session Replay
disableRecording()Disables Session Replay
disableCrashReportingInstrumentation()Disables automatic crash reporting
disableNetworkMonitoring()Disables HTTP instrumentation
disableSlowRenderingDetection()Disables slow and frozen frame detection
slowFrameDetectionThresholdMs(Double)Sets the slow frame threshold
frozenFrameDetectionThresholdMs(Double)Sets the frozen frame threshold

Troubleshooting#

No RUM data appears#

If your application is running but telemetry does not appear:

  • Verify that the SDK is installed and imported correctly.
  • Confirm that MiddlewareRumBuilder().build() runs during application startup.
  • Check the RUM access token and target URL.
  • Verify that the device can connect to Middleware over HTTPS.
  • Review the Xcode console for initialization or export errors.

Network requests are missing#

If sessions appear but HTTP requests are not collected:

  • Confirm that disableNetworkMonitoring() is not enabled.
  • Verify that requests use URLSession or a networking library built on it.
  • Check whether the requests are sent to excluded Middleware ingestion endpoints.

Backend traces are not correlated#

If network requests appear but backend traces are missing:

  • Verify that backend APM instrumentation is enabled.
  • Confirm that the backend accepts W3C Trace Context.
  • Check that tracePropagationTargets() matches your backend domains.
  • Ensure that proxies or gateways do not remove the traceparent header.

Session Replay is missing#

If sessions appear without recordings:

  • Verify that disableRecording() is not enabled.
  • Check that SDK initialization completes successfully.
  • Confirm that recording is permitted by your application's consent settings.
  • Review SDK logs for recording or upload errors.

Sensitive information appears in recordings#

  • Verify that text and image masking is enabled.
  • Use .sensitive() for SwiftUI views.
  • Use MiddlewareRum.addIgnoredView() for UIKit views.
  • Mark sensitive fields with mw-no-capture.
  • Review masking whenever the application UI changes.

High slow or frozen frame counts#

The SDK reports:

  • Slow frames: Rendering time above 16.7 ms.
  • Frozen frames: Rendering time above 700 ms.

Use Xcode Instruments, including Time Profiler and Core Animation, to identify expensive main-thread work or rendering operations.

HTTPS requests are blocked#

iOS App Transport Security (ATS) blocks cleartext HTTP connections by default.

Use HTTPS for your Middleware ingestion endpoint and backend APIs. For development environments requiring HTTP, configure scoped ATS exceptions in Info.plist.

If the issue persists, contact Middleware Support at [email protected].

Need assistance or want to learn more about Middleware? Get in touch with us via our Contact Us or join our Slack channel.

What did you think of this content?