Skip to content
Last9
Book demo

iOS RUM SDK

Install and configure the Last9 iOS RUM SDK. Swift API, CDN-hosted CocoaPods podspec and SPM XCFramework, automatic instrumentation for sessions, views, network, errors, and resource sampling.

Real User Monitoring for iOS apps. Automatic instrumentation for sessions, views, network requests, errors, and resource metrics via OpenTelemetry.

Prerequisites

  • iOS 15.1+
  • Swift 5.9+
  • Dependencies (resolved transitively): OpenTelemetry-Swift-Api ~> 1.10, OpenTelemetry-Swift-Sdk ~> 1.10
  • A Last9 RUM client token and OTLP endpoint

CDN artifacts

ArtifactURL
Podspechttps://cdn.last9.io/rum-sdk/ios/builds/0.3.1/Last9RUM.podspec
XCFrameworkhttps://cdn.last9.io/rum-sdk/ios/builds/0.3.1/Last9RUM.xcframework.zip
Checksumhttps://cdn.last9.io/rum-sdk/ios/builds/0.3.1/Last9RUM.xcframework.zip.sha256

Staging builds use the -alpha suffix.

Installation

  1. Add to your Podfile

    pod 'Last9RUM', :podspec => 'https://cdn.last9.io/rum-sdk/ios/builds/0.3.1/Last9RUM.podspec'
  2. Install

    pod install

Initialization

import Last9RUM
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions:
[UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
var config = L9RumConfig(
baseUrl: "https://otlp-ext-aps1.last9.io/v1/otlp/organizations/<org>",
clientToken: "your-client-token",
serviceName: "my-ios-app",
serviceVersion: "1.0.0",
deploymentEnvironment: "production"
)
config.origin = "https://app.last9.io"
L9Rum.shared.initialize(config: config)
return true
}
}

Configuration

var config = L9RumConfig(
// --- Required ---------------------------------------------------------
baseUrl: "https://otlp-ext-aps1.last9.io/v1/otlp/organizations/<org>",
clientToken: "your-client-token",
serviceName: "my-ios-app",
serviceVersion: "1.0.0",
deploymentEnvironment: "production"
)
// --- Optional -------------------------------------------------------------
// Origin sent as X-LAST9-ORIGIN header.
// Required for client_monitoring tokens.
config.origin = "https://app.last9.io"
// Specific build identifier (maps to app.build_id)
config.appBuildId = "1.0.0-build-42"
// Unique per-install ID (NOT a hardware ID). Persists across launches.
config.appInstallationId = nil
// Session sampling rate: 0-100 (percentage). 100 = sample everything.
config.sampleRate = 100
// Print debug logs to console
config.debugLogs = false
// Automatically trace HTTP requests via URLProtocol
config.networkInstrumentation = true
// Automatically capture unhandled exceptions
config.errorInstrumentation = true
// Max spans per export batch
config.maxExportBatchSize = 100
// Export timeout in milliseconds
config.exportTimeoutMs = 30_000
// Periodically sample memory and CPU
config.resourceMonitoringEnabled = true
// Interval between resource samples (ms)
config.resourceSamplingIntervalMs = 30_000
// When true, each HTTP request gets its own traceId
// instead of sharing the current view's traceId
config.isolateTracePerRequest = false
// Custom resource attributes added to every span
config.resourceAttributes = [
"app.platform": "ios",
]
// W3C Baggage propagation on outgoing requests
config.baggage = L9BaggageConfig()
config.baggage.enabled = false
config.baggage.allowedKeys = ["session.id", "user.id"]
config.baggage.maxTotalBytes = 8192
config.baggage.trackedUrlPatterns = []
config.baggage.warnAtPercentage = 80

API reference

Identify a user

L9Rum.shared.identify(userId: "user-123", attributes: [
"email": "user@example.com",
"plan": "premium",
])

Clear user on sign-out

L9Rum.shared.clearUser()

Capture errors

do {
try riskyOperation()
} catch {
L9Rum.shared.captureError(error, context: ["screen": "checkout"])
}

Track views

L9Rum.shared.startView("ProductDetailsScreen")
L9Rum.shared.setViewName("Product #42")

Custom events

L9Rum.shared.addEvent("purchase_completed", attributes: [
"product_id": "12345",
"amount": 29.99,
])

Global span attributes

// Inject attributes into every span
L9Rum.shared.spanAttributes([
"experiment": "checkout_v2",
"feature_flag": "new_cart",
])
// Clear
L9Rum.shared.spanAttributes(nil)

Session ID

let sessionId: String? = L9Rum.shared.getSessionId()

Flush pending data

L9Rum.shared.flush()

Next steps

Once data is flowing, explore it in Discover > Applications — performance, errors, and sessions.


Troubleshooting

Please get in touch with us on Discord or Email if you have any questions.