Our automatic instrumentation relies on Objective-C method “swizzling” — amending the behavior of selectors at runtime – to wrap framework method calls to take measurements. This page describes our usage, and the justification for it, as well as providing options for avoiding its usage in your app.
Every care is taken to ensure this is done without negative impact to the functionality and performance of your app and takes place as early as possible in the Objective-C initialization phase and the app is still single-threaded, to eliminate unexpected behavior changes or conflicts with other method swizzling in your app or by other libraries.
The following methods are wrapped using swizzling:
If you do not wish to having swizzled methods in your app, the automatic network request and view load instrumentation can be disabled using the autoInstrumentNetworkRequests
and autoInstrumentViewControllers
configuration options.
However because swizzling is applied so early in the app’s startup, to prevent any method swizzling being registered, you will need to set the disableSwizzling
key in your app’s Info.plist
:
<key>bugsnag</key>
<dict>
<key>performance</key>
<dict>
<key>disableSwizzling</key>
<true/>
</dict>
</dict>
Without automated instrumentation of network requests and view loads, no measurements will be taken for these areas of your dashboard. You can instead send these measurements by calling startViewLoadSpan
and reportNetworkRequestSpan
methods yourself in the appropriate places in your app.
For example in URLSessionTaskDelegate
URLSession:task:didFinishCollectingMetrics
:
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics {
[Bugsnag reportNetworkRequestSpanWithTask:task metrics:metrics];
}
func urlSession(_ session: URLSession, task: URLSessionTask,
didFinishCollecting metrics: URLSessionTaskMetrics) {
Bugsnag.reportNetworkRequestSpan(task: task, metrics: metrics)
}
And for view loads in viewDidLoad
and viewDidAppear
:
- (void)viewDidLoad {
self.span = [BugsnagPerformance
startViewLoadSpanWithName:@"MyViewController"
viewType:BugsnagPerformanceViewTypeUIKit];
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.span end];
}
override func viewDidLoad() {
span = BugsnagPerformance.startViewLoadSpan(
name: "MyViewController", viewType: .uiKit)
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated);
span?.end()
span = nil
}