OneAgent SDK for iOS
Use the OneAgent SDK for iOS to report additional details about the user sessions in your mobile app. The OneAgent SDK for iOS allows you to create custom actions, measure web requests, report errors, and tag specific users. The sections below explain how to enable these capabilities.
For iOS, the OneAgent SDK is available automatically once you add the Dynatrace CocoaPod to your project. You can use the OneAgent SDK for iOS in Swift and Objective-C.
Start OneAgent
To disable the automatic OneAgent startup, set the DTXAutoStart
configuration key to false
in your app's Info.plist
file:
<key>DTXAutoStart</key>
<false/>
After that, you can start OneAgent manually using either the Info.plist
configuration or the passed configuration dictionary.
We recommend that you start OneAgent as early as possible, for example, in applicationWillFinishLaunching
.
Start OneAgent with Info.plist
configuration
If you want to start OneAgent with the configuration from the Info.plist
file, use the startupWithInfoPlistSettings
API call.
Dynatrace.startupWithInfoPlistSettings()
[Dynatrace startupWithInfoPlistSettings];
Start OneAgent with passed config dictionary
If you want to start OneAgent with the passed configuration dictionary, use the startupWithConfig
API call. Configuration keys for the dictionary are the same as for the Info.plist
file, and you can also find them in the Dynatrace.h
header file shipped with OneAgent.
let startupDictionary: [String : Any?] = [
kDTXApplicationID: "aaaa-bbbb-cccc-dddd-eeee-ffff",
kDTXBeaconURL: "https://my.beacon.url/mbeacon",
kDTXLogLevel: "WARNING"
]
Dynatrace.startup(withConfig: startupDictionary)
NSDictionary<NSString*, id> *startupDictionary = @{
kDTXApplicationID: @"aaaa-bbbb-cccc-dddd-eeee-ffff",
kDTXBeaconURL: @"https://my.beacon.url/mbeacon",
kDTXLogLevel: @"WARNING"
};
[Dynatrace startupWithConfig:startupDictionary];
There might be more parameters that you need to provide. Check the instrumentation wizard in the Dynatrace web UI to learn which parameters and values to pass.
Create custom actions
You can define and report custom actions. After you start them, enhance them with additional information before finally closing them.
If you need to change an autogenerated user action, see Modify and cancel autogenerated actions.
Start and close custom actions
The code snippet below shows how to start and close a custom action. Note that OneAgent discards all action-related monitoring data when the custom action isn't closed. Timing is measured automatically.
// start the "Tap on Search" action
let action = DTXAction.enter(withName: "Tap on Search")
// ...do some work here...
// close the "Tap on Search" action
action?.leave()
// start the "Tap on Search" action
DTXAction *action = [DTXAction enterActionWithName:@"Tap on Search"];
// ...do some work here...
// close the "Tap on Search" action
[action leaveAction];
For a mobile custom action or a mobile autogenerated user action, the maximum name length is 250 characters.
The maximum duration of a mobile custom action is 9 minutes.
If a custom action takes longer than 9 minutes and is not closed, such an action is discarded and not reported to Dynatrace.
You can perform the following monitoring operations with a custom action:
- Create a child action
- Report an event
- Report a value
- Report an error
- Attach a web request
- Cancel an action
Create child actions
Child actions are similar to parent actions. When a parent action is closed, OneAgent automatically closes all child actions of the parent action.
The code snippet below shows how to start an action as the child of another action.
// start a parent custom action
let searchAction = DTXAction.enter(withName: "Tap on Search")
// ...do some work here...
// start a child action
let parseAction = DTXAction.enter(withName: "Tap on Confirm", parentAction: searchAction)
// ...do some work here...
// close a child action
parseAction?.leave()
// ...do some work here...
// close a parent custom action
searchAction?.leave()
// start a parent custom action
DTXAction *searchAction = [DTXAction enterActionWithName: @"Tap on Search"];
// ...do some work here...
// start a child action
DTXAction *parseAction = [DTXAction enterActionWithName: @"Tap on Confirm" parentAction: searchAction];
// ...do some work here...
// close a child action
[parseAction leaveAction];
// ...do some work here...
// close a parent custom action
[searchAction leaveAction];
For a mobile custom action or a mobile autogenerated user action, the maximum name length is 250 characters.
User action sample
The following code snippet shows a sample manual instrumentation.
func countParameters(query: String?) -> Int {
var count: Int = 0
//create a parent custom action
let checkQueryAction = DTXAction.enter(withName: "Tap on Check query")
//report a value on an action
checkQueryAction?.reportValue(withName: "query", stringValue: String(describing: query))
let countParametersAction = DTXAction.enter(withName: "Count parameters", parentAction: checkQueryAction)
if let query = query {
count = query.components(separatedBy:"&").count
//report a value
countParametersAction?.reportValue(withName: "Parameters found", intValue: Int64(count))
//close a child action
countParametersAction?.leave()
} else {
//report an event
countParametersAction?.reportEvent(withName: "No parameters found")
//close a child action
countParametersAction?.leave()
//report an error
checkQueryAction?.reportError(withName: "Query was nil", errorValue: -42)
}
//close a parent custom action - automatically closes all open child actions if not closed by API
checkQueryAction?.leave()
return count
}
- (int) countParameters: (NSString *) query {
int count = 0;
//create a parent custom action
DTXAction *checkQueryAction = [DTXAction enterActionWithName:@"Tap on Check query"];
//report a value on an action
[checkQueryAction reportValueWithName:@"query" stringValue:query];
DTXAction *countParametersAction = [DTXAction enterActionWithName:@"Count parameters" parentAction:checkQueryAction];
if (query != nil) {
count = [query componentsSeparatedByString:@"&"].count;
//report a value
[countParametersAction reportValueWithName:@"Parameters found" intValue:count];
//close a child action
[countParametersAction leaveAction];
} else {
//report an event
[countParametersAction reportEventWithName:@"No parameters found"];
//close a child action
[countParametersAction leaveAction];
//report an error
[checkQueryAction reportErrorWithName:@"Query was nil" errorValue:-42];
}
//close a parent custom action - automatically closes all open child actions if not closed by API
[checkQueryAction leaveAction];
return count;
}
Cancel actions
OneAgent for iOS version 8.229+
You can cancel a custom action or an autogenerated user action. Canceling an action discards all data associated with it: all reported values are discarded and all child actions are canceled.
You cannot cancel a closed action, so calling cancel
/cancelAction
after leave
/leaveAction
is impossible for the same action. The same goes for closing a canceled action: you cannot call leave
/leaveAction
after using cancel
/cancelAction
for the same action.
// start the "Tap on Search" action
let action = DTXAction.enter(withName: "Tap on Search")
// ...do some work here...
// cancel the "Tap on Search" action
action?.cancel()
// start the "Tap on Search" action
DTXAction *action = [DTXAction enterActionWithName:@"Tap on Search"];
// ...do some work here...
// cancel the "Tap on Search" action
[action cancelAction];
Report an event
With reportEvent
, you can report a specific event. The event must belong to an existing custom action or an autogenerated user action. Reported events are displayed in the user action waterfall analysis.
let myAction = DTXAction.enter(withName: "My action")
myAction?.reportEvent(withName: "Something important just happened")
myAction?.leave()
// report an event
- (DTX_StatusCode) reportEventWithName:(NSString *)eventName
If you want to report standalone events with lots of additional information, see Report a business event.
Report an error
With reportError
, you can report a specific event as an error event.
There are two options for reporting an error event:
- Report it as part of an action (either a custom action or an autogenerated user action)
- Report it as a standalone error, which is generated as a global event that is not tied to a specific action
Reported errors (both standalone and "attached" to a user action) are displayed on the user session details page and multidimensional User action analysis page. Reported errors that are part of a user action are also displayed in the user action waterfall analysis.
You can report an error with an error code, an exception, or an NSError
.
Standalone 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]];
Report a value
The reportValue
method allows you to report your own metrics. These metrics must be part of a custom action or an autogenerated user action. Reported values are displayed in the user action waterfall analysis.
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
Report a business event
OneAgent for iOS version 8.253+
With sendBizEvent
, you can report business events. These are standalone events, as OneAgent sends them separately from user actions or user sessions.
For more information on business events, see Business Analytics in Dynatrace.
let attributes: [String: Any] = [
"event.name": "Confirmed Booking",
"screen": "booking-confirmation",
"product": "Danube Anna Hotel",
"amount": 358.35,
"currency": "USD",
"reviewScore": 4.8,
"arrivalDate": "2022-11-05",
"departureDate": "2022-11-15",
"journeyDuration": 10,
"adultTravelers": 2,
"childrenTravelers": 0
]
Dynatrace.sendBizEvent(withType: "com.easytravel.funnel.booking-finished", attributes: attributes)
NSDictionary<NSString*, id> *attributes = @{
@"event.name": @"Confirmed Booking",
@"screen": @"booking-confirmation",
@"product": @"Danube Anna Hotel",
@"amount": @358.35,
@"currency": @"USD",
@"reviewScore": @4.8,
@"arrivalDate": @"2022-11-05",
@"departureDate": @"2022-11-15",
@"journeyDuration": @10,
@"adultTravelers": @2,
@"childrenTravelers": @0
};
[Dynatrace sendBizEventWithType: @"com.easytravel.funnel.booking-finished" attributes: attributes];
Measure web requests
To track web requests, OneAgent adds the x-dynatrace
HTTP header with a unique value to each request. This is required to correlate the server-side monitoring data to the corresponding mobile web request. Additionally, the timing values from the mobile side are measured.
OneAgent for iOS automatically times web requests made using NSURLRequest
, NSURLConnection
, NSURLSession
, NSURLProtocol
, NSString
, WKWebView
, or NSData
. However, you have to manually instrument requests in the following cases:
- When the automatic instrumentation of web requests is disabled
- When the requests of a third-party framework aren't instrumented
- When you need to report non-HTTP(S) requests
Which instrumentation type to use
For HTTP(S) requests, you cannot combine automatic and manual web request instrumentation. However, you can use automatic instrumentation for HTTP(S) requests and manual instrumentation for non-HTTP(S) requests such as WebSocket or gRPC requests.
The table below explains which type of request instrumentation to use depending on which request types your app has. It also shows whether you should disable the automatic request instrumentation.
Request type | Instrumentation type | DTXInstrumentWebRequestTiming |
---|---|---|
Only HTTP(S) | Option A Auto | true |
Option B Manual | false | |
Only non-HTTP(S) | Manual | false (optional) |
HTTP(S) + non-HTTP(S) | Option A Auto for HTTP(S) and manual for non-HTTP(S) | true |
Option B Manual | false |
Parent action of web requests
There is a predefined order that OneAgent for iOS follows to determine the parent of a web request event, which affects how web requests are listed in the waterfall analysis.
Automatic web request instrumentation
- If there is an active custom action started on the same thread as a web request, this action is the parent action.
- If there is no active custom action, but there is an active autogenerated action, then the autogenerated action (for example,
Touch on...
) is the parent action. This includes theLoading ...
autogenerated action. - If OneAgent cannot find an active action, then the web request event is a root level event that doesn't have a parent action.
Manual web request instrumentation
- If no parent action is provided (
Dynatrace.getRequestTagValue(for: url)
), then the behavior to find the parent action is the same as for automatic web request timing. - If a parent action is provided (
childAction?.getTagFor(url)
), then this action is the parent action.
Currently, you cannot view standalone web request events of a root level in Session segmentation.
Example: Simplified manual web request instrumentation
import UIKit
import WebKit
import Dynatrace
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.dynatrace.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 dynatraceHeaderValue = Dynatrace.getRequestTagValue(for: url) { //let agent decide which action it uses as parent (last created action)
if let dynatraceHeaderValue = childAction?.getTagFor(url) { //provide parent action
let dynatraceHeaderKey = Dynatrace.getRequestTagHeader() //this could be cached as it always is x-dynatrace
request.addValue(dynatraceHeaderValue, forHTTPHeaderField: dynatraceHeaderKey)
webrequestTiming = DTXWebRequestTiming.getDTXWebRequestTiming(dynatraceHeaderValue, 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()
}
}
Monitor non-HTTP(S) requests
OneAgent for iOS does not support auto-instrumentation of non-HTTP(S) requests. If you need to report requests such as a WebSocket request (starts with ws://
or wss://
), check the following code samples.
- If you have only non-HTTP(S) requests, you can disable the automatic request instrumentation, but it's not really required.
- If you have both HTTP(S) and non-HTTP(S) requests and HTTP(S) requests are auto-instrumented, don't disable automatic request instrumentation.
import UIKit
import Dynatrace
class ViewController: UIViewController {
override func viewDidLoad() {
let parentAction = DTXAction.enter(withName: #function)!
defer { parentAction.leave() }
webSocketMonitoringExample(parentAction: parentAction)
}
func webSocketMonitoringExample(parentAction : DTXAction) {
let childAction = DTXAction.enter(withName: #function, parentAction: parentAction)
defer { childAction?.leave() }
let urlSession = URLSession(configuration: .default)
let url = URL(string: "wss://....")! // example echo wss server
let tag = childAction?.getTagFor(url)! // not sending the tag, just using it for internal reference
let webrequestTiming = DTXWebRequestTiming.getDTXWebRequestTiming(tag!, request: url)
let webSocketTask = urlSession.webSocketTask(with: url)
webSocketTask.resume()
webrequestTiming?.start()
let message = URLSessionWebSocketTask.Message.string("Hello World")
webSocketTask.send(message) { error in
if let error = error {
print("send error: \(error.localizedDescription)")
}
}
// synchronous example
let receiveDispatch = DispatchGroup()
receiveDispatch.enter()
webSocketTask.receive { result in
print("received data: \(result)")
receiveDispatch.leave()
}
receiveDispatch.wait()
webSocketTask.cancel()
webrequestTiming?.stop(String(URLSessionWebSocketTask.CloseCode.normalClosure.rawValue))
}
}
#import "ViewController.h"
#import <Dynatrace/Dynatrace.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
DTXAction* parent = [DTXAction enterActionWithName: [NSString stringWithFormat:@"%s", __FUNCTION__]];
[self webSocketMonitoringExample:parent];
[parent leaveAction];
}
- (void)webSocketMonitoringExample:(DTXAction*)parentAction {
DTXAction* childAction = [DTXAction enterActionWithName:[NSString stringWithFormat:@"%s", __FUNCTION__] parentAction:parentAction];
NSURLSession* urlSession = [NSURLSession sessionWithConfiguration:NSURLSessionConfiguration.defaultSessionConfiguration];
NSURL* url = [NSURL URLWithString:@"wss://...."]; // example echo wss server
NSString* tag = [childAction getTagForURL:url]; // not sending the tag, just using it for internal reference
DTXWebRequestTiming* webrequestTiming = [DTXWebRequestTiming getDTXWebRequestTiming:tag requestUrl:url];
NSURLSessionWebSocketTask* webSocketTask = [urlSession webSocketTaskWithURL:url];
[webSocketTask resume];
[webrequestTiming startWebRequestTiming];
NSURLSessionWebSocketMessage* message = [[NSURLSessionWebSocketMessage alloc] initWithString:@"Hello World"];
[webSocketTask sendMessage:message completionHandler:^(NSError * _Nullable error) {
if (error) {
NSLog(@"send error: %@", error.localizedDescription);
}
}];
// synchronous example
dispatch_group_t receiveDispatch = dispatch_group_create();
dispatch_group_enter(receiveDispatch);
[webSocketTask receiveMessageWithCompletionHandler:^(NSURLSessionWebSocketMessage * _Nullable message, NSError * _Nullable error) {
NSLog(@"received data: %@", message);
dispatch_group_leave(receiveDispatch);
}];
dispatch_group_wait(receiveDispatch, DISPATCH_TIME_FOREVER);
[webSocketTask cancel];
[webrequestTiming stopWebRequestTiming:[NSString stringWithFormat:@"%ld", (long)NSURLSessionWebSocketCloseCodeNormalClosure]];
[childAction leaveAction];
}
@end
Disable automatic request instrumentation
To disable the automatic web request instrumentation, set the DTXInstrumentWebRequestTiming
configuration key to false
.
Tag specific users
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 Dynatrace API. You can tag users when they log in or when an already logged in session is used or restored upon app relaunch, as the tag isn't persisted over app restarts.
Dynatrace.identifyUser("userId")
[Dynatrace identifyUser:@"userId"];
OneAgent for iOS version 235+ Sessions split due to idle or duration timeout are re-tagged automatically.
When OneAgent ends a tagged session because the session duration has reached its set limit or due to the user's inactivity, the subsequent session is re-tagged automatically. You don't need to provide the user identification information again.
However, note that OneAgent does not re-tag the subsequent session in the following cases:
- When you explicitly end a tagged user session via
endVisit
- When the user or the mobile operating system closes or force stops the app
- When OneAgent ends the current user session and generates a new session after the privacy settings have been changed
See User sessions > Session end to learn when OneAgent ends a mobile user session.
End a session
You can force a session to end via the Dynatrace API. This also closes all open actions and starts a new session.
Dynatrace.endVisit()
[Dynatrace endVisit];
Configure data privacy
With the user opt-in mode for mobile apps, you can dynamically adjust data privacy settings and build your apps in compliance with data protection laws and regulations.
Enable user opt-in mode
To activate the user opt-in mode, add the DTXUserOptIn
configuration key to your app's Info.plist
file:
<key>DTXUserOptIn</key>
<true/>
Apply data privacy settings
The following code examples show you how to work with the API:
import Dynatrace
…
let privacyConfig = Dynatrace.userPrivacyOptions()
privacyConfig.dataCollectionLevel = .userBehavior
privacyConfig.crashReportingOptedIn = true
privacyConfig.crashReplayOptedIn = true
Dynatrace.applyUserPrivacyOptions(privacyConfig) { (successful) in
// callback after privacy changed
}
#import <Dynatrace/Dynatrace.h>
…
id<DTXUserPrivacyOptions> privacyConfig = [Dynatrace userPrivacyOptions];
privacyConfig.dataCollectionLevel = DTX_DataCollectionUserBehavior;
privacyConfig.crashReportingOptedIn = YES;
privacyConfig.crashReplayOptedIn = YES;
[Dynatrace applyUserPrivacyOptions:privacyConfig completion:^(BOOL successful) {
// callback after privacy changed
}];
OneAgent persists the data privacy settings and automatically applies them when the app is restarted. Each time the user changes the data collection level, OneAgent generates a new session with new settings. Ensure that you don't wrap this API method with a user action; otherwise OneAgent won't be able to attach the user action to the correct session.
Data collection levels
The table below describes the available data collection levels and shows whether user tags and custom user actions, events, values, and errors are reported for a particular level.
Level | Description | User tags, custom events, and custom values | Custom user actions and errors |
---|---|---|---|
Off Monitoring data is not sent | No personal data is sent; all identifiers are randomized on every launch.1 | ||
Performance Only performance, automatically captured data is sent | No personal data is sent; all identifiers are randomized on every launch. | ||
User behavior Performance data and user data is sent | Personal data is sent; OneAgent recognizes and reports users who revisit in the future.2 |
A single Loading <App>
event is sent to track the number of users that opted out.
If you haven't configured user tagging and custom event or value reporting, the User behavior level works similarly to the Performance level.
The possible values for the data collection levels are as follows:
Swift | Objective-C |
---|---|
.off | DTX_DataCollectionOff |
.performance | DTX_DataCollectionPerformance |
.userBehavior | DTX_DataCollectionUserBehavior |
Fetch data privacy options
You can also use the same properties to fetch the data privacy options:
import Dynatrace
…
let privacyOptions = Dynatrace.userPrivacyOptions()
let dataCollectionLevel = privacyConfig.dataCollectionLevel
let crashReporting = privacyConfig.crashReportingOptedIn
let crashReplay = privacyConfig.crashReplayOptedIn
#import <Dynatrace/Dynatrace.h>
…
id<DTXUserPrivacyOptions> privacyConfig = [Dynatrace userPrivacyOptions];
DTX_DataCollectionLevel level= privacyConfig.dataCollectionLevel;
BOOL crashReporting = privacyConfig.crashReportingOptedIn;
BOOL crashReplay = privacyConfig.crashReplayOptedIn;
User action naming
To construct user action names, OneAgent captures the control title from UIButton
by evaluating the following order of APIs or fields and stopping once it receives a valid text:
titleLabel.attributedText
attributedTitleForState:UIControlStateNormal
accessibilityLabel
If none of these produce usable text, OneAgent sets the control title to the default Button
value.
For cells, the behavior is similar: a heuristic is used to determine the most prominent label in the cell, and OneAgent uses that text in a user action name.
Use custom control titles
You can override the captured control titles for UIControl
, UITableViewCell
, and UICollectionViewCell
. This allows you to change control titles or hide them for privacy reasons.
If you provide an empty string, OneAgent uses the control type in a user action name, for example, Touch on Button
. Providing nil
resets the control title to the default one.
var button: UIButton
button.dtxCustomControlName("Custom button title")
var tableCell: UITableViewCell
tableCell.dtxCustomCellName("Custom table cell title")
var collectionCell: UICollectionViewCell
collectionCell.dtxCustomCellName("Custom collection cell title")
UIButton *button;
[button dtxCustomControlName:@"Custom button title"];
UIButton *tableCell;
[tableCell dtxCustomCellName:@"Custom table cell title"];
UIButton *collectionCell;
[collectionCell dtxCustomCellName:@"Custom collection cell title"];
If you want to get rid of control titles in all user actions at once, see Mask user actions.
Modify autogenerated actions
OneAgent for iOS creates user actions based on interactions of your application's users. These actions are different from custom actions and are sometimes called autogenerated actions. We also refer to them as user actions.
Using the OneAgent SDK for iOS, you can modify or even cancel these autogenerated actions.
If you want to avoid capturing personal information for all user actions at once, see Mask user actions.
Modify a specific user action
OneAgent for iOS version 8.215+
With Dynatrace.modifyUserAction
, you can modify the current user action. You can change the user action name and report events, values, and errors. You can also cancel a user action.
Allowed operations on the returned user action object are as follows:
getName
setName
reportEvent
reportValue
reportError
- OneAgent for iOS version 8.241+
cancelAction
/cancel
You can modify a user action only while it is still open. If the user action times out before it is modified, the modification has no effect. Calling leave
on this object also has no effect.
@IBAction func buttonTouchUp(_ sender: Any) {
//for example, handle button touch, get values that should be put into user action name
//fetch current autogenerated action and modify it
Dynatrace.modifyUserAction( { (action) -> () in
let oldName = action?.getName()
action?.setName("This is a renamed auto user action (was '\(oldName)')")
action?.reportValue(withName: "The Answer to the Ultimate Question of Life, the Universe, and Everything", intValue: 42)
action?.reportValue(withName: "G-force", doubleValue: 9.81)
action?.reportValue(withName: "Palindrome", stringValue: "Was it a car or a cat I saw?")
action?.reportError(withName: "Some error", errorValue: -1)
//other reportError also possible, skipping in this example
})
}
- (IBAction)buttontouchUp:(UIButton *)sender {
//for example, handle button touch, get values that should be put into user action name
//fetch current autogenerated action and modify it
[Dynatrace modifyUserAction:^(DTXAction * _Nullable modifiableAction) {
NSString* oldName = [modifiableAction getName];
[modifiableAction setName:[NSString stringWithFormat: @"This is a renamed auto user action (was '%@')", oldName]];
[modifiableAction reportValueWithName: @"The Answer to the Ultimate Question of Life, the Universe, and Everything" intValue: 42];
[modifiableAction reportValueWithName: @"G-force" doubleValue: 9.81];
[modifiableAction reportValueWithName: @"Palindrome" stringValue: @"Was it a car or a cat I saw?"];
[modifiableAction reportErrorWithName: @"Some error" errorValue: -1];
//other reportError also possible, skipping in this example
}];
}
For a mobile custom action or a mobile autogenerated user action, the maximum name length is 250 characters.
Modify any user action
OneAgent for iOS version 8.241+
You can modify autogenerated user actions via Dynatrace.modifyUserAction
. However, you can do that only for a specific user action, and you usually should know whether this user action is still open or not.
To overcome these limitations, we introduced a feature that allows you to receive a callback for every newly created user action. With this approach, you are notified about every new autogenerated user action, so you get a chance to update the user action name as well as report events, values, and errors. You can also cancel a user action.
You can register a callback that is invoked for each autogenerated user action. You can set the callback anywhere in the application at any point in time.
Any previously registered callback is overwritten by a subsequent call to the API method.
Allowed operations are as follows:
getName
setName
reportEvent
reportValue
reportError
cancelAction
/cancel
Dynatrace.setAutoUserActionCreationCallback { modifiableAction in
guard let modifiableAction = modifiableAction else {
return
}
if modifiableAction.getName().starts(with: "Loading") {
modifiableAction.cancel()
} else {
modifiableAction.setName("Modified Action: " + modifiableAction.getName())
}
}
[Dynatrace setAutoUserActionCreationCallback:^(DTXAction * _Nullable modifiableAction) {
if (!modifiableAction) {
return;
}
if ([[modifiableAction getName] hasPrefix:@"Loading"]) {
[modifiableAction cancelAction];
} else {
[modifiableAction setName:[NSString stringWithFormat:@"Modified Action: %@", [modifiableAction getName]]];
}
}];
For a mobile custom action or a mobile autogenerated user action, the maximum name length is 250 characters.
Mask user actions
OneAgent for iOS version 8.249+
By default, user action names are derived from UI element titles, for example, button or table cell titles. In rare circumstances, email addresses, usernames, or other personal information might be unintentionally included in user action names. This happens when this information is included in parameters used for control titles, resulting in user action names such as Touch on Account 123456
.
If such personal information appears in your application's user action names, enable user action masking. OneAgent will replace all Touch on <control title>
action names with the type of the control that the user touched, for example:
Touch on Account 123456
>Touch on Button
Touch on Transfer all amount
>Touch on Switch
Touch on Country
>Touch on TableCell
To enable user action masking, set the DTXUIActionNamePrivacy
configuration key to true
in your app's Info.plist
file.
<key>DTXUIActionNamePrivacy</key>
<true/>
User action masking doesn't change custom control titles.
If you want to change names only for certain controls or certain user actions, use one of the following settings:
- Use custom control titles to override the UI element titles captured by default
- Modify autogenerated actions to change user action names
- Set naming rules (mobile app settings > Naming rules) to configure user action naming rules or extraction rules