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
.
If the UIViewController
disappears before it finishes loading, the spans status will be set to .error
with the .userAbandon
code.
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()
}
}
}
If the UIViewController
disappears before it is flagged as ready for interaction, the spans status will be set to .error
with the .userAbandon
code.
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",
]
)
}
}