• Home
  • Platform modules
  • Digital Experience
  • Mobile applications
  • iOS
  • Customization
  • OneAgent SDK for iOS

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:

xml
<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.

swift
Dynatrace.startupWithInfoPlistSettings()
objectivec
[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.

swift
let startupDictionary: [String : Any?] = [ kDTXApplicationID: "aaaa-bbbb-cccc-dddd-eeee-ffff", kDTXBeaconURL: "https://my.beacon.url/mbeacon", kDTXLogLevel: "WARNING" ] Dynatrace.startup(withConfig: startupDictionary)
objectivec
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.

swift
// 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()
objectivec
// 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.

swift
// 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()
objectivec
// 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.

swift
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 }
objectivec
- (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.

swift
// 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()
objectivec
// 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.

swift
let myAction = DTXAction.enter(withName: "My action") myAction?.reportEvent(withName: "Something important just happened") myAction?.leave()
objectivec
// 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)

swift
DTXAction.reportError(withName: "My custom error", error: NSError(domain: "Global issue", code: 007, userInfo: nil))

Error bound to a specific user action

swift
let myAction = DTXAction.enter(withName: "My action") myAction?.reportError(withName: "My custom error", error: NSError(domain: "Action issue", code: 007, userInfo: nil)) myAction?.leave()
objectivec
// 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.

swift
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()
objectivec
- (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.

swift
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)
objectivec
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 typeInstrumentation typeDTXInstrumentWebRequestTiming
Only HTTP(S)Option A Autotrue
Option B Manualfalse
Only non-HTTP(S)Manualfalse (optional)
HTTP(S) + non-HTTP(S)Option A Auto for HTTP(S) and manual for non-HTTP(S)true
Option B Manualfalse

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 the Loading ... 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

swift
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.
swift
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)) } }
objectivec
#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.

swift
Dynatrace.identifyUser("userId")
objectivec
[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.

swift
Dynatrace.endVisit()
objectivec
[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.

To activate the user opt-in mode, add the DTXUserOptIn configuration key to your app's Info.plist file:

xml
<key>DTXUserOptIn</key> <true/>

The following code examples show you how to work with the API:

swift
import Dynatrace … let privacyConfig = Dynatrace.userPrivacyOptions() privacyConfig.dataCollectionLevel = .userBehavior privacyConfig.crashReportingOptedIn = true privacyConfig.crashReplayOptedIn = true Dynatrace.applyUserPrivacyOptions(privacyConfig) { (successful) in // callback after privacy changed }
objectivec
#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 }];

The following data collection levels are available:

  • off / DTX_DataCollectionOff
  • performance / DTX_DataCollectionPerformance
  • userBehavior / DTX_DataCollectionUserBehavior

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.

You can also use the same properties to fetch the data privacy options:

swift
import Dynatrace … let privacyOptions = Dynatrace.userPrivacyOptions() let dataCollectionLevel = privacyConfig.dataCollectionLevel let crashReporting = privacyConfig.crashReportingOptedIn let crashReplay = privacyConfig.crashReplayOptedIn
objectivec
#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:

  1. titleLabel.attributedText
  2. attributedTitleForState:UIControlStateNormal
  3. 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.

swift
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")
objectivec
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.

swift
@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 }) }
objectivec
- (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
swift
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()) } }
objectivec
[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.

xml
<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