Android Monitoring API
- Instana Android agent API
- Setup
- Current configuration
- Session identifier
- Automatic HTTP monitoring
- Manual HTTP monitoring
- Views
- Identifying users
- Meta data
- Excluding URLs from monitoring
- Report custom events
- Google play services
- Logging facade
- Logging levels
- Enable/Disable Data Collection
- Redact URL Query parameters
- Capture HTTP headers
- Slow sending mode
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
)
)
}
}