Skip to main content

View Capture Service

The ViewCaptureService is in charge of automatically instrumenting UIViewController load and render times. You can customize the service behavior by passing a custom ViewCaptureService when setting up the Embrace SDK:

let services = CaptureServiceBuilder()
.add(.view(options: ViewCaptureService.Options(instrumentVisibility: true, instrumentFirstRender: true)))
.addDefaults()
.build()

try Embrace
.setup(
options: Embrace.Options(
appId: "APPID",
captureServices: services
//...other options
)
)
.start()

Customization

The EmbraceViewControllerCustomization protocol allows you to customize UIViewControllers for Embrace capture at an individual level.

The shouldCaptureViewInEmbrace variable allows you to prevent the Embrace SDK from generating data for that UIViewController.

The nameForViewControllerInEmbrace variable allows you to customize the name for the screen (the class name is used by default).

Screen visibility

This feature is enabled by setting instrumentVisibility to true in the ViewCaptureService.Options. The service will generate spans that start when a UIViewController appears (viewDidAppear) and ends when it disappears (viewDidDisappear).

Time to First Render

This feature is enabled by setting instrumentFirstRender to true in the ViewCaptureService.Options.

The service will generate spans that start when a UIViewController is loaded (viewDidLoad) and ends when it becomes visible for the first time (viewDidAppear). Additionally, the service generates child spans measuring several steps in the process: viewDidLoad, viewWillAppear, viewIsAppearing (measuring the time from the end of viewWillAppear to the start of viewDidAppear, including animations), and viewDidAppear.

info

If the UIViewController disappears before it finishes loading, the spans status will be set to .error with the .userAbandon code.

warning

If you're using the Embrace Dashboard with your app, you might need to contact an Embrace representative to enable this feature through the remote configuration.

If you're not using the Embrace Dashboard, you can enable this feature by passing a custom EmbraceConfigurable with isUiLoadInstrumentationEnabled set to true when initializing the SDK.

Time to Interactive

This feature is enabled by setting instrumentFirstRender to true in the ViewCaptureService.Options, and making a UIViewController implement the InteractableViewController protocol.

The service will generate spans that start when a UIViewController is loaded (viewDidLoad) and ends when it is flagged as ready for interaction (setInteractionReady()). If you implement this protocol in one of your UIViewControllers, you need to call setInteractionReady() when the screen is ready to be interacted by the user.

Example:

class MyViewController: UIViewController, InteractableViewController {

override func viewDidLoad() {
super.viewDidLoad()

// some async operation
MyDataFetcher.fetch { [weak self] data in
self?.loadData(data)
self?.setInteractionReady()
}
}
}
info

If the UIViewController disappears before it is flagged as ready for interaction, the spans status will be set to .error with the .userAbandon code.

warning

If you're using the Embrace Dashboard with your app, you might need to contact and Embrace representative to enable this feature through the remote configuration.

If you're not using the Embrace Dashboard, you can enable this feature by passing a custom EmbraceConfigurable with isUiLoadInstrumentationEnabled set to true when initializing the SDK.

Custom child spans

When the first render instrumentation is enabled, you can also add custom child spans to the ones automatically generated by the service. You'll need to implement the InstrumentableViewController protocol and use the buildChildSpan or recordCompletedChildSpan methods

Example:

class MyViewController: UIViewController, InstrumentableViewController {

override func viewDidLoad() {
super.viewDidLoad()

let childSpan = buildChildSpan(name: "data-fetch").startSpan()

// some async operation
MyDataFetcher.fetch { [weak self] data in
self?.loadData(data)
childSpan.end()
}
}
}

Adding Attributes to the Trace

When the first render instrumentation is enabled, you can also add custom attributes to the trace generated by the service. To do this, you can use the addAttributesToTrace(_:) method provided by the InstrumentableViewController protocol.

Example:

class MyViewController: UIViewController, InstrumentableViewController {
override func viewDidLoad() {
super.viewDidLoad()
try? instrumentView()
}

func instrumentView() throws {
try addAttributesToTrace(
[
"custom_attribute_key": "custom_attribute_value",
"other_attribute_key": "other_attribute_value",
]
)
}
}