AWS Distro for OpenTelemetry (ADOT) Swift is a redistribution of the OpenTelemetry Swift, configured with in-house instrumentations to use with AWS CloudWatch Real User Monitoring.
At this time, we only officially support iOS 16+. However, we also have continuation integration in place for latest versions of macOS, tvOS, watchOS, and visionOS.
| Instrumentation | Description | Documentation |
|---|---|---|
| App Launch | App launches (cold, warm, and pre-warm) | App Launch README |
| Crashes | Crashes with on-device symbolication in Apple format via KSCrash | Crashes |
| Hangs | Application hang detection with live stack traces | Hangs |
| Network | Network requests (currently limited to URLSession) | Network README |
| UIKit | View instrumentation for UIKit | UIKitView README |
| SwiftUI | View instrumentation for SwiftUI | SwiftUI README |
| Session Events | Session lifecycle tracking with start and end events | Sessions README |
| Metadata | Attribute Name | Description |
|---|---|---|
| Session IDs | session.id |
UID for the current user session, which by default expires after 30 minutes of inactivity |
| User IDs (anonymous) | user.id |
Anonymous UID to enumerate the current user |
| Screen names | screen.name |
The name of the current screen |
| Battery usage | hw.battery.charge |
Battery level as percentage (0.0-1.0) |
| CPU usage | process.cpu.utilization |
CPU utilization ratio (0.0-8.0+) |
| Memory usage | process.memory.usage |
Memory usage in megabytes |
| Device data | device.model, os.version, etc. |
Hardware and OS information |
| Network data | network.carrier, network.connection.type, etc. |
Network connectivity information |
Add the following to your Package.swift file:
dependencies: [
.package(url: "https://github.com/aws-observability/aws-otel-swift.git", .upToNextMajor(from: "1.0.0"))
]At this time, Cocoapods distribution is not supported. Please open an issue to get this work prioritized.
Add AwsOpenTelemetryAgent to target dependencies. This will automatically setup the AWS OTel agent using AwsOpenTelemetryCore as a transitive dependency.
targets: [
.target(
name: "<your app target>",
dependencies: [
.product(name: "AwsOpenTelemetryAgent", package: "aws-otel-swift")
]
)
]Then add aws_config.json to your application bundle. See AwsHackerNewsDemo for a complete example.
{
"aws": {
"rumAppMonitorId": "<your app monitor id>",
"region": "<your app monitor region>"
},
"otelResourceAttributes": {
"service.name": "<your application name>",
"service.version": "1.0.0"
}
}Add AwsOpenTelemetryCore to package dependencies. This option is recommended if you would like to directly manage our dependency on OTel.
targets: [
.target(
name: "<your app target>",
dependencies: [
.product(name: "AwsOpenTelemetryCore", package: "aws-otel-swift")
]
)
]Initialize the ADOT OTel Agent in your AppDelegate
import AwsOpenTelemetryCore
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
AwsOpenTelemetryRumBuilder.create(
config: AwsOpenTelemetryConfig(
aws: AwsConfig(
rumAppMonitorId: "<your app monitor id>",
region: "<your app monitor region>"
),
otelResourceAttributes: [
"service.name": "<your application name>",
"service.version": "1.0.0"
]
)
)?.build()
return true
}
}| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| aws | AwsConfig |
Yes | nil | AWS service configuration settings (see AwsConfig section) |
| exportOverride | AwsExportOverride |
No | nil | Export endpoint overrides for custom logs and traces endpoints (see AwsExportOverride section) |
| sessionTimeout | Int |
No | 30 * 60 | Session timeout in seconds. When nil, uses default value |
| sessionSampleRate | Double |
No | 1.0 | Session sample rate from 0.0 to 1.0. When nil, uses default value |
| otelResourceAttributes | Object |
No | nil | Key-value pairs for resource metadata, which are added as resource attributes |
| telemetry | AwsTelemetryConfig |
No | all enabled | Telemetry feature configuration settings (see AwsTelemetryConfig section) |
| debug | Boolean |
No | false | Flag to enable local logging for debugging purposes. |
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| region | String | Yes | - | AWS region where the RUM service is deployed |
| rumAppMonitorId | String | Yes | - | Unique identifier for the RUM App Monitor |
| rumAlias | String | No | nil | Adds an alias to all requests. It will be compared to the rum:alias service context key in the resource based policy attached to a RUM app monitor. See public docs for using an alias with a RUM resource based policy. |
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| logs | String | No | nil | Custom endpoint for log exports. When nil, uses AWS CloudWatch RUM OTLP endpoint https://dataplane.rum.${region}.amazonaws.com/v1/rum |
| traces | String | No | nil | Custom endpoint for trace exports. When nil, uses AWS CloudWatch RUM OTLP endpoint https://dataplane.rum.${region}.amazonaws.com/v1/rum |
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| startup | Object | No | { "enabled": true } | Generate app launch diagnostic as log records. |
| sessionEvents | Object | No | { "enabled": true } | Creates session.start and session.end as log records according to OpenTelemetry Semantic Convention. As an ADOT-Swift extension, session.end also includes duration and end_time. |
| crash | Object | No | { "enabled": true } | Generate crash diagnostic as log records. |
| network | Object | No | { "enabled": true } | Generate spans of URLSession HTTP requests directly from OTel Swift's implementation of URLSessionInstrumentation. HTTP requests to the logs and spans endpoints are ignored to avoid infinite recursion. |
| hang | Object | No | { "enabled": true } | Generate hang diagnostic as log records. |
| view | Object | No | { "enabled": true } | Create spans from views created with UIKit and SwiftUI. |
The AWS OpenTelemetry Swift SDK uses OTLP (OpenTelemetry Protocol) over HTTP to export telemetry data to AWS CloudWatch RUM. The SDK supports multiple authentication methods and export configurations.
By default, the SDK exports telemetry data with unsigned requests, which is the recommended pattern for monitoring real users. Please refer to AWS docs for allowing unauthenticated ingestion via RUM resource based policy.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| maxRetries | Int |
No | 3 | Maximum number of retry attempts |
| retryableStatusCodes | Set<Int> |
No | [408, 429, 500, 502, 503, 504, 509] | HTTP status codes that trigger retry logic |
| maxBatchSize | Int |
No | 100 | Maximum batch size for exports |
| maxQueueSize | Int |
No | 1048 | Maximum in-memory queue size (separate queues for logs and spans) |
| batchInterval | TimeInterval |
No | 5.0 | Batch export interval in seconds |
| exportTimeout | TimeInterval |
No | 30.0 | Export timeout in seconds |
| compression | CompressionType |
No | .gzip | Compression type for OTLP exports |
See the AwsExportConfig for detailed configuration options.
For scenarios requiring authenticated requests, the SDK supports AWS Signature Version 4 (SigV4) authentication using the AwsOpenTelemetryAuth module:
import AwsOpenTelemetryCore
import AwsOpenTelemetryAuth
class CustomIdentityProvider: CredentialsProviding {
func getCredentials() async throws -> Credentials {
// Your custom credential logic here
return Credentials(...)
}
}
// Create SigV4 exporters (uses default AWS RUM regional endpoints)
let customProvider = CustomIdentityProvider()
let sigV4SpanExporter = AwsSigV4SpanExporter(
region: "us-east-1",
credentialsProvider: customProvider
)
let sigV4LogExporter = AwsSigV4LogRecordExporter(
region: "us-east-1",
credentialsProvider: customProvider
)
// Add to agent builder
AwsOpenTelemetryRumBuilder.create(config: config)?
.addSpanExporterCustomizer { _ in sigv4SpanExporter }
.addLogRecordExporterCustomizer { _ in sigv4LogExporter }
.build()- Read more about configuring the SDK with authentication
- See the AwsOpenTelemetryAuth README for detailed explanations on AwsOpenTelemetryAuth
| Method | Support Status | Description |
|---|---|---|
| Server-side | ❌ Not supported | Please open an issue to prioritize this important feature! |
| On-device | ✅ Supported | Enable on-device symbolication via KSCrash by setting Strip Style to Debugging Symbols, which comes with the tradeoff of approximately ~5% increase in binary size. |
| Offline | ✅ Supported | We've provided a script in Examples/Symbolication to help with offline symbolication via atos, which also includes swift demangling. Offline symbolication is always possible via XCode or the native atos tool . |
You can create custom span and log events using the OpenTelemetry APIs. The SDK provides convenient access to configured tracer and logger instances. All events are populated with available metadata by ADOT Swift.
Please be mindful about the following restrictions:
- AWS RUM OTLP endpoint enforces a 30KB limit on attribute size. If an event attribute exceeds the limit, then it is dropped from the payload.
- AWS RUM OTLP endpoint requires
spanNameto be set for successful ingestion. - AWS RUM OTLP endpoint requires log to be events, so you must set log
eventNamefor successful ingestion.
Read more about custom events you can manually record
Use spans for events with durations and tracing support (read more). Warning: spanName must be set for successful ingestion.
// Example: a database query can be recorded as a span
import AwsOpenTelemetryCore
import OpenTelemetryApi
// Get the configured tracer
let tracer = AwsOpenTelemetryAgent.getTracer()
// Track a database query operation
let span = tracer.spanBuilder(spanName: "database.query") // `spanName` is REQUIRED
.startSpan()
span.setAttribute(key: "db.operation", value: "SELECT")
span.setAttribute(key: "db.table", value: "users")
// Perform the database operation
let users = await fetchUsers()
// End the span when operation completes
span.end()Use logs for point-in-time events (read more). Warning: log eventName must be set for successful ingestion.
// Example: a user login can be recorded as a log record.
import AwsOpenTelemetryCore
import OpenTelemetryApi
// Get the configured logger
let logger = AwsOpenTelemetryAgent.getLogger()
// Log a login event
logger.logRecordBuilder()
.setEventName("user.login") // `eventName` is REQUIRED
.emit()See CONTRIBUTING.md for detailed testing instructions, development setup, and contributor guidelines.
This project is licensed under the Apache-2.0 License.
{ "aws": { "region": "<your app monitor region", "rumAppMonitorId": "<your app monitor id>", "rumAlias": "<your app monitor alias" // if resource based policy requires alias }, "exportOverride": { "logs": "http://localhost:3000/v1/logs", // custom logs otlp endpoint "traces": "http://localhost:3000/v1/traces" // custom traces otlp endpoint }, "sessionTimeout": 1800, // in seconds (default 30 minutes) "sessionSampleRate": 1.0, // as ratio from 0.0 -> 1.0 "otelResourceAttributes": { "service.version": "1.0.0", // optional "service.name": "<your app name>" // optional }, "telemetry": { "startup": { "enabled": true }, "sessionEvents": { "enabled": true }, "crash": { "enabled": true }, "hang": { "enabled": true }, "network": { "enabled": true }, "view": { "enabled": true } }, "debug": false // [for dev only] locally print info/warn/debug logs }