Skip to content
Last9
Book demo

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

  1. Open Last9 → Settings → Ingestion Tokens
  2. Click Create Token → choose type Client
  3. Set the allowed origin to ios://com.yourcompany.yourapp — use your app’s exact bundle ID
  4. Copy the token and the OTLP endpoint URL

Install

In Xcode: File → Add Package Dependencies, enter:

https://github.com/last9/last9-ios-swift-sdk

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

Every URLSession request is now traced automatically. No further code changes required.

What’s captured automatically

SignalDetails
Network requestsEvery 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
Sessions15m inactivity / 4h max, persisted across restarts, rollover detection
App launch timeCold and warm start duration (process start → first viewDidAppear)
Frame rateSlow frames (>25ms) and frozen frames (>700ms) per view
User interactionsTap tracking via UIApplication.sendEvent swizzle
Network timingDNS, TLS, TTFB, transfer breakdown from URLSessionTaskMetrics
Hangs (ANR)Background thread detects main thread blocks > 2s, captures stack trace
Watchdog terminationsDetects abnormal previous termination (0x8badf00d) on next launch
Signal crashesSIGSEGV, SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGTRAP with crash markers
ObjC exceptionsNSSetUncaughtExceptionHandler with full stack trace
Device contextdevice.model, os.name, os.version, service.version, last9.rum.sdk.version

User Identification

// After login
Last9RUM.identify(id: "u_123", name: "Alice", email: "alice@example.com")
// On logout
Last9RUM.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↗.