Loading

Automatic instrumentation for iOS applications with EDOT iOS

EDOT iOS can automatically generate telemetry on your behalf. This allows you to capture telemetry for supported Apple APIs and app lifecycle events without writing manual instrumentation.

Automatic instrumentations are bundled with EDOT iOS. After you add and initialize the SDK, supported instrumentations are enabled by default.

You do not need to add separate instrumentation packages.

Use InstrumentationConfigBuilder to turn individual instrumentations on or off:

import ElasticApm
import Foundation

let agentConfiguration = AgentConfigBuilder()
  .withExportUrl(URL(string: "https://your-otlp-endpoint")!)
  .build()

let instrumentationConfiguration = InstrumentationConfigBuilder()
  .withCrashReporting(true)
  .withURLSessionInstrumentation(true)
  .withViewControllerInstrumentation(true)
  .withSystemMetrics(true)
  .withLifecycleEvents(true)
  .build()

ElasticApmAgent.start(
  with: agentConfiguration,
  instrumentationConfiguration
)
		

Refer to Automatic instrumentation configuration for all options and defaults.

URLSession instrumentation creates spans for requests made with URLSession and injects W3C trace context headers into outgoing requests. These headers connect the mobile span with spans created by an instrumented backend.

By default, EDOT iOS names spans using the HTTP method and destination host, for example GET api.example.com.

When a response has a status code from 400 through 599, EDOT iOS adds an exception event with the status code and its localized description. Transport errors are also recorded as exception events.

URLSession spans include the current network connection type when it is available.

URLSession instrumentation is provided by OpenTelemetry-Swift. Refer to the URLSession instrumentation source for upstream implementation details.

EDOT iOS creates spans that measure how long UIKit and SwiftUI-backed views take to appear.

The SDK chooses span names in the following order, from lowest to highest precedence:

  1. The view controller class name followed by - view appearing.
  2. The navigation title or accessibility label followed by - view appearing.
  3. A custom name provided with reportName(_:).

Class names can be Swift-mangled and are usually less useful than a navigation title or custom name.

For a SwiftUI view, set a navigation title when possible:

import SwiftUI

struct ProductsView: View {
  var body: some View {
    List {
      Text("Elastic mug")
      Text("Elastic shirt")
    }
    .navigationTitle("Products")
  }
}
		

The span appears as Products - view appearing.

If you cannot set a navigation title, use reportName(_:):

import ElasticApm
import SwiftUI

struct ProductsView: View {
  var body: some View {
    List {
      Text("Elastic mug")
      Text("Elastic shirt")
    }
    .reportName("Products - view appearing")
  }
}
		
Note

reportName(_:) uses the complete string you provide. Include - view appearing if you want custom names to follow the SDK's default naming format.

EDOT iOS captures app crashes and reports them using the OpenTelemetry Events API.

A crash is stored on the device when it occurs. The SDK loads and exports the report on the next app launch as a log event with:

  • Event name crash.
  • Fatal severity.
  • Exception type, message, and stack trace.
  • The session ID from the crashed app session.
  • The last known network connection type on supported iOS devices.

Crash reporting is enabled by default.

Crash capture is turned off while a debugger is attached. A crash triggered during a normal Xcode debug session is not recorded.

To test crash reporting:

  1. In Xcode, select ProductSchemeEdit Scheme.
  2. Select Run, then open the Info tab.
  3. Clear Debug executable.
  4. Build and run the app.
  5. Trigger the crash.
  6. Launch the app again to send the pending crash report.

Alternatively, install the app, stop the Xcode session, and launch it from the device home screen before triggering the crash.

Note

Crash reports are sent on the next app launch, not at the time of the crash.

EDOT iOS records app CPU and memory usage:

Metric Description Unit
system.cpu.usage CPU used by the app's active threads Percentage
system.memory.usage Physical memory footprint of the app process Bytes

Both metrics include the attribute state=app.

EDOT iOS creates lifecycle log events when the app changes state.

The lifecycle.state attribute can have the following values:

Value App transition
active The app became active.
inactive The app is about to become inactive.
background The app entered the background.
foreground The app is about to enter the foreground.
terminate The app is about to terminate.

Automatic instrumentation captures telemetry only for the APIs and lifecycle events listed on this page. It cannot instrument:

  • Custom or proprietary frameworks.
  • Closed-source components without instrumentation support.
  • Application-specific business logic.

If your app uses code that is not covered by automatic instrumentation, use one of the following approaches:

  1. Native OpenTelemetry support — Some libraries include instrumentation provided by their vendor.
  2. Manual instrumentation — Use the OpenTelemetry-Swift APIs to create spans, metrics, and logs.

EDOT iOS currently uses OpenTelemetry-Swift 2.2.1 or later and OpenTelemetry-Swift Core 2.3.0 or later.