Skip to main content

Performance Tracing

Overview

Embrace’s Performance Tracing solution gives you visibility into any app operation you’d like to track, including duration, success rate, and any contextual metadata collected at runtime that helps debug the root cause of your mobile app's performance issues. With our tool, you can quickly spot any bottlenecks in your app’s architecture, pinpoint areas you need to troubleshoot with high precision, and ultimately deliver a truly optimized user experience.

API Usage Examples

Start and stop a span

A span typically models the lifecycle operation in your app. You can start it, let the operation finish, then stop the span, and Embrace will record how long the span took.

final span = await Embrace.instance.startSpan('my-span');
// some lengthy operation
await span?.stop();

Add attributes to a span

If you have metadata values that relate to the entire span you can add these as attributes.

final span = await Embrace.instance.startSpan('my-span');
await span?.addAttribute('my-key', 'my-value');

Add events to a span

If you have an event that happens at a point in time within a span, you can add a span event. This can contain optional attributes about the event.

final span = await Embrace.instance.startSpan('my-span');
await span?.addEvent(
'my-event-name',
attributes: {
'my-event-attribute-key': 'my-event-attribute-value',
},
);

Record an operation that already happened

If an operation already happened or you don't want to call start/stop individually, it's possible to record that a span happened via recordCompletedSpan.

final start = DateTime.now().millisecondsSinceEpoch - 1000;
final end = start + 500;
final result = await Embrace.instance.recordCompletedSpan(
'my-recorded-span',
start,
end,
attributes: {'my-span-key': 'my-span-value'},
events: [
EmbraceSpanEvent(
name: 'my-span-event',
attributes: {'my-event-key': 'my-event-value'},
timestampMs: DateTime.now().millisecondsSinceEpoch,
)
],
);

Add child spans

It's possible to create child spans. This can be useful if you want to record finer details about an operation, for example, a network request span might have a child span of JSON serialization to see how long it took.

final span = await Embrace.instance.startSpan('my-span');

if (span != null) {
final childSpan =
await Embrace.instance.startSpan('child-span', parent: span);
await childSpan?.stop();
await span.stop();
}

Export to OpenTelemetry Collectors

To send telemetry to any OpenTelemetry Collector directly from your app you can setup a SpanExporter and LogRecordExporter. When configured, telemetry will be sent to these exporters as soon as they are recorded. More than one exporter of each signal can be configured, but be aware of the performance impact of sending too many network requests if that is applicable.

info

All telemetry in Embrace's Flutter SDK is routed through Embrace's Android/iOS SDKs so it's necessary to configure Android/iOS code to send Dart telemetry to your desired destination.

Android OTel export

Please follow this guide to setup OpenTelemetry collectors on Android.

iOS OTel export

Please follow this guide to setup OpenTelemetry collectors on iOS.

info

Please note the OpenTelemetry-Swift repository does not support Cocoapods so you will be unable to import ready-made exporters directly. We recommend adding a new file that implements SpanExporter or LogRecordExporter directly, and using the ready-made exporters as reference implementations.