Android Monitoring API

Instana Android agent API

The following section describes the usage of the Instana Android agent. Instana's Android agent can be used via the Instana class methods explained as follows.

Setup

We recommend initializing Instana in your Application class' onCreate(), right after super.onCreate():

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        Instana.setup(
            this,
            InstanaConfig(
                key = "YOUR_APP_KEY",
                reportingURL = "YOUR_REPORTING_URL"
            )
        )
    }
}

Configuration parameters

Parameter
Description
key (String) Instana monitoring configuration key.
reportingURL (String) 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 the automatic monitoring, set this parameter to HTTPCaptureConfig.MANUAL. To turn off the HTTP session monitoring, set this parameter to HTTPCaptureConfig.NONE.
suspendReporting (SuspendReportingType, optional) Transmission of Instana beacons happens with low priority in the background. You can choose the conditions under which the transmission of beacons must be suspended, such as when the battery is low, when you have only a cellular connection, or never.
initialBeaconDelayMs (Long, optional) The agent delays the transmission of the first beacons for the determined time to make sure that the client has set up all the additional parameters, such as Session Identifiers before sending any beacon to the Instana server.
Note: Only the transmission of the beacons are delayed; monitoring and capturing starts as soon as the agent is initialized, regardless of the initialBeaconDelayMs parameter.
collectionEnabled (Bool, optional) This parameter enables or disables the Android agent's data collection and submission on startup. 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 Android agent can collect data. The default value is true.
enableCrashReporting (Boolean, optional) (technology preview) This parameter enables or disables the crash data collection and submission on startup. If required, the collection and submission can be enabled after startup. This parameter is useful for scenarios in which user consent is required before the Android agent can collect crash data. The default value is false.
slowSendIntervalMillis (Long, optional) This parameter enables the slow sending mode feature on beacon sending failure by providing a valid positive integer in milliseconds (range from 2000-3600000 milliseconds). The default value is null, which means that the slow sending mode is disabled.

Current configuration

To check the current Instana configuration, simply access the InstanaConfig instance:

val currentConfig = Instana.config

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

val sessionId = Instana.sessionId

Automatic HTTP monitoring

By default, HTTP sessions will be be captured automatically. Upon initializing Instana (after installing the Instana Android Plugin and Instana Android SDK), the Agent will take care of the rest.

The Instana Android agent will automatically weave code to provide monitoring of HTTP requests for the supported clients:

  • OkHttp3
  • HttpURLConnection
  • Retrofit

Automatic HTTP monitoring can be disabled in favor of manual HTTP monitoring, as explained in the following section.

Manual HTTP monitoring

Start capture

This function returns the HTTPMarker which you need later when the request has been completed.

Instana {
    fun startCapture(url: String, viewName: String? = view, requestHeaders: Map<String,String>?): HTTPMarker?
}
Configuration parameters
Parameter
Description
url (String) The URL to capture.
viewName (String, optional) Optional name of the visible view related to this request
requestHeaders (Map<String,String>, optional) Optional list of request header name and values

Returns: HTTP marker to set the response size, call the finish or error state when the request has been completed.

Finish capture

Once the request has been completed you must call finish with the response on the HTTPMarker and an optional Error:

HTTPMarker {
    fun finish(response: okhttp3.Response)
    fun finish(request: okhttp3.Request, error: Throwable)
    fun finish(connection: java.net.HttpURLConnection)
    fun finish(connection: java.net.HttpURLConnection, error: Throwable)
    fun finish(data: com.instana.android.instrumentation.HTTPMarkerData)
}

Cancel capture

Invoke this method on the HTTPMarker if the request has been canceled before completion.

fun cancel()

Examples

val request = yourMethodToCreateRequest()
val marker = Instana.startCapture(request.url().toString(), viewName: "User Details")
val response = OkHttpClient().newCall(request).execute()
marker?.finish(response)
val marker = Instana.startCapture("https://example.com/user", viewName: "User Details")
// Complete request and manually obtain any relevant information
val httpMarkerData = HTTPMarkerData(
            requestMethod = "GET",
            responseStatusCode = 200,
            responseSizeEncodedBytes = 200,
            responseSizeDecodedBytes = 1000
        )
marker?.finish(httpMarkerData)
HTTPMarker marker = Instana.startCapture("https://example.com/user", "User Details");
// Complete request and manually obtain any relevant information
HTTPMarkerData data = new HTTPMarkerData.Builder()
        .requestMethod("GET")
        .responseStatusCode(200)
        .responseSizeEncodedBytes(200)
        .responseSizeDecodedBytes(1000)
        .build();
marker.finish(data);

Views

Instana can segment mobile app insights by logical views. To do so, set the view name via the Instana.setView(String) method. The view will then be associated to all monitored beacons until the view changes once setView is called again.

We recommend not to use technical or generic names like the Class (e.g. WebViewActivity) to define views. We recommend the usage of readable names for views, for example product detail page or payment selection. Focusing on what users are experience will allow team members without intimate knowledge of the codebase to understand the insights provided.

Note: Instana.setView(String) should be called when a screen is presented to the user, rather than when a screen is created (as in a Fragment which could be created once but shown multiple times). Setting the view name will also enable Instana to track page transitions in addition to page loads.

Example

class WebViewActivity : AppCompatActivity() {

    override fun onResume() {
        super.onResume()
        Instana.view = "Webview: FitBit authorization"
    }
}

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 early as possible in the app launch process.

Instana {
    void setUserId(@Nullable String)
    @Nullable String getUserId()
    void setUserName(@Nullable String)
    @Nullable String getUserName()
    void setUserEmail(@Nullable String)
    @Nullable String getUserEmail()
}

Example

class MyApp : Application() {

    override fun onCreate() {
        super.onCreate()
        Instana.setup(
            this,
            InstanaConfig(
                key = BuildConfig.INSTANA_KEY,
                reportingURL = BuildConfig.INSTANA_REPORTING_URL
            )
        )
        Instana.userId = "1234567890"
        Instana.userEmail = "instana@example.com"
        Instana.userName = "instana android agent demo"
    }
}

Meta data

Arbitrary meta data can optionally be attached to all data transmitted to Instana. Consider using this to track UI configuration values, settings, feature flags… any additional context that might be useful for analysis.

Note: Currently, up to 50 meta key/value pairs are supported. The key can be up to 98 characters, and the value can be up to 1024 characters.

Instana {
     val meta = MaxCapacityMap<String, String>(50)
}

Properties

Parameter
Description
meta (MaxCapacityMap) The object which will hold all meta key/value pairs. It's interface resembles that of a common Map; you can add and remove elements as usual, as long as you don't go over it's maximum capacity

Example

class UserProfileActivity : AppCompatActivity() {

    override fun onResume() {
        super.onResume()
        Instana.meta.put("user authenticated", "true")
        Instana.meta.put("user type", "editor")
    }
}

Excluding URLs from monitoring

URLs can be ignored by providing regular expressions, by adding them to the ignoreURLs list. A good scenario for usage of this function would be to ignore all HTTP requests that contain any sensitive data like a password.

Only automatically monitored URLs will be ignored. Manually monitored URLs will not be ignored.

Instana {
    val ignoreURLs = mutableListOf<Regex>()
}
Instana {
    List<Pattern> getIgnoreURLs()
}

Example

class MyApp : Application() {

    override fun onCreate() {
        super.onCreate()
        Instana.setup(
            this,
            InstanaConfig(
                key = BuildConfig.INSTANA_KEY,
                reportingURL = BuildConfig.INSTANA_REPORTING_URL
            )
        )
        Instana.ignoreURLs.add("/.*([&?])password=.*/i".toRegex())
    }
}

The example ignores all URLs that contain a password in the query.

Report custom events

Custom events enable reporting about non-standard activities, important interactions and custom timings to Instana. This can be especially helpful when analyzing uncaught errors (breadcrumbs) and to track additional performance metrics.

Instana {
    fun reportEvent(event: CustomEvent)
}

The Instana-provided CustomEvent allows you to set multiple parameters, eventName (in its constructor) being the only mandatory one.

Configuration parameters

Parameter
Description
eventName (String) Name for the custom event. It will be prominently shown in the Instana Dashboard
startTime (Long, optional) Timestamp in which the event started, defined in milliseconds since Epoch. Will default to Now()-duration
duration (Long, optional) Duration duration of the event defined in milliseconds. Will default to 0
viewName (String, optional) Logical view in which the event happened. Will default to the current view set in Instana.view
meta (Map<String, String>, optional) Map of meta values. These will be merged with the global Instana.meta tags for this event; they won't be applied to any other future event
backendTracingID (String, optional) Tracing ID sent by the Instana-enabled server in the Server-Timing header as intid;desc=backendTracingID
error (Throwable, optional) Error Throwable to provide additional context, if any

Examples

val myEvent = CustomEvent("MyCustomEvent").apply {
    duration = 300
    meta = mapOf("keyOne" to "valueOne", "keyTwo" to "valueTwo")
    backendTracingID = "1234567890"
}

Instana.reportEvent(myEvent)
Map<String,String> myMetas = new HashMap<>();
myMetas.put("keyOne", "valueOne");
myMetas.put("keyTwo", "valueTwo");

CustomEvent myEvent = new CustomEvent("MyCustomEvent");
myEvent.setDuration(300L, TimeUnit.MILLISECONDS);
myEvent.setMeta(myMetas);
myEvent.setBackendTracingID("1234567890");

Instana.reportEvent(myEvent);

Google play services

You can explicitly tell Instana whether Google Play Services are available for a given user & session.

Instana {
    val googlePlayServicesMissing: Boolean?
}

Example

class MyApp : Application() {

    override fun onCreate() {
        super.onCreate()
        Instana.setup(
            this,
            InstanaConfig(
                key = BuildConfig.INSTANA_KEY,
                reportingURL = BuildConfig.INSTANA_REPORTING_URL
            )
        )
        Instana.googlePlayServicesMissing = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this) != ConnectionResult.SUCCESS
    }
}
//app/build.gradle
dependencies {
    implementation 'com.google.android.gms:play-services-basement:17.1.1'
    implementation 'com.google.android.gms:play-services-base:17.1.0'
}

Logging facade

By default, Instana will log directly into LogCat. You can pipe these logs by providing an object implementing the Logger interface:

interface Logger {
    fun log(level: Int, tag: String, message: String, error: Throwable?)
}

Instana {
    var logger: com.instana.android.Logger?
}

Configuration parameters

Parameter
Description
level (Int) Log level defined by one of android.util.Log levels (android.util.Log.INFO, android.util.Log.ERROR, ...)
tag (String) Internal Instana Agent tag
message (String) Log message generated by Instana
error (Throwable, optional) Error Throwable to provide additional context, if any

Example

Instana.logger = object : Logger {
    override fun log(level: Int, tag: String, message: String, error: Throwable?) {
        Log.d("my_tag", "intercepted Instana Android Agent log message: '$message'")
    }
}

Logging levels

By default, Instana will generate INFO level logs. You change this by defining any log level out of the common android.util.Log levels (android.util.Log.INFO, android.util.Log.ERROR, ...):

Instana {
    var logLevel: Int
}

Example

Instana.logLevel = android.util.Log.ERROR

Enable/Disable Data Collection

You can enable or disable data collection and submission at any time, such as at agent startup or during runtime.

This is most useful in scenarios where explicit user consent is required before the collection of data can proceed.

Instana {
    fun setCollectionEnabled(enabled: Boolean)
    fun isCollectionEnabled()
}

Example

Instana.setCollectionEnabled(true)

Redact URL Query parameters

Query parameters in collected URLs might contain sensitive data. Therefore, the Instana 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 agent is configured with a list of three regex patterns to automatically redact query parameter values:

  • "key"
  • "secret"
  • "password"

Redaction will only be applied to automatically monitored requests and their associated logs. Manually monitored requests are not redacted.

Instana {
    val redactHTTPQuery = mutableListOf<Regex>()
}

Example

class MyApp : Application() {

    override fun onCreate() {
        super.onCreate()
        Instana.setup(
            this,
            InstanaConfig(
                key = BuildConfig.INSTANA_KEY,
                reportingURL = BuildConfig.INSTANA_REPORTING_URL
            )
        )

        // in order to for example redact "https://example.com?secret=abcdef" into "https://example.com?secret=<redacted>"
        Instana.redactHTTPQuery.add("secret".toRegex())
        // in order to for example redact "https://example.com?hidden1=abcdef&hidden2=123456" into "https://example.com?hidden1=<redacted>&hidden2=<redacted>"
        Instana.redactHTTPQuery.add("^hidden[0-9]".toRegex())
    }
}

Capture HTTP headers

Optionally, the Instana agent can capture the HTTP headers of every tracked request/response.

A list of regex patterns can be defined to determine which headers will be captured.

If the same header name is present in both a request and its response, only the response's header value will be kept.

Instana {
    val captureHeaders = mutableListOf<Regex>()
}

Example

class MyApp : Application() {

    override fun onCreate() {
        super.onCreate()
        Instana.setup(
            this,
            InstanaConfig(
                key = BuildConfig.INSTANA_KEY,
                reportingURL = BuildConfig.INSTANA_REPORTING_URL
            )
        )

        // in order to capture all request/response headers like: "X-MyCompany-name1", "X-MyCompany-name2"...
        Instana.captureHeaders.add("X-MyCompany-.*".toRegex())
    }
}

Slow sending mode

The slow sending mode feature is disabled by default. If required, you can enable this 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 slowSendIntervalMillis parameter. Each beacon sending consists of only one beacon instead of a batch (maximum 100 beacons in a batch). The Instana agent stays in slow sending mode until one beacon is sent successfully.

The valid time range for slowSendIntervalMillis is 2000-3600000 milliseconds.

Example

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        Instana.setup(
            this,
            InstanaConfig(
                key = BuildConfig.INSTANA_KEY,
                reportingURL = BuildConfig.INSTANA_REPORTING_URL,
                slowSendIntervalMillis = 60000
            )
        )
    }
}