iOS API

Instana iOS agent API

The following section describes the usage of the Instana iOS agent. Instana's iOS agent can be used through the Instana class methods that are explained here.

Setup

Initialize the Instana iOS agent early in didFinishLaunchingWithOptions by calling the setup function. Do not start Instana delayed. Make sure to call the setup right after the app launch. You can enable or disable Instana delayed by using the Instana.collectionEnabled flag.

static func setup(key: String, reportingURL: URL, httpCaptureConfig: HTTPCaptureConfig = .automatic)

Configuration parameters

Parameter Description
key (String) The Instana monitoring configuration key.
reportingURL (URL) The URL pointing to the Instana instance to which the monitoring data is sent.
httpCaptureConfig HTTPCaptureConfig (Optional) By default, HTTP requests and responses are captured automatically. To disable automatic monitoring, set this parameter to manual or use both the modes together with automaticAndManual HTTP capture configuration. To turn off HTTP session monitoring, you can pass none.
collectionEnabled (Bool, optional) By default, the data collection is turned on with the setup. To set up Instana but ignore any data collection, set this parameter to false in the setup. This parameter is useful for scenarios in which user consent is required before the agent can collect data. The default value is true.
enableCrashReporting (Bool, optional) (technology preview) By default, the data collection is disabled in the setup. The data collection can be enabled later by using this property, which allows apps to start collecting Instana crash data. This property is most useful for scenarios in which explicit user consent is required before the agent can collect crash data. The default value is false.
slowSendInterval (Double, optional) This parameter enables slow sending mode feature on beacon sending failure by providing a valid positive number in seconds (range from 2-3600). The default value is 0.0, which means that the slow sending mode is disabled.

Example

import InstanaAgent

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    Instana.setup(key: "<Your Instana Key>", reportingURL: URL(string: "<Your Instana instance URL>")!)
    ....
    return true
}

The following example captures HTTP header fields with the key X-Key or X-KEY and uses the default automatic HTTP capture configuration. To change the default settings, use the following commands:

let options = InstanaSetupOptions(httpCaptureConfig: .manual)
Instana.setup(key: <Your Key>, reportingURL: <Your Instana URL>, options: options)

Current configuration

The Instana class object has some properties to retrieve the current configuration setup:

Property Description
key (String, optional) The Instana monitoring configuration key.
reportingURL (URL, optional) The URL pointing to the Instana instance to which to the send monitoring data to.

Example

let key = Instana.key
let url = Instana.reportingURL

Session identifier

Each Instana agent instance has an unique session identifier you could use for other purposes in your app.

Property Description
sessionID (String, optional) The current session identifier. This session id will be created within the setup process.

Example

let sessionID = Instana.sessionID

Automatic HTTP monitoring

By default HTTP sessions are captured automatically. The Instana iOS agent uses Foundation's NSURLProtocol to monitor HTTP requests and responses. To observe all NSURLSession automatically with NSURLProtocol some method swizzling in the NSURLSession is necessary. To opt out automatic HTTP session monitoring, you must capture every request and response manually.

Manual HTTP monitoring

To capture HTTP sessions manually, you must set up Instana by using the httpCaptureConfig: .manual and use the corresponding functions that are described. You can capture HTTP requests and responses manually by using the URLRequest or URL.

Automatic and manual HTTP monitoring

To capture HTTP sessions automatically and manually you must set up Instana by using the httpCaptureConfig: .automaticAndManual. You can use the automatic instrumentation or optionally capture HTTP requests or responses manually.

Start Capture (URLRequest)

This function starts the http capture for the URLRequest and the optional view name. A HTTPMarker object is returned which you need later to set the results of the HTTP response.

static func startCapture(_ request: URLRequest?, viewName: String? = nil) -> HTTPMarker
Configuration parameters
Parameter Description
request (URLRequest) The URLRequest to capture.
viewName (String, optional) Optional name of the visible view that is related to this request

Returns: HTTP marker to set the results of the HTTP response (HTTP status code, sizes, error).

Start capture (URL)

This function starts the HTTP capture for the URL, HTTP method, and the optional view name. A HTTPMarker object is returned which you need later to set the results of the HTTP response.

static func startCapture(url: URL, method: String, viewName: String? = nil) -> HTTPMarker
Configuration parameters
Parameter Description
url (URL) The URL to capture.
method (String) The HTTP method of the request.
viewName (String, optional) Optional name of the visible view that is related to this request

Returns: HTTP marker to set the results of the HTTP response (HTTP status code, sizes, error).

Set HTTP response size

Invoke this method on the HTTPMarker when the response size is determined.

func set(responseSize: Instana.Types.HTTPSize)
Configuration parameters
Parameter Description
responseSize (HTTPSize) The httpSize object that contains headerBytes, bodyBytes, bodyBytesAfterDecoding

Note: Make sure that you don't call any methods on the HTTPMarker after you called finish or cancel

HTTP response size

You can create the HTTPMarker.Size with the following initializer:

init(response: URLResponse, transactionMetrics: [URLSessionTaskTransactionMetrics]?)
Configuration parameters
Parameter Description
response (URLResponse) The URLResponse object
transactionMetrics ([URLSessionTaskTransactionMetrics], optional) An optional array with URLSessionTaskTransactionMetrics

You can also create the HTTPMarker.Size object by passing the size values directly as parameter

HTTPMarker.Size(header: Instana.Types.Bytes, body: Instana.Types.Bytes, bodyAfterDecoding: Instana.Types.Bytes)

Finish Capture (URLResponse)

Call finish on HTTPMarker once the request is completed with the URLResponse and an optional Error

func finish(response: URLResponse?, error: Error?)

Finish Capture (HTTPCaptureResult)

Alternatively you can use the HTTPCaptureResult to finish the capture.

let size = HTTPMarker.Size(header: 123, body: 1024, bodyAfterDecoding: 2048)
let result = HTTPCaptureResult(statusCode: statusCode, backendTracingID: "Instana-backend-tracing-id", responseSize: size, error: error)
marker.finish(result: result)

Cancel capture

Invoke this method on the HTTPMarker if the request is canceled before completion. The state is set to failed internally with an NSURLErrorCancelled when you are calling cancel.

func cancel()

Complete manual HTTP monitoring example (URLResponse)

let marker = Instana.startCapture(request, viewName: "User: Details")
URLSession.shared.dataTask(with: request) { data, response, error in
    marker.finish(response: response, error: error)
}.resume()

You can also set the HTTP response size manually through the URLSessionDelegate like the following example (before you are calling finish or cancel):

func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
    guard let response = task.response else { return }
    marker.set(responseSize: HTTPMarker.Size(response: response, transactionMetrics: metrics.transactionMetrics))
}

Complete manual HTTP monitoring example (URL)

let url = URL(string: "https://www.example.com/user/123/details")!
let marker = Instana.startCapture(url: url, method: "GET", viewName: "Home")
YourNetworkManager(url: url, method: "GET") { (statusCode, error) in
    let size = HTTPMarker.Size(header: 123, body: 1024, bodyAfterDecoding: 2048) // optionally
    let backendTracingID = "Instana-backend-tracing-id" // optionally
    let result = HTTPCaptureResult(statusCode: statusCode, backendTracingID: backendTracingID, responseSize: size, error: error)
    marker.finish(result: result)
}.resume()

Views

Instana can segment app metrics by logical views. To do so, it needs a hint what view the user is currently looking at. This view name can be set via the setView(name: String). The view name will be attached to all monitored beacons until you call setView again with another name. Generally speaking, we recommend not to use technical or generic names like the Class (i.e. WebViewController) to define views. We recommend the usage of readable names for views. For example product detail page or payment selection. This will result in fewer pages which will have a direct relation to actually existing code. We recommend to set the view name in viewDidAppear. Setting the view name will also enable Instana to track page transitions in addition to page loads.

The view name gets updated automatically when your app changes the state (e.g. from active to inactive or background). The view name will be Inactive when your app is in the inactive state (when receiving a SMS) and will be set to Background once your app leaves the foreground.

static func setView(name: String)

Configuration parameters

Parameter Description
name (String) The name of the view.

Example

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    Instana.setView(name: "User: Details")
}

To get the current view name, you can use the class variable viewName. The value for view name might be Inactive or Background depending on your app state.

Property Description
viewName (String, optional) The current view name set through setView(name:).

Example

let viewName = Instana.viewName

Identifying Users

User-specific information can optionally be sent with data transmitted to Instana. This information can then be used to unlock additional capabilities such as:

  • calculate the number of users affected by errors,
  • to filter data for specific users and
  • to see which user initiated a view change or HTTP request.

By default, Instana will not associate any user-identifiable information to beacons. Please be aware of the respective data protection laws when choosing to do so. We generally recommend identification of users via a user ID. For Instana this is a completely transparent String that is only used to calculate certain metrics. userName and userEmail can also be used to have access to more filters and a more pleasant presentation of user information.

In cases in which you are handling anonymous users and thus don't have access to user IDs you could alternatively use session IDs. Session IDs are not as helpful as user IDs when filtering data but they are a good indicator to calculate affected/unique user metrics. We recommend setting a user name such as Anonymous to have a clear differentiation between authenticated and unauthenticated users. Session IDs can be sensitive data (depending on the framework/platform used). Please consider hashing session IDs to avoid transmitting data to Instana that can grant access.

It is important to note that data already transmitted to Instana's server cannot be retroactively updated. For this reason it is important to call this API as soon as possible in the app launch process.

static func setUser(id: String, email: String?, name: String?)

Configuration parameters

Parameter Description
id (String) An identifier for the user.
email (String, optional) The user's email address.
name (String, optional) The user's name.

You can pass nil for values you don't want to set.

Example

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
     Instana.setup(key: InstanaKey, reportingURL: InstanaURL)
     Instana.setUser(id: someID, email: "email@example.com", name: "John")
     return true
}

Alternatively, you can set the user properties individually.

User ID

Set the user ID

static func setUser(id: String)
Configuration parameters
Parameter Description
id (String) An identifier for the user.

User email address

Set the user email address

static func setUser(email: String)
Configuration parameters
Parameter Description
email (String) User's email address.

Username

Set user's name

static func setUser(name: String)

Parameters

Parameter Description
name (String) User's name.

Metadata

Metadata information that is attached to the transmitted data. Consider using to track UI configuration values, settings, feature flags… any additional context that might be useful for analysis. You should set the metadata in the app launch process to assign the key or values to all transmitted data.

static func setMeta(value: String, key: String)

Parameters

Parameter Description
value (String) The value of the key-value pair you want to add as metadata.
key (String) The key of the key-value pair you want to add as metadata.

Example

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    Instana.setup(key: InstanaKey, reportingURL: InstanaURL)
    Instana.setMeta(value: "ReactNative", key: "Platform")
    Instana.setMeta(value: "DEBUG", key: "Environment")
    return true
}

Excluding URLSession from monitoring

You can ignore a custom URLSession from being monitored by the Instana iOS agent.

static func ignore(_ session: URLSession)

Configuration parameters

Parameter Description
session (URLSession) URLSession to be ignored from monitoring.

Example

let session = URLSession(configuration: .default)
Instana.ignore(session)

Excluding URLs from monitoring

You can ignore URLs to reject that match with the given regular expressions to prevent transmission to Instana. A good example for usage of this function would be to ignore all HTTP requests that contain any sensitive data like a password.

static func setIgnoreURLs(matching regex: [NSRegularExpression])

Configuration parameters

Parameter Description
regex ([NSRegularExpression]) An array of NSRegularExpression objects matching the URLs you want to ignore.

Example

let regex = try! NSRegularExpression(pattern: "/.*(&|\?)password=.*/i")
Instana.setIgnoreURLs(matching: [regex])

That examples ignore all URLs that contain password in the query.

Alternatively you can ignore full URLs like:

Instana.setIgnore(urls: [URL(string: "https://www.example.com")!])

Report custom events

Custom events enable reporting about nonstandard activities, important interactions, and custom timings to Instana. It can be especially helpful when analyzing uncaught errors (breadcrumbs) and to track more performance metrics.

static func reportEvent(name: String, timestamp: Instana.Types.Milliseconds? = nil, duration: Instana.Types.Milliseconds? = nil, backendTracingID: String? = nil, error: Error? = nil, meta: [String: String]? = nil, viewName: String? = Instana.viewName)

Configuration parameters

Parameter Description
name (String) Defines what kind of event that happens in your app that results in the transmission of a custom beacon.
timestamp (Int64, optional) The timestamp in milliseconds when the event is started. If you don't provide a timestamp, we assume now as timestamp. In case you don't provide a timestamp, but set a duration, we calculate a timestamp by subtracting the duration from now. (timestamp = now - duration)
duration (Int64, optional) The duration in milliseconds of how long the event lasted. Default is zero
backendTracingID (String, optional) Identifier to create a backend trace for this event.
error (Error, optional) Error object to provide more context.
meta ([String: String], optional) Key - Value data, which can be used to send metadata to Instana just for this singular event
viewName (String, optional) You can pass a String to group the request to a view. If you send explicitly nil, the viewName is ignored. Alternatively you can leave out the parameter viewName to use the current view name you did set in setView(name: String))

Examples

Instana.reportEvent(name: "Event-Name")
Instana.reportEvent(name: "Event-Name", viewName: "User: Details")
Instana.reportEvent(name: "Event-Name", timestamp: 1590149955086, duration: 124842, backendTracingID: "some-id", error: NSError(domain: "Some", code: -1, userInfo: nil), meta: ["Key": "Value"], viewName: "User: Details")

Enabled or disable collection

You can enable or disable the data collection at any time during the runtime. It enables the delayed start of the data collection (for example after user consent).

Property Description
collectionEnabled (Bool) Flag to enable or disable data collection

Example

Instana.collectionEnabled = true

Enable logging

The Instana iOS agent has a logging capability for debugging purposes. Just add the environment variable INSTANA_DEBUG_LOGLEVEL in Xcode. As value you must pass the number for the log level: 0 = Debug information, warnings and error, 1 = Warnings and errors, 2 => Errors only

Redact URL Query parameters

Query parameters in collected URLs may contain sensitive data. Therefore, the Instana iOS agent supports the specification of regex patterns for query parameter keys whose values should be redacted. Any redacted value will be replaced with <redacted>. Redaction happens within the Instana agent, before reporting to the Instana server. Consequently, secrets will not reach the Instana servers for processing and will not be available for analysis in the UI or retrieval by using Instana API.

By default, the Instana iOS agent is configured with a list of three regex patterns to automatically redact query parameter values for the keys: "password", "key" and "secret". Redaction will only be applied to automatically monitored requests and their associated logs. Manually monitored requests are not redacted.

static func redactHTTPQuery(matching regex: [NSRegularExpression])

Configuration parameters

Parameter Description
regex ([NSRegularExpression]) An array of NSRegularExpression objects matching the keys for the values that you want to redact.

Example

let regex = try! NSRegularExpression(pattern: #"pass(word|wort)"#)
Instana.redactHTTPQuery(matching: [regex])

This example redacts values for the HTTP parameter keys "password" or "passwort". The captured URL https://example.com/accounts/?password=123&passwort=459 will be collected and displayed as https://example.com/accounts/?password=<redacted>&passwort=<redacted>.

Note: The Instana iOS agent does not support treating path parameters (/account/ /status) or matrix parameters (/account;accountId= /status) as secrets.

Capture HTTP header fields

HTTP request and response headers can be captured by the iOS agent. You can use regular expressions to define the keys of the HTTP header fields that the iOS agent needs to capture.

public static func setCaptureHeaders(matching regex: [NSRegularExpression])

Configuration parameters

Parameter Description
regex ([NSRegularExpression]) An array of NSRegularExpression objects to match the key of HTTP request/response headers that you want to capture.

Example

let regex = try! NSRegularExpression(pattern: #"X-Key"#, options: [.caseInsensitive])
Instana.setCaptureHeaders(matching: [regex])

This example captures HTTP header fields with the key X-Key or X-KEY.

Slow Sending Mode

Optional: You can turn on the slow sending mode feature.

By default, if a beacon sending fails, the Instana agent tries to resend the beacon until the sending is successful. This doesn't work well with some cellular networks. By enabling the slow sending mode feature, the beacon sending interval is changed to the time value that is assigned to the slowSendInterval parameter. Each sending consists of only one beacon instead of a batch (maximum 100 beacons in a batch). Instana agent stays in slow sending mode until one beacon is sent successfully.

The valid time range for slowSendInterval is 2-3600 in seconds.

Example

import InstanaAgent
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
    let options = InstanaSetupOptions(slowSendInterval: 60.0)
    if !Instana.setup(key: InstanaKey, reportingURL: InstanaURL, options: options) {
        // Error handling here
    }
    ....
    return true
}