Skip to main content

FAQ

Embrace Apple SDK 7.x FAQ​

Questions we commonly receive about the 7.x Apple SDK, along with their answers. For questions that apply to every version of the Apple SDK, see the Apple SDK FAQ.

If you don't see your question here, or would like more clarification on one, please reach out to us on the community Slack or email us at support@embrace.io.

OpenTelemetry and Embrace types​

Why did Embrace introduce its own types (EmbraceSpan, EmbraceLog) rather than continue to use OpenTelemetry SDK types?​

The shift to Embrace-owned types is primarily about giving us more control over the experience we provide to customers, while still building around OpenTelemetry standards. A few of the key benefits are:

  • Sensible safeguards for mobile telemetry. OpenTelemetry is intentionally flexible and doesn't prescribe strong opinions around things like signal limits. By owning the data flow from the point a signal is created, Embrace can apply appropriate limits, sanitization, and protections early, helping prevent unexpected and excessive telemetry volume and ensuring the data sent to the backend is valid and useful.
  • A better experience for Embrace-specific capabilities. Features such as automatic span termination can be implemented cleanly and predictably rather than being layered awkwardly on top of APIs we don't control.
  • A more stable API for customers. By owning our public API, we can evolve Embrace independently without exposing customers to breaking changes or implementation details from underlying third-party libraries.
  • More flexibility over time. This gives us room to continue adopting and supporting OpenTelemetry conventions while optimizing the SDK and pipeline for the needs of mobile applications and Embrace customers.
  • Alignment with Embrace Android. The Android SDK has taken this approach since its 6.0 release. EmbraceSpan is an Embrace-owned type there too, and direct OpenTelemetry access is confined to explicit accessors. Apple 7.0 brings the two platforms onto the same model, so concepts, limits, and behavior are consistent for teams shipping both.

See Architecture for the full list of Embrace-owned types and their 6.x OpenTelemetry equivalents.

Can I still export telemetry to my own OpenTelemetry collector or backend?​

Yes. We are firm believers in OpenTelemetry and the interoperability it brings, and owning the public API types did not close the OpenTelemetry export path. Construct an EmbraceIO.OTelOptions and pass it as the otel parameter of EmbraceIO.Options when you start the SDK:

let otel = EmbraceIO.OTelOptions(
resource: myResource,
spanExporters: [myOTLPSpanExporter],
logExporters: [myOTLPLogExporter]
)

OTelOptions accepts the standard OpenTelemetry Swift SDK types — SpanProcessor, SpanExporter, LogRecordProcessor, and LogRecordExporter. Your processors and exporters are attached as children of Embrace's own, so they receive every signal the SDK records, delivered as ordinary OTel SpanData and ReadableLogRecord.

You can also supply a custom Resource. Its attributes take priority over the ones Embrace generates, except service.name, service.version, and telemetry.sdk.language, which the SDK always owns and which can't be overridden.

For complete examples, including OTLP export over HTTP and gRPC and writing a custom exporter, see OpenTelemetry Export.

Can I feed my own OpenTelemetry instrumentation through Embrace?​

Yes. EmbraceIO.shared exposes the TracerProvider and LoggerProvider that back the Embrace pipeline, plus tracer(instrumentationName:instrumentationVersion:) and logger(instrumentationScopeName:instrumentationVersion:) convenience accessors:

let span = EmbraceIO.shared
.tracer(instrumentationName: "com.mycompany.checkout")?
.spanBuilder(spanName: "checkout")
.startSpan()

Spans and logs created this way are captured by Embrace, forwarded to your custom processors and exporters, and count against the same per-session limits as createSpan and log. The accessors return nil unless you started the SDK with an EmbraceIO.OTelOptions — an empty one is enough.

If you want third-party OpenTelemetry libraries that resolve OpenTelemetry.instance to emit through Embrace without configuring them yourself, start the SDK with EmbraceIO.OTelOptions(registersGlobalProviders: true). Unlike 6.x, which always registered its providers globally, 7.x leaves the process-wide providers alone unless you opt in. See OpenTelemetry Providers.

For your own app code, we still recommend EmbraceIO.shared.createSpan(...) and EmbraceIO.shared.log(...) — the providers are there for instrumentation that is already written against the OpenTelemetry API.

Is the data Embrace sends still OpenTelemetry-compliant?​

Yes — the OpenTelemetry data model is intact. What 7.0 changed is the type you hold in your app code, not the telemetry underneath it. Everything the SDK captures is available as standard OpenTelemetry signals and can be exported to any OpenTelemetry-compatible backend.

Upgrading from 6.x​

What do I need to change in my code when upgrading from 6.x?​

Most changes are mechanical renames, but two are conceptual and worth reading in full: the single EmbraceIO entry point and the redefined session model. The migration guide covers every breaking change.

There is also a Claude Code skill that inventories every 6.x call site in your codebase, rewrites the startup call and the renamed APIs, flags the removals that need a decision from you, and builds the project to verify the result.