OneAgent SDK for iOS
The OneAgent SDK for iOS can be used to report additional details about the mobile user sessions in your app. The OneAgent SDK for iOS allows you to create custom user actions, measure web requests, report errors, and tag specific users. The following sections explain how to enable these capabilities.
For iOS, the OneAgent SDK is available automatically once you add the DESK CocoaPod to your project. The OneAgent SDK for Mobile can be used in Swift as well as in Objective-C.
You can define your own user actions. After you create them, enhance them with additional information before finally closing them. OneAgent discards all action-related monitoring data when the action isn't closed.
You must call enterActionWithName
to start each action and leaveAction
to close each action. Timing is measured automatically.
// start action "search"
let action = DTXAction.enter(withName: "search")
// ...do some work here...
// end action "search"
action.leave()
// start action "search"
DTXAction *action = [DTXAction enterActionWithName:@"search"];
// ...do some work here...
// end action "search"
[action leaveAction];
With a user action you can perform the following monitoring operations:
- report an event
- report a value
- report an error
- attach a web request to the user action
- create a child action
With reportEvent
, you can report a specific event. The event must belong to a user action.
let myAction = DTXAction.enter(withName: "My action")
myAction?.reportEvent(withName: "Something important just happened")
myAction?.leave()
// report an event
- (DTX_StatusCode) reportEventWithName:(NSString *)eventName
With reportError
, you can report a specific event as an error event. This will be displayed in the user action waterfall analysis. There are two variants of an error event. In the first variant, the error is part of a user action, while in the second, the error is generated as a global event (not tied to a specific action).
You can report an error with an error code, an exception, or an NSError
.
- Global error (not bound to a specific user action)
DTXAction.reportError(withName: "My custom error", error: NSError(domain: "Global issue", code: 007, userInfo: nil))
- Error bound to a specific user action
let myAction = DTXAction.enter(withName: "My action") myAction.reportError(withName: "My custom error", error: NSError(domain: "Action issue", code: 007, userInfo: nil)) myAction?.leave()
// report an error
DTXAction *action;
NSError* error;
[action reportErrorWithName:@"CommunicationError" errorValue:[error code]];
The reportValue
method allows you to report your own metrics. These metrics must be part of a user action. The OneAgent SDK allows you to report int
, double
, and String
values.
let myAction = DTXAction.enter(withName: "My action")
myAction?.reportValue(withName: "My int value", intValue: 1234)
myAction?.reportValue(withName: "My double value", doubleValue: 12.34)
myAction?.reportValue(withName: "My string value", stringValue: "Hello World!")
myAction?.leave()
- (DTX_StatusCode) reportValueWithName:(NSString *)valueName
intValue:(NSInteger)value
- (DTX_StatusCode) reportValueWithName:(NSString *)valueName
doubleValue:(double)doubleValue
- (DTX_StatusCode) reportValueWithName:(NSString *)valueName
stringValue:(NSString *)stringValue
To monitor a web request, the DESK tag has to be placed on the HTTP request. The tag is needed to correlate the server-side monitoring data to the corresponding mobile web request. Additionally, the timing values from the mobile side have to be measured.
The OneAgent SDK for iOS automatically times web requests made by using NSURLRequest
, NSURLConnection
, NSURLSession
, NSURLProtocol
, NSString
, UIWebView
and WKWebView
. Manual web request tagging/timing is only necessary when the automatic instrumentation of web requests is disabled or when requests of a 3rd-party framework aren't instrumented.
Simplified web request timing/tagging demo
import UIKit
import WebKit
import DESK
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let wkWebView = WKWebView(frame: self.view.frame)
self.view.addSubview(wkWebView)
manualTaggingDemo(wkWebView: wkWebView)
}
func manualTaggingDemo(wkWebView: WKWebView) {
let parentAction = DTXAction.enter(withName: #function)
let url = URL(string: "https://www.desk.com")
downloadRequest(url: url!, wkWebView: wkWebView, parentAction: parentAction) //as this is async parent action should be left when request is done
}
func downloadRequest(url: URL, wkWebView: WKWebView, parentAction: DTXAction?) {
let childAction = DTXAction.enter(withName: #function, parentAction: parentAction) //add child action to see method call trace
let session = URLSession.shared
let request = NSMutableURLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = .reloadIgnoringCacheData
var webrequestTiming: DTXWebRequestTiming?
if let deskHeaderValue = DESK.getRequestTagValue(for: url) {
let deskHeaderKey = DESK.getRequestTagHeader() //this could be cached as it always is x-desk
request.addValue(deskHeaderValue, forHTTPHeaderField: deskHeaderKey)
webrequestTiming = DTXWebRequestTiming.getDTXWebRequestTiming(deskHeaderValue, request: url)
}
let task = session.downloadTask(with: request as URLRequest) {
(location, response, error) in
defer {
parentAction?.leave() //leave parent action when request finished - all child actions are automaticlly left on leaving parent
}
guard let _:URL = location, let _:URLResponse = response, error == nil else {
webrequestTiming?.stop("failed") //stop webrequest timing in error case
return
}
let urlContents = try! String(contentsOf: location!, encoding: .utf8)
guard !urlContents.isEmpty else {
webrequestTiming?.stop("empty content") //stop webrequest timing in error case
return
}
webrequestTiming?.stop((response as! HTTPURLResponse).statusCode.description) //stop webrequest when request finished
DispatchQueue.main.async {
wkWebView.loadHTMLString(urlContents, baseURL: nil)
}
}
webrequestTiming?.start() //start webrequest timing
task.resume()
}
}
You can tag each user of your mobile apps with a unique user name. This enables you to search and filter specific user sessions and analyze individual user behavior over time. The following steps explain how to manually tag an individual user via the DESK API. This API must be called, for example, when a user logs in or when an already logged in session is used or restored upon app relaunch, as the tag isn't persisted over app restarts.
DESK.identifyUser("userId")
[DESK identifyUser:@"userId"];
You can force a session to end via the DESK API.
DTXAction.endVisit()
[DTXAction endVisit];
As of version 7.1.4, the OneAgent SDK for iOS allows you to dynamically adjust data-privacy settings so that you can build your apps in compliance with GDPR data-privacy regulations. To activate this feature, enable the DTXUserOptIn
flag.
The privacy API methods allow you to dynamically activate/deactivate crash reporting and to change the data-collection level based on the individual preferences of your end users. Each end user can select from three data-privacy levels:
off
: OneAgent doesn't capture any monitoring data.performance
: OneAgent only captures anonymous performance data. Monitoring data that can be used to identify individual users (for example, user tags or custom values) isn't captured.user behavior
: OneAgent captures both performance and user data. In this mode OneAgent recognizes and reports users who re-visit in future sessions.
When OneAgent starts for the first time, it deactivates crash reporting and sets the data-collection level to off
. You should change the privacy settings (based on each user's individual preference) when your app starts for the first time. OneAgent doesn't provide a privacy settings dialog or any similar UI component. You must integrate a privacy dialog into your app. We recommend that you display the privacy dialog before your app is displayed and then apply the user's privacy preference. You must also provide your users with an option to change their privacy settings in the future.
OneAgent persists the privacy setting and automatically applies it when the app is restarted. Each time the user changes the data-collection level, a new session with new privacy settings is generated by OneAgent. Don't wrap this API method with a user action. If you do, OneAgent won't be able to attach the user action to the correct session.
To activate this feature, enable the user opt-in mode by adding the keys below to the Info.plist
or DESK.plist
file:
<key>DTXUserOptIn</key>
<true/>
With the + (void)setCrashReportingOptedIn:(BOOL)optedIn;
method you can activate or deactivate crash reporting. The data collection level can be changed with the + (void)setDataCollectionLevel:(DTX_DataCollectionLevel)dataCollectionLevel completion:(void(^ _Nullable)(BOOL successful))completion;
method with the completion handler being called when switching to the new data-collection level is finished.
You can retrieve the privacy settings with + (DTX_DataCollectionLevel)dataCollectionLevel;
and + (BOOL)crashReportingOptedIn;
methods.
Available data-collection levels for OneAgent on iOS are:
DTX_DataCollectionOff
DTX_DataCollectionPerformance
DTX_DataCollectionUserBehavior
For UI elements inheriting from UIControl
, UITableViewCell
, and UICollectionViewCell
, it is possible to override the captured control title for each instance with a custom name. This can be used to customize control names or hide them for privacy reasons. Providing an empty string will use the control type as name, such as Button
. Providing nil
resets it to the default behavior.
var button: UIButton
button.dtxCustomControlName("Custom Name Button")
var tableCell: UITableViewCell
tableCell.dtxCustomCellName("Custom Name Table Cell")
var collectionCell: UICollectionViewCell
collectionCell.dtxCustomCellName("Custom Name Collection Cell")
UIButton *button;
[button dtxCustomControlName:@"Custom Name Button"];
UIButton *tableCell;
[tableCell dtxCustomCellName:@"Custom Name Table Cell"];
UIButton *collectionCell;
[collectionCell dtxCustomCellName:@"Custom Name Collection Cell"];