How are manual API calls used to enrich mobile-user experience data?

The Dynatrace API can be used to report additional details about the mobile user sessions in your application environment. The API enables you to:

  • Create custom user actions
  • Measure web requests
  • Report errors
  • Tag specific users

Android

Use the following Gradle command to add the Dynatrace API to your project during the compile process:

compile Dynatrace.agent()

Create custom user actions

You must call enterAction to start each action and leaveAction to close each action. Timing is measured automatically.

// start user action
DTXAction searchAction = Dynatrace.enterAction("search");

// ...do some work here...

// end the action after the search completed  
searchAction.leaveAction();

Measure web requests

Auto-instrumentation automatically instruments HttpUrlConnection, HttpClient, and OkHttp3 requests. If you're using a different library, you can use manual instrumentation to tag and time your web requests.

// generate a new request tag
String requestTag = Dynatrace.getRequestTag();

// associate the timing with the tag
WebRequestTiming timing = Dynatrace.getWebRequestTiming(requestTag);

// create request and add the dynatrace header key and the tag value to the
// request this will allow you to see the service flow of your web requests if
// the server side is instrumented with a OneAgent
Request request = new Request.Builder()
  .url("http://example.com/request")
	.addHeader(Dynatrace.getRequestTagHeader(), requestTag)
	.build();

// call startWebRequestTiming() to begin the timing
timing.startWebRequestTiming();

// ... send the request and receive the response ...

// once we're done reading, we can stop the timing
timing.stopWebRequestTiming();

Report errors

// start user action
DTXAction searchAction = Dynatrace.enterAction("search");

try {
  // ... do something that might throw an exception ...
} catch (Exception e) {
  // report the error
  searchAction.reportError("An exception occured", e);
}

// end the action after the search completed  
searchAction.leaveAction();

Tag a specific user

Dynatrace.identifyUser(<usertag>);

iOS

The iOS API is available automatically once you add the Dynatrace CocoaPod to your project. The API can be used in Swift as well as in Objective-C.

Create custom user actions

You must call enterActionWithName to start each action and leaveAction to close each action. Timing is measured automatically.

// start action "search"
DTXAction *action = [DTXAction enterActionWithName:@"search"];

// ...do some work here...

// end action "search"
[action leaveAction];

Measure web requests

Dynatrace OneAgent automatically times web requests made using NSURLRequest, NSURLConnection, NSURLProtocol, NSString', andUIWebView`.

/**
 *  simplified manual webrequest timing/tagging demo
 */

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 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(nil) //stop webrequest when request finished

            wkWebView.loadHTMLString(urlContents, baseURL: nil)
        }

        webrequestTiming?.start()    //start webrequest timing
        task.resume()
    }

}

Report errors

The API enables you to report error codes NSError, NSException, and NSInteger.

// report an error
DTXAction *action;
NSError* error;
[action reportErrorWithName:@"CommunicationError" errorValue:[error code]];

Tag a specific user

[Dynatrace identifyUser:<username>];