iOS / Swift
Real User Monitoring for iOS using the Last9 RUM SDK. One package, one initialize call — sessions, views, crashes, hangs, and network traces captured automatically.
Real User Monitoring for iOS, built on OpenTelemetry. One package, one initialize call — every network request, screen view, crash, hang, and user interaction is automatically traced and sent to Last9.
Prerequisites
- iOS 13+, Xcode 15+, Swift 5.9+
- A Last9 client monitoring token (see below)
Create a Client Monitoring Token
- Open Last9 → Settings → Ingestion Tokens
- Click Create Token → choose type Client
- Set the allowed origin to
ios://com.yourcompany.yourapp— use your app’s exact bundle ID - Copy the token and the OTLP endpoint URL
Install
In Xcode: File → Add Package Dependencies, enter:
https://github.com/last9/last9-ios-swift-sdkSelect Last9RUM as the product to add to your target.
Or in Package.swift:
dependencies: [ .package(url: "https://github.com/last9/last9-ios-swift-sdk", from: "0.1.2"),],targets: [ .target(name: "YourApp", dependencies: [ .product(name: "Last9RUM", package: "last9-ios-swift-sdk"), ]),]Initialize
Call once at app startup — that’s it.
import Last9RUM
func application(\_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {Last9RUM.initialize(endpoint: "<your-otlp-endpoint>",clientToken: "<your-client-token>",serviceName: "my-ios-app")return true}import Last9RUM
@mainstruct YourApp: App { init() { Last9RUM.initialize( endpoint: "<your-otlp-endpoint>", clientToken: "<your-client-token>", serviceName: "my-ios-app" ) } var body: some Scene { WindowGroup { ContentView() } }}Every URLSession request is now traced automatically. No further code changes required.
What’s captured automatically
| Signal | Details |
|---|---|
| Network requests | Every URLSession call — latency, status code, URL, W3C traceparent injected |
| Screen views (UIKit) | UIViewController swizzle — view.name, view.time_spent, CPU, memory, frame rate |
| Screen views (SwiftUI) | .trackView(name:) modifier |
| Sessions | 15m inactivity / 4h max, persisted across restarts, rollover detection |
| App launch time | Cold and warm start duration (process start → first viewDidAppear) |
| Frame rate | Slow frames (>25ms) and frozen frames (>700ms) per view |
| User interactions | Tap tracking via UIApplication.sendEvent swizzle |
| Network timing | DNS, TLS, TTFB, transfer breakdown from URLSessionTaskMetrics |
| Hangs (ANR) | Background thread detects main thread blocks > 2s, captures stack trace |
| Watchdog terminations | Detects abnormal previous termination (0x8badf00d) on next launch |
| Signal crashes | SIGSEGV, SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGTRAP with crash markers |
| ObjC exceptions | NSSetUncaughtExceptionHandler with full stack trace |
| Device context | device.model, os.name, os.version, service.version, last9.rum.sdk.version |
User Identification
// After loginLast9RUM.identify(id: "u_123", name: "Alice", email: "alice@example.com")
// On logoutLast9RUM.clearUser()user.id, user.name, and user.email are stamped on every subsequent span automatically.
SwiftUI View Tracking
UIKit views are tracked automatically. For SwiftUI, add the modifier:
ContentView() .trackView(name: "Home")Custom Spans
let tracer = Last9RUM.tracer("checkout")let span = tracer.spanBuilder(spanName: "order.place") .setAttribute(key: "order.id", value: "ORD-9999") .setAttribute(key: "order.total_usd", value: 49.99) .startSpan()// ... your logic ...span.end()Configuration
Last9RUM.initialize( endpoint: "...", clientToken: "...", serviceName: "my-ios-app", environment: "production", // default: "production" sessionInactivityTimeout: 10 * 60, // default: 15 min enableAutoViewTracking: true, // default: true hangThreshold: 2.0 // default: 2s, 0 to disable)Backend Correlation
The SDK injects W3C traceparent into every outgoing URLSession request. If your backend is instrumented with OpenTelemetry, iOS network requests appear as parent spans linked to backend traces — no additional configuration needed.
Security
Client monitoring tokens are write-only and origin-scoped to your app’s bundle ID. Safe to ship in the app binary.
Example App
See the full working example on GitHub↗.