This guide shows you how to add custom telemetry to your iOS app using the AWS Distro for OpenTelemetry Swift.
Spans track operations in your app. Use them to measure how long something takes.
import OpenTelemetryApi
let tracer = OpenTelemetry.instance.tracerProvider.get(instrumentationName: "my-app")
let span = tracer.spanBuilder(spanName: "load_user_profile").startSpan()
defer { span.end() }
let user = database.getUser(userId: userId)
processUser(user)Add context to your spans with attributes:
func checkoutButton() {
let span = tracer.spanBuilder(spanName: "checkout")
.setAttribute(key: "cart.items", value: 3)
.setAttribute(key: "cart.total", value: 49.99)
.setAttribute(key: "payment.method", value: "credit_card")
.startSpan()
defer { span.end() } // close the span on function end
processCheckout()
}For async operations:
func performBackgroundTask() async {
let span = tracer.spanBuilder(spanName: "background_task").startSpan()
do {
try await doWork()
} catch {
span.recordException(error)
}
span.end()
}Events are point-in-time occurrences. Use them to track user actions or important moments.
import OpenTelemetryApi
let logger = OpenTelemetry.instance.loggerProvider.get(instrumentationScopeName: "my-app")
logger.eventBuilder(name: "button_clicked")
.emit()logger.eventBuilder(name: "purchase_completed")
.setBody(AttributeValue.string("User completed checkout"))
.setAttributes([
"order.id": AttributeValue.string("12345"),
"order.total": AttributeValue.double(99.99)
])
.emit()Track view appearance with the built-in AwsOTelTraceView wrapper:
import SwiftUI
import AwsOpenTelemetryCore
struct ContentView: View {
var body: some View {
AwsOTelTraceView("HomeScreen") {
VStack {
Text("Welcome")
}
}
}
}With custom attributes:
AwsOTelTraceView("ProductDetail", attributes: ["product.id": "12345"]) {
ProductDetailContent()
}Add attributes to all telemetry data:
import AwsOpenTelemetryCore
let manager = AwsGlobalAttributesProvider.getInstance()
manager.setAttribute(key: "user.tier", value: AttributeValue.string("premium"))
manager.setAttribute(key: "app.variant", value: AttributeValue.string("beta"))func fetchProducts() async throws -> [Product] {
let span = tracer.spanBuilder(spanName: "api_fetch_products").startSpan()
defer { span.end() }
do {
let response = try await apiClient.getProducts()
span.setAttribute(key: "response.status", value: response.statusCode)
span.setAttribute(key: "response.items", value: response.items.count)
return response.items
} catch {
span.recordException(error)
throw error
}
}@IBAction func submitButtonTapped(_ sender: UIButton) {
logger.eventBuilder(name: "form_submitted")
.setAttributes([
"form.type": AttributeValue.string("registration"),
"form.fields": AttributeValue.int(5)
])
.emit()
submitForm()
}Task {
let span = tracer.spanBuilder(spanName: "sync_data").startSpan()
let result = await syncRepository.sync()
span.setAttribute(key: "sync.records", value: result.count)
span.end()
}