Android monitoring API
You can use the Instana Android agent API to monitor your Android applications.
- Instana Android agent
- Setting up Instana monitoring
- Checking current configuration
- Retrieving the session identifier
- Automatic HTTP monitoring
- Manual HTTP monitoring
- Setting views
- Identifying users
- Adding metadata
- Excluding URLs from monitoring
- Reporting custom events
- Availability of Google Play services
- Logging facade
- Defining logging levels
- Enabling or disabling data collection
- Redacting URL Query parameters
- Capturing HTTP headers
- Enabling slow sending mode
- Tracing user session ID
- Capturing composable UI name
Instana Android agent
You can use the Instana Android agent through the Instana
class methods.
Setting up Instana monitoring
To set up the Instana monitoring for Android applications, initialize Instana in your Application
class' onCreate()
, immediately 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 ) |
The 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 sets up all the additional parameters, such as Session Identifiers , before the agent sends any
beacon to the Instana server. Only the transmission of the beacons are delayed. The monitoring and capturing of beacons start 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) |
(public 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. |
usiRefreshTimeIntervalInHrs (Long , optional) |
This parameter determines the time interval for refreshing the usi (userSessionIdentifier). The usi serves as a unique identifier, which is assigned to the application when identifying user data is not explicitly provided or when the application doesn't possess any user context. If this parameter is set to a negative value, the usi retains its default behavior and never refreshes. If this parameter is set
to a value of zero, the usi is not sent to the backend, and thus the identifier is deactivated. If this parameter is set to a positive value, the usi refreshes at the specified time intervals. The parameter
value needs to be provided in hours. The default value is `-1. |
autoCaptureScreenNames (Boolean , optional) |
(public preview) This parameter enables automatic capturing of screen names. Currently, it supports screen name capture for Android applications that are built by using Fragments and Activities with xml layouts (not applicable to composable or other UIs). Enabling this feature removes the need for the existing Instana.view implementation in the codebase, as it serves as a replacement. Screen names are captured at multiple levels as follows: * Activity * Fragments Activity: Name is automatically extracted from accessibility labels that are assigned to the root layout. If not found, the Activity class name is used as the screen name. Fragments: The agent first looks for labels in the navController , then in the fragment tags , and later in accessibility labels on
the root view. If none are available, it uses the Fragment class name as the screen name. Metadata for each captured view includes the local path, OnResume time (you might see a minor difference in actual and captured resume time as it is collected from callbacks), and class names of Fragments and Activities. It's important to note that auto capture is only functional for applications with minify disabled or pro-guard excluded for all Fragments as of now. The default value is false . |
Checking current configuration
To check the current Instana configuration, access the InstanaConfig
instance:
val currentConfig = Instana.config
Retrieving the session identifier
Each Instana agent instance has a unique session identifier that you might use for other purposes in your app.
Property
|
Description |
---|---|
sessionId (String , optional) |
The current session identifier. This session ID is created within the setup process. |
Example
val sessionId = Instana.sessionId
Automatic HTTP monitoring
By default, HTTP sessions are captured automatically. Upon initializing Instana (after you install the Instana Android plug-in and Instana Android SDK), the agent takes care of the rest.
The Instana Android agent automatically weaves 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.
Manual HTTP monitoring
You can also monitor HTTP sessions manually.
Starting capture
This function returns the HTTPMarker
, which you need later when the request is 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) |
The name of the visible view that is related to this request. |
requestHeaders (Map<String,String> , optional) |
The name and values for the request header. |
This function returns the HTTP marker that you can use to set the response size and call the finish or error state when the request is completed.
Finishing capture
After the request is 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)
}
Cancelling capture
If the request is canceled before completion, start the following method on HTTPMarker
:
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);
Setting views
Instana can segment mobile app insights by logical views. To do so, set the view name through the Instana.setView(String)
method. The view is then associated to all monitored beacons until the view changes when setView
is called again.
Do not use technical or generic names like the Class (for example, WebViewActivity
) to define views. Use readable names for views, for example, product detail page
or payment selection
. By focusing on
user experience, team members without intimate knowledge of the codebase can understand the insights that are provided.
Instana.setView(String)
must be called when a screen is presented to the user, rather than when a screen is created (as in a Fragment, which can be created once but shown multiple times). Setting the view name also enables 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 that is transmitted to Instana. This information can then be used to unlock the following extra capabilities:
- Calculating the number of users affected by errors
- Filtering data for specific users
- Identifying the user who initiated a view change or HTTP request
By default, Instana associates any user-identifiable information to beacons. Be aware of the respective data protection laws when you choose to send user-specific information to Instana. Identify users through a user ID. For Instana, this
action is a 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.
If you handle anonymous users and thus don't have access to user IDs, you can alternatively use session IDs. Session IDs are not as helpful as user IDs when you filter data, but they are a good indicator to calculate affected or unique user
metrics. You must set a username, such as Anonymous
to have a clear differentiation between authenticated and unauthenticated users. Session IDs can be sensitive data (depending on the framework or platform used). To avoid transmitting
data to Instana that can grant access, hash session IDs.
Data already transmitted to the Instana backend cannot be retroactively updated. Therefore, you must call this API as early as possible in the app launch process.
If user data is not provided or the application lacks any user context, the usi
(userSessionIdentifier) is retrieved from the beacon. The usi
functions as a distinct identifier, which is assigned to the application
for uniquely identifying users in scenarios where user data is not available. By using the usiRefreshTimeIntervalInHrs
parameter in the Configuration parameters section, you can specify
the time interval for refreshing the usi
.
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"
}
}
Adding metadata
Arbitrary metadata can optionally be attached to all data transmitted to Instana. You can use this metadata to track UI configuration values, settings, feature flags, and any additional context that might be useful for analysis.
Currently, up to 50 meta key or 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 that holds all meta key or value pairs. Its interface resembles that of a common Map. You can add and remove elements as usual, if you don't go over the object'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 are ignored. Manually monitored URLs are not 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.
Reporting custom events
Custom events enable reporting about nonstandard activities, important interactions, and custom timings to Instana. This reporting can be especially helpful to analyze undetected errors (breadcrumbs) and to track extra performance metrics.
Instana {
fun reportEvent(event: CustomEvent)
}
With CustomEvent
provided by Instana, you can set multiple parameters, eventName
(in its constructor) being the only mandatory one.
Configuration parameters
Parameter
|
Description |
---|---|
eventName (String ) |
Name for the custom event. It is prominently shown in the Instana Dashboard |
startTime (Long , optional) |
Timestamp in which the event started, which is defined in milliseconds since Epoch. Defaults to Now()-duration . |
duration (Long , optional) |
Duration of the event, which is defined in milliseconds. Defaults to 0. |
viewName (String , optional) |
Logical view in which the event happened. Defaults to the current view set in Instana.view . |
meta (Map<String, String> , optional) |
Map of meta values. These values are merged with the global Instana.meta tags for this event. They won't be applied to any other future event. Do not include sensitive information with meta . |
backendTracingID (String , optional) |
Tracing ID that is sent by the Instana-enabled backend in the Server-Timing header as intid;desc=backendTracingID . |
error (Throwable , optional) |
Error that is thrown to provide extra context, if any. |
customMetric (Double , optional) |
Option for supplying custom metric data with precision up to four decimal places. Do not include sensitive information in this metric. |
Examples
val myEvent = CustomEvent("MyCustomEvent").apply {
duration = 300
meta = mapOf("keyOne" to "valueOne", "keyTwo" to "valueTwo")
backendTracingID = "1234567890"
customMetric = 98.7654
}
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);
Availability of Google Play services
You can explicitly tell Instana whether Google Play services are available for a specific user and 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 logs directly into LogCat. You can pipe these logs by providing an object that implements 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 that is thrown to provide more 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'")
}
}
Defining logging levels
By default, Instana generates INFO level logs. You change this default by defining any log level out of the common android.util.Log
levels (android.util.Log.INFO
, android.util.Log.ERROR
, or other levels):
Instana {
var logLevel: Int
}
Example
Instana.logLevel = android.util.Log.ERROR
Enabling or disabling data collection
You can enable data collection and submission at any time, such as when the Instana agent starts or during the runtime.
This feature 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)
Redacting 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 must be redacted; any redacted value is replaced with <redacted>
.
Redaction happens within the Instana agent before the agent reports to the Instana backend. Therefore, secrets do not reach the Instana backends for processing and are not 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 is only 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())
}
}
Capturing HTTP headers
Optionally, the Instana agent can capture the HTTP headers of every tracked request or response.
A list of regex patterns can be defined to determine which headers are captured.
If the same header name is present in both a request and its response, only the response's header value is 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())
}
}
Enabling 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 resending 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 (a maximum of 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
)
)
}
}
Tracing user session ID
By default, the user session is tracked, and the ID is a randomly generated Universally Unique Identifier (UUID). This ID remains unchanged while the app is installed. You can configure the expiration time of the user session ID by using the
usiRefreshTimeIntervalInHrs
parameter. The following parameter values indicate the status of the user session ID:
-
Negative number: This value indicates that the user session ID never expires. The default value is -1.
-
Positive number: This value means that the user session ID is refreshed after the set time, that is, a new UUID is generated and used.
-
Zero: This value denoted by 0.0 means that the user session ID is disabled.
Example
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
Instana.setup(
this,
InstanaConfig(
key = BuildConfig.INSTANA_KEY,
reportingURL = BuildConfig.INSTANA_REPORTING_URL,
usiRefreshTimeIntervalInHrs = 24
)
)
}
}
Capturing composable UI name
To automatically capture the screen names of composable UIs, you can add addInstanaObserver()
extension function to the NavHostController
object in your composable application. This function collects names of the
route path that are specified for composable navigation.
Example
@Composable
fun RootNavigationGraph(navHostController: NavHostController, context: Context) {
NavHost(
navController = navHostController,
route = Graph.ROOT,
startDestination = Graph.INITIAL_FLOW,
) {
initNavGraph(navHostController, context)
composable(route = Graph.HOME) {
navHostController.addInstanaObserver() //Adding Instana observer as a extension function.
HomeScreen()
}
}
}