Skip to main content

Capture Services

Capture Services​

Capture Services are core components of the Embrace SDK that provide automatic instrumentation of your application. Each service focuses on capturing specific types of data and events.

Available Capture Services​

The SDK includes the following built-in capture services:

  • NetworkCaptureService - Captures HTTP/HTTPS network requests and responses
  • ViewCaptureService - Tracks UIViewController lifecycle and performance
  • TapCaptureService - Records user interaction with your app's interface
  • WebViewCaptureService - Monitors WKWebView performance and errors
  • LowMemoryWarningCaptureService - Detects low memory warnings
  • LowPowerModeCaptureService - Tracks low power mode
  • PushNotificationCaptureService - Captures push notification events
  • HangCaptureService - Captures app hangs (opt-in — not included in the defaults)

NetworkCaptureService​

Captures network requests and responses to provide visibility into API performance, error rates, and data transfer volumes.

Options​

struct NetworkCaptureServiceOptions {
init(
captureRequestHeaders: Bool = true,
captureResponseHeaders: Bool = true,
captureBodies: NetworkBodyCaptureOptions = .none,
urlPatternBlocklist: [String] = [],
headerKeys: HeaderFilterKeys = .init(),
requestHeaderFilter: ((URLRequest) -> [String: String]?)? = nil,
responseHeaderFilter: ((URLResponse) -> [String: String]?)? = nil,
requestBodyCapturePredicate: ((URLRequest, Data?) -> Bool)? = nil,
responseBodyCapturePredicate: ((URLRequest, URLResponse?, Data?) -> Bool)? = nil
)
}

Parameters:

  • captureRequestHeaders: Whether to capture request headers.
  • captureResponseHeaders: Whether to capture response headers.
  • captureBodies: Options for capturing request and response bodies.
  • urlPatternBlocklist: List of URL patterns to exclude from capture.
  • headerKeys: Configuration for header key filtering.
  • requestHeaderFilter: Custom filter for request headers.
  • responseHeaderFilter: Custom filter for response headers.
  • requestBodyCapturePredicate: Custom predicate for determining when to capture request bodies.
  • responseBodyCapturePredicate: Custom predicate for determining when to capture response bodies.

NetworkBodyCaptureOptions​

enum NetworkBodyCaptureOptions {
case none
case request
case response
case both
}

GitHub Source: EmbraceCaptureService

ViewCaptureService​

Captures UIViewController lifecycle events to measure screen load times, rendering performance, and navigation patterns.

Options​

struct ViewCaptureServiceOptions {
init(
captureFrameRates: Bool = true,
viewNameProvider: ((UIViewController) -> String?)? = nil,
viewAttributesProvider: ((UIViewController) -> [String: String]?)? = nil,
viewNameFilter: ((UIViewController) -> Bool)? = nil
)
}

Parameters:

  • captureFrameRates: Whether to capture frame rate information.
  • viewNameProvider: Custom function for providing view names.
  • viewAttributesProvider: Custom function for providing additional view attributes.
  • viewNameFilter: Filter function to determine which views to track.

GitHub Source: EmbraceCaptureService

TapCaptureService​

Captures user tap interactions to provide insights into user engagement and interaction patterns.

Options​

struct TapCaptureServiceOptions {
init(
captureCoordinates: Bool = true,
targetProvider: ((UIView) -> String?)? = nil,
viewFilter: ((UIView) -> Bool)? = nil
)
}

Parameters:

  • captureCoordinates: Whether to capture tap coordinates.
  • targetProvider: Custom function for providing tap target identifiers.
  • viewFilter: Filter function to determine which views to track taps for.

GitHub Source: EmbraceCaptureService

WebViewCaptureService​

Captures WKWebView loading performance and JavaScript errors.

Options​

struct WebViewCaptureServiceOptions {
init(
captureJavaScriptErrors: Bool = true,
captureJavaScriptLogs: Bool = false
)
}

Parameters:

  • captureJavaScriptErrors: Whether to capture JavaScript errors.
  • captureJavaScriptLogs: Whether to capture JavaScript console logs.

GitHub Source: EmbraceCaptureService

PushNotificationCaptureService​

Captures push notification events including arrivals and user interactions.

Options​

struct PushNotificationCaptureServiceOptions {
init(
captureNotificationContent: Bool = false,
payloadAttributesFilter: ((UserInfo) -> [String: String]?)? = nil
)
}

Parameters:

  • captureNotificationContent: Whether to capture notification content.
  • payloadAttributesFilter: Filter for notification payload attributes to capture.

GitHub Source: EmbraceCaptureService

LowMemoryWarningCaptureService​

Captures low memory warning events from iOS.

This service doesn't have configurable options.

GitHub Source: EmbraceCaptureService

LowPowerModeCaptureService​

Captures device low power mode state changes.

This service doesn't have configurable options.

GitHub Source: EmbraceCaptureService

HangCaptureService​

Captures main-thread hangs as emb-thread-blockage spans, by monitoring frame delivery with CADisplayLink. Requires SDK 6.19.0 or later.

This service is opt-in. It is not added by EmbraceIO.CaptureServicesOptions.default() nor by CaptureServiceBuilder.addDefaults() — you must register it explicitly:

  • With EmbraceIO: CaptureServicesOptionsBuilder().addDefaults().addHangCaptureService().build()
  • With Embrace: CaptureServiceBuilder().addDefaults().add(HangCaptureService()).build()

This service is turned off when attached to a debugger (ie: while debugging in Xcode). You can enable it when connected to a debugger by setting the EMBAllowWatchdogInDebugger environment var to 1.

HangCaptureService(limits:) accepts a HangLimits, but the SDK replaces it with the active configuration's hangLimits at setup and on every config refresh — in an appId setup, limits always come from remote configuration.

For full configuration details (including HangLimits), see Hang Detection.

GitHub Source: HangCaptureService

Custom Capture Services​

You can also extend the SDK by creating your own custom capture services.

Implementing a Custom Capture Service​

Custom capture services must conform to the CaptureService protocol:

protocol CaptureService {
var type: CaptureServiceType { get }
func setup(with dependencies: EmbraceCaptureDependencies) -> Bool
func stop()
}

Code Examples​

Configuring Network Capture​

let networkOptions = NetworkCaptureServiceOptions(
captureRequestHeaders: true,
captureResponseHeaders: true,
urlPatternBlocklist: [
"^https://analytics\\.example\\.com",
"^https://.*\\.sensitiveapi\\.com"
],
headerKeys: .init(
requestHeadersBlocklist: ["Authorization", "Cookie"],
responseHeadersBlocklist: ["Set-Cookie"]
)
)

let services = CaptureServiceBuilder()
.add(.network(options: networkOptions))
.build()

let options = EmbraceIO.Options.withAppId(
"YOUR_APP_ID",
captureServices: services
)

Configuring View Capture​

let viewOptions = ViewCaptureServiceOptions(
captureFrameRates: true,
viewNameProvider: { viewController in
// Use a custom name based on view properties
if let tabController = viewController as? UITabBarController {
return "Tab-\(tabController.selectedIndex)"
}
// Default to class name
return String(describing: type(of: viewController))
},
viewAttributesProvider: { viewController in
// Add custom attributes to view spans
if let productVC = viewController as? ProductViewController {
return [
"product_id": productVC.productId,
"category": productVC.category
]
}
return nil
},
viewNameFilter: { viewController in
// Only capture main screens, not utility views
return !(viewController is UIAlertController)
}
)

let services = CaptureServiceBuilder()
.add(.view(options: viewOptions))
.build()

Configuring Tap Capture​

let tapOptions = TapCaptureServiceOptions(
captureCoordinates: true,
targetProvider: { view in
// Provide meaningful names for tap targets
if let button = view as? UIButton, let label = button.titleLabel?.text {
return "Button-\(label)"
}
if let cell = view as? UITableViewCell, let identifier = cell.reuseIdentifier {
return "Cell-\(identifier)"
}
return view.accessibilityIdentifier
},
viewFilter: { view in
// Only capture taps on interactive elements
return view is UIButton || view is UITableViewCell || view.isUserInteractionEnabled
}
)

let services = CaptureServiceBuilder()
.add(.tap(options: tapOptions))
.build()

Configuring All Capture Services​

let services = CaptureServiceBuilder()
.add(.network(options: networkOptions))
.add(.view(options: viewOptions))
.add(.tap(options: tapOptions))
.add(.webView(options: webViewOptions))
.add(.pushNotification(options: pushOptions))
.add(.lowMemoryWarning)
.add(.lowPowerMode)
.add(HangCaptureService()) // opt-in
.build()

let options = EmbraceIO.Options.withAppId(
"YOUR_APP_ID",
captureServices: services
)