Instrumentation via OneAgent SDK for Android
Use the OneAgent SDK for Android to report additional details about the user sessions in your mobile app. The OneAgent SDK for Android allows you to create custom actions, report errors, tag specific users, and more. The sections below explain how to enable these capabilities.
You can use the OneAgent SDK in Java and Kotlin.
Start OneAgent
If you've disabled auto-start with the autoStart.enabled
property or you're using standalone manual instrumentation instead of auto-instrumentation, start OneAgent manually in the Application.onCreate
method. Use the Dynatrace.startup(Application, Configuration)
API method.
public class YourApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
// provide the application context as parameter
Dynatrace.startup(this, new DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconUrl>")
... // additional configuration
.buildConfiguration());
}
}
class YourApplication : Application() {
override fun onCreate() {
super.onCreate()
// provide the application context as parameter
Dynatrace.startup(this, DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconUrl>")
... // additional configuration
.buildConfiguration())
}
}
If you need to start OneAgent at a later stage, use the Dynatrace.startup(Activity, Configuration)
API method. You have to provide the active Activity
as a parameter so that OneAgent can immediately monitor it.
Dynatrace.startup(yourActiveActivity, new DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconUrl>")
... // additional configuration
.buildConfiguration());
Dynatrace.startup(yourActiveActivity, DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconUrl>")
... // additional configuration
.buildConfiguration())
If your app supports Direct Boot, ensure that Dynatrace.startup
is never called from a Direct Boot aware component. Also see Adjust communication with OneAgent SDK for Android to make sure that OneAgent can transmit data to the Dynatrace Cluster.
Configure OneAgent
Use the DynatraceConfigurationBuilder class to customize OneAgent settings.
new DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconURL>")
.withUserOptIn(true)
.withCrashReporting(true)
.buildConfiguration();
DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconURL>")
.withUserOptIn(true)
.withCrashReporting(true)
.buildConfiguration()
If you use a combination of manual and auto-instrumentation, the auto-instrumentation injects a Dynatrace.startup
call into the Application.onCreate
method. In this case, the injected Dynatrace.startup
call is called before your manual Dynatrace.startup
call, so your manual configuration is ignored.
Use the autoStart.enabled
property to deactivate the auto-start feature from the auto-instrumentation. You can then define a manual Dynatrace.startup
call. In this case, you can override the values pre-configured from the auto-instrumentation.
User action monitoring
With user action monitoring, you can define and report custom actions. You can then enrich these custom actions using the following monitoring operations:
- Create a child action
- Report an event
- Report a value
- Report an error
- Attach a web request to the user action
Custom actions are different from the user actions created with the Dynatrace Android Gradle plugin. OneAgent does not automatically add additional events, such as web requests, to custom actions or close custom actions. However, when OneAgent shuts down or has to start a new session, it closes all open custom actions.
Create custom actions
You can create custom actions and enhance them with additional information. If custom actions are not closed explicitly, OneAgent closes them and sends them to the Dynatrace Cluster.
Call enterAction
to start a custom action and leaveAction
to close a custom action. Timing is measured automatically.
// start a custom action
DTXAction action = Dynatrace.enterAction("Tap on Search");
// ...do some work here...
// end a custom action
action.leaveAction();
// start a custom action
val action = Dynatrace.enterAction("Tap on Search")
// ...do some work here...
// end a custom action
action.leaveAction()
For a mobile custom action or a mobile autogenerated user action, the maximum name length is 250 characters.
The maximum duration of a mobile custom action is 9 minutes.
If a custom action takes longer than 9 minutes and is not closed, such an action is discarded and not reported to Dynatrace.
Create child actions
Child actions are similar to parent actions. When the parent action is closed, OneAgent automatically closes all child actions of the parent action.
Generate child actions using the Dynatrace.enterAction(String, DTXAction)
method.
// start a parent custom action
DTXAction parentAction = Dynatrace.enterAction("Tap on Search");
// ...do some work here...
// start a child action
DTXAction childAction = Dynatrace.enterAction("Tap on Confirm", parentAction);
// ...do some work here...
// end a child action
childAction.leaveAction();
// ...do some work here...
// end a parent custom action
parentAction.leaveAction();
// start a parent custom action
val parentAction = Dynatrace.enterAction("Tap on Search")
// ...do some work here...
// start a child action
val childAction = Dynatrace.enterAction("Tap on Confirm", parentAction)
// ...do some work here...
// end a child action
childAction.leaveAction()
// ...do some work here...
// end a parent custom action
parentAction.leaveAction()
For a mobile custom action or a mobile autogenerated user action, the maximum name length is 250 characters.
Cancel custom actions
OneAgent for Android version 8.231+
If you need to cancel an already created but not yet completed custom action, use the DTXAction#cancel()
API call.
Canceling an action discards all data associated with it: all reported values are discarded and all child actions are canceled. Also, note that you cannot cancel a completed action.
// create a custom action
DTXAction action = Dynatrace.enterAction("Tap on Purchase");
try {
// ...do some work here...
performWork();
// close the custom action. All associated data is stored and sent to Dynatrace
action.leaveAction();
}
catch(Exception e) {
// cancel the custom action. All associated data is discarded.
action.cancel();
}
// create a custom action
val action = Dynatrace.enterAction("Tap on Purchase")
try {
// ...do some work here...
performWork()
// close the custom action. All associated data is stored and sent to Dynatrace
action.leaveAction()
} catch (e: Exception) {
// cancel the custom action. All associated data is discarded.
action.cancel()
}
Determine custom action state
OneAgent for Android version 8.231+
Sometimes it's helpful to know whether a custom action is still open and can be used to report data.
To check the state of a custom action, use the DTXAction#isFinished()
method.
A custom action is finished when the action is:
- Completed via
DTXAction#leaveAction()
, or - Canceled via
DTXAction#cancel()
, or - Terminated by OneAgent (for example, when OneAgent shuts down)
Note that you shouldn't interact with a finished custom action.
Custom action code sample
The following code snippet shows a sample instrumentation of the fictional method search, which makes a web request to an instrumented server and parses the received result. The following instrumentation actions are part of the code snippet:
- Creates a custom action
- Reports a value
- Reports a error
- Monitors a web request
- Creates a child action
public boolean search(String query) {
// [1a] start a parent custom action
DTXAction searchAction = Dynatrace.enterAction("Tap on Search");
// [2] report a value
searchAction.reportValue("query", query);
URL url;
try {
url = new URL("https://www.example.com/?query=" + query);
} catch (MalformedURLException e) {
// [3] report an error
searchAction.reportError("invalid url", e);
// [1b] end a parent custom action
searchAction.leaveAction();
return false;
}
// [4.1] Generate a new unique tag associated with the custom action "Tap on Search"
String uniqueRequestTag = searchAction.getRequestTag();
// [4.2] Generate a WebRequestTiming object based on the unique tag
WebRequestTiming timing = Dynatrace.getWebRequestTiming(uniqueRequestTag);
Request request = new Request.Builder()
.url(url)
// [4.3] Place the Dynatrace HTTP header on your web request
.addHeader(Dynatrace.getRequestTagHeader(), uniqueRequestTag)
.build();
// [4.4] Start web request timing before the HTTP request is sent
timing.startWebRequestTiming();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
// [4.5] Stop web request timing when a connection exception occurs
timing.stopWebRequestTiming(url, response.code(), response.message());
return false;
}
String body = response.body().string();
// [4.5] Stop web request timing when the HTTP response is received and the response body is obtained
timing.stopWebRequestTiming(url, response.code(), response.message());
// [5a] start a child action
DTXAction parseAction = Dynatrace.enterAction("Parse result", searchAction);
parseResult(body);
// [5b] end a child action
parseAction.leaveAction();
return true;
} catch (IOException e) {
// [4.5] Stop web request timing when a connection exception occurs
timing.stopWebRequestTiming(url, -1, e.toString());
return false;
}
finally {
// [1b] end a parent custom action
searchAction.leaveAction();
}
}
fun search(query: String): Boolean {
// [1a] start a parent custom action
val searchAction = Dynatrace.enterAction("Tap on Search")
// [2] report a value
searchAction.reportValue("query", query)
var url: URL? = null
try {
url = URL("https://www.example.com/?query=$query")
} catch (e: MalformedURLException) {
// [3] report an error
searchAction.reportError("invalid url", e)
// [1b] end a parent custom action
searchAction.leaveAction()
return false
}
// [4.1] Generate a new unique tag associated with the custom action "Tap on Search"
val uniqueRequestTag = searchAction.requestTag
// [4.2] Generate a WebRequestTiming object based on the unique tag
val timing = Dynatrace.getWebRequestTiming(uniqueRequestTag)
val request = Request.Builder()
.url(url)
// [4.3] Place the Dynatrace HTTP header on your web request
.addHeader(Dynatrace.getRequestTagHeader(), uniqueRequestTag)
.build()
try {
// [4.4] Start web request timing before the HTTP request is sent
timing.startWebRequestTiming()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) {
// [4.5] Stop web request timing when a connection exception occurs
timing.stopWebRequestTiming(url, response.code, response.message)
return false
}
val body = response.body!!.string()
// [4.5] Stop web request timing when the HTTP response is received and the response body was obtained
timing.stopWebRequestTiming(url, response.code, response.message)
// [5a] start a child action
val parseAction = Dynatrace.enterAction("Parse result", searchAction)
parseResult(body)
// [5b] end a child action
parseAction.leaveAction()
}
return true
} catch (e: IOException) {
// [4.5] Stop web request timing when a connection exception occurs
timing.stopWebRequestTiming(url, -1, e.toString())
return false
} finally {
// [1b] end a parent custom action
searchAction.leaveAction()
}
}
Custom value reporting
Using the OneAgent SDK for Android, you can report events, values, and errors. Reported events, values, and errors that are part of a user action are then displayed in the user action waterfall analysis. Reported errors (both standalone and "attached" to a user action) are also displayed on the user session details page and multidimensional User action analysis page.
Report an event
With reportEvent
, you can report a specific event. The reported event must be part of a user action.
action.reportEvent("event_name");
action.reportEvent("event_name")
If you want to report standalone events with lots of additional information, see Business event reporting.
Report a value
The reportValue
method allows you to report your own metrics. These metrics must be part of a user action.
The OneAgent SDK allows you to report metrics with the following value types:
Metrics with type long
are supported for OneAgent SDK versions 8.197+.
// report int
action.reportValue("int_metrics_name", 5);
// report long
action.reportValue("long_metrics_name", 5L);
// report double
action.reportValue("double_metrics_name", 5.6);
// report string
action.reportValue("string_metrics_name", "exampleValue");
// report int
action.reportValue("int_metrics_name", 5)
// report long
action.reportValue("long_metrics_name", 5L)
// report double
action.reportValue("double_metrics_name", 5.6)
// report string
action.reportValue("string_metrics_name", "exampleValue")
Report an error
The reportError
method is different from the reportValue
method, as it is specifically identified as an error type event.
The OneAgent SDK allows you to report the following:
- Error codes. Use the
reportError(String, int)
method. - Handled exceptions. Use the
reportError(String, Throwable)
method.
There are two options for reporting an error event. You can report an error as part of a user action or as a standalone error, which is generated as a global event that is not tied to a specific user action.
Error within a user action
// report an error code
action.reportError("error_code_name", -1);
// report an exception
action.reportError("exception_name", exception);
// report an error code
action.reportError("error_code_name", -1)
// report an exception
action.reportError("exception_name", exception)
Standalone error
You can report standalone error events via the Dynatrace
class.
// report an error code
Dynatrace.reportError("error_code_name", -1);
// report an exception
Dynatrace.reportError("exception_name", exception);
// report an error code
Dynatrace.reportError("error_code_name", -1)
// report an exception
Dynatrace.reportError("exception_name", exception)
Business event reporting
OneAgent for Android version 8.253+
With sendBizEvent
, you can report business events. These are standalone events, as OneAgent sends them separately from user actions or user sessions.
For more information on business events, see Business Analytics in Dynatrace.
JSONObject attributes = new JSONObject();
try {
attributes.put("event.name", "Confirmed Booking");
attributes.put("screen", "booking-confirmation");
attributes.put("product", "Danube Anna Hotel");
attributes.put("amount", 358.35);
attributes.put("currency", "USD");
attributes.put("reviewScore", 4.8);
attributes.put("arrivalDate", "2022-11-05");
attributes.put("departureDate", "2022-11-15");
attributes.put("journeyDuration", 10);
attributes.put("adultTravelers", 2);
attributes.put("childrenTravelers", 0);
Dynatrace.sendBizEvent("com.easytravel.funnel.booking-finished", attributes);
} catch (JSONException e) {
// handle exception
}
try {
JSONObject().apply {
put("event.name", "Confirmed Booking")
put("screen", "booking-confirmation")
put("product", "Danube Anna Hotel")
put("amount", 358.35)
put("currency", "USD")
put("reviewScore", 4.8)
put("arrivalDate", "2022-11-05")
put("departureDate", "2022-11-15")
put("journeyDuration", 10)
put("adultTravelers", 2)
put("childrenTravelers", 0)
}.also { jsonObject->
Dynatrace.sendBizEvent("com.easytravel.funnel.booking-finished", jsonObject)
}
} catch (e: JSONException) {
// handle exception
}
Lifecycle monitoring
OneAgent for Android version 8.223+
With lifecycle monitoring, OneAgent collects the following data:
- Activity display: Measures the timespan from
Activity.onCreate(Bundle)
toActivity.onPostResume()
and reports the time of each activity lifecycle state that is entered. - Activity redisplay: Measures the time it takes to redisplay a previously created activity and reports the time of each activity lifecycle state that is entered until the activity is visible again.
Activity lifecycle monitoring is turned on by default, but you can disable it with the withActivityMonitoring
method.
new DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconURL>")
.withActivityMonitoring(false)
.buildConfiguration();
DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconURL>")
.withActivityMonitoring(false)
.buildConfiguration()
Web request monitoring
The Dynatrace Android Gradle plugin automatically instruments most web requests. However, you have to manually instrument requests in the following cases:
- When the requests of a third-party framework aren't instrumented
- When you need to report non-HTTP(S) requests
- If you've disabled web request monitoring
For HTTP(S) requests, never combine automatic and manual web request instrumentation. However, you can use automatic instrumentation for HTTP(S) requests and manual instrumentation for non-HTTP(S) requests.
To track web requests, add the x-dynatrace
HTTP header with a unique value to the web request. This is required to correlate the server-side monitoring data to the corresponding mobile web request. Additionally, the timing values from the mobile side must be measured.
To monitor a web request
- Generate a new unique tag.
- Generate a
WebRequestTiming
object based on the tag. - Place the Dynatrace HTTP header on your web request.
- Start web request timing before the HTTP request is sent.
- Stop web request timing.
- The HTTP response is received, and the response body is obtained.
- A connection exception occurs.
There are two types of web requests in terms of their hierarchy:
-
Standalone requests. For these requests, OneAgent automatically tries to find an appropriate user action. If it finds one, the web request is attached to the user action. The web request is only reported as a standalone web request when no appropriate user action is found.
Currently, you cannot view standalone requests in Session segmentation.
Attach a web request to a user action
To attach a web request to a user action, generate a unique tag with the DTXAction.getRequestTag()
method.
The following sample shows how to attach a synchronous OkHttp
web request to the "Search request"
user action.
URL url = new URL("https://www.example.com");
// First, create a custom action
DTXAction webAction = Dynatrace.enterAction("Search request");
// [1] Generate a new unique tag associated with the user action
String uniqueRequestTag = webAction.getRequestTag();
// [2] Generate a WebRequestTiming object based on the unique tag
WebRequestTiming timing = Dynatrace.getWebRequestTiming(uniqueRequestTag);
// Define your OkHttp request. This varies greatly depending on your implementation
Request request = new Request.Builder()
.url(url)
// Define your headers for the OkHttp request
.addHeader(yourKey1, yourValue1)
.addHeader(yourKey2, yourValue2)
// [3] Place the Dynatrace HTTP header on your web request
.addHeader(Dynatrace.getRequestTagHeader(), uniqueRequestTag)
.build();
// [4] Start web request timing before the HTTP request is sent
timing.startWebRequestTiming();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
// handle response
String body = response.body().string();
}
// [5.1] Stop web request timing when the HTTP response is received and the response body was obtained
timing.stopWebRequestTiming(url, response.code(), response.message());
} catch (IOException e) {
// [5.2] Stop web request timing when a connection exception occurs
timing.stopWebRequestTiming(url, -1, e.toString());
// user-defined exception handling
}
finally {
// Lastly, end the custom action
webAction.leaveAction();
}
val url = URL("https://www.example.com")
// First, create a custom action
val webAction = Dynatrace.enterAction("Search request")
// [1] Generate a new unique tag associated with the user action
val uniqueRequestTag = webAction.requestTag
// [2] Generate a WebRequestTiming object based on the unique tag
val timing = Dynatrace.getWebRequestTiming(uniqueRequestTag)
// Define your OkHttp request. This varies greatly depending on your implementation
val request = Request.Builder()
.url(url)
// Define your headers for the OkHttp request
.addHeader(yourKey1, yourValue1)
.addHeader(yourKey2, yourValue2)
// [3] Place the Dynatrace HTTP header on your web request
.addHeader(Dynatrace.getRequestTagHeader(), uniqueRequestTag)
.build()
try {
// [4] Start web request timing before the HTTP request is sent
timing.startWebRequestTiming()
client.newCall(request).execute().use { response ->
if (response.isSuccessful) {
// handle response
val body = response.body!!.string()
}
// [5.1] Stop web request timing when the HTTP response is received and the response body was obtained
timing.stopWebRequestTiming(url, response.code, response.message)
}
} catch (e: IOException) {
// [5.2] Stop web request timing when a connection exception occurs
timing.stopWebRequestTiming(url, -1, e.toString())
// user-defined exception handling
} finally {
// Lastly, end the custom action
webAction.leaveAction()
}
Monitor a standalone web request
To monitor a web request as a standalone request, generate a unique tag with the Dynatrace.getRequestTag()
method.
The following sample shows how to monitor a synchronous OkHttp
web request.
URL url = new URL("https://www.example.com");
// [1] Generate a new unique tag
String uniqueRequestTag = Dynatrace.getRequestTag();
// [2] Generate a WebRequestTiming object based on the unique tag
WebRequestTiming timing = Dynatrace.getWebRequestTiming(uniqueRequestTag);
// Define your OkHttp request. This varies greatly depending on your implementation
Request request = new Request.Builder()
.url(url)
// Define your headers for the OkHttp request
.addHeader(yourKey1, yourValue1)
.addHeader(yourKey2, yourValue2)
// [3] Place the Dynatrace HTTP header on your web request
.addHeader(Dynatrace.getRequestTagHeader(), uniqueRequestTag)
.build();
// [4] Start web request timing before the HTTP request is sent
timing.startWebRequestTiming();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
// handle response
String body = response.body().string();
}
// [5.1] Stop web request timing when the HTTP response is received and the response body was obtained
timing.stopWebRequestTiming(url, response.code(), response.message());
} catch (IOException e) {
// [5.2] Stop web request timing when a connection exception occurs
timing.stopWebRequestTiming(url, -1, e.toString());
// user-defined exception handling
}
val url = URL("https://www.example.com")
// [1] Generate a new unique tag
val uniqueRequestTag = Dynatrace.getRequestTag()
// [2] Generate a WebRequestTiming object based on the unique tag
val timing = Dynatrace.getWebRequestTiming(uniqueRequestTag)
// Define your OkHttp request. This varies greatly depending on your implementation
val request = Request.Builder()
.url(url)
// Define your headers for the OkHttp request
.addHeader(yourKey1, yourValue1)
.addHeader(yourKey2, yourValue2)
// [3] Place the Dynatrace HTTP header on your web request
.addHeader(Dynatrace.getRequestTagHeader(), uniqueRequestTag)
.build()
try {
// [4] Start web request timing before the HTTP request is sent
timing.startWebRequestTiming()
client.newCall(request).execute().use { response ->
if (response.isSuccessful) {
// handle response
val body = response.body!!.string()
}
// [5.1] Stop web request timing when the HTTP response is received and the response body was obtained
timing.stopWebRequestTiming(url, response.code, response.message)
}
} catch (e: IOException) {
// [5.2] Stop web request timing when a connection exception occurs
timing.stopWebRequestTiming(url, -1, e.toString())
// user-defined exception handling
}
Monitor non-HTTP(S) requests
OneAgent for Android version 8.249+
Monitoring of WebSocket connections is available starting with OneAgent for Android version 8.239. Monitoring of all non-HTTP(S) requests is available starting with OneAgent for Android version 8.249.
OneAgent for Android does not support auto-instrumentation of non-HTTP(S) requests. If you need to report requests such as a WebSocket request (starts with ws://
or wss://
), check the code samples below.
- Use the
stopWebRequestTiming(URI requestUri, int respCode, String respPhrase)
API method to manually instrument non-HTTP(S) requests. - Make sure to pass along the original URI. Do not retrieve the URI from the
OkHttp
object because this doesn't return the original URI. - This approach is only suitable for WebSocket connections that are open for up to about 9 minutes. Longer connections may not be reported.
- If you only have non-HTTP(S) requests, you can optionally disable web request monitoring.
- If you have both HTTP(S) and non-HTTP(S) requests, and HTTP(S) requests are auto-instrumented, don't disable web request monitoring.
final URI uri = URI.create("wss://websocket.example.com");
// First, create a custom action
DTXAction webSocketAction = Dynatrace.enterAction("WebSocket");
// Generate a WebRequestTiming object based on the unique request tag
WebRequestTiming timing = Dynatrace.getWebRequestTiming(webSocketAction.getRequestTag());
// Define your OkHttp request. This varies greatly depending on your implementation
Request request = new Request.Builder()
.url(uri.toString())
.build();
// Start web request timing when you are about to open a WebSocket connection
timing.startWebRequestTiming();
WebSocket webSocket = client.newWebSocket(request, new WebSocketListener() {
@Override
public void onClosing(@NonNull WebSocket webSocket, int code, @NonNull String reason) {
// Stop web request timing when the webSocket connection closes
// Don't retrieve the URI from the OkHttp object because it always replaces wss:// with https://
timing.stopWebRequestTiming(uri, code, reason);
// end the action
webSocketAction.leaveAction();
}
@Override
public void onFailure(@NonNull WebSocket webSocket, @NonNull Throwable t, @Nullable Response response) {
// Stop web request timing when the webSocket connection fails and customize the return code and message
// Don't retrieve the URI from the OkHttp object because it always replaces wss:// with https://
timing.stopWebRequestTiming(uri, 1011, "ERROR");
// end the action
webSocketAction.leaveAction();
}
});
val uri = URI.create("wss://websocket.example.com")
// First, create a custom action
val webSocketAction = Dynatrace.enterAction("WebSocket")
// Generate a WebRequestTiming object based on the unique request tag
val webRequestTiming = Dynatrace.getWebRequestTiming(webSocketAction.requestTag)
// Define your OkHttp request. This varies greatly depending on your implementation
val request = Request.Builder()
.url(uri.toString())
.build()
// Start web request timing when you are about to open a WebSocket connection
webRequestTiming.startWebRequestTiming()
val webSocket = client.newWebSocket(request, object : WebSocketListener() {
override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
// Stop web request timing when the webSocket connection closes
// Don't retrieve the URI from the OkHttp object because it always replaces wss:// with https://
webRequestTiming.stopWebRequestTiming(uri, code, reason)
// end the action
webSocketAction.leaveAction()
}
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
// Stop web request timing when the webSocket connection fails
// Don't retrieve the URI from the OkHttp object because it always replaces wss:// with https://
webRequestTiming.stopWebRequestTiming(uri, 1011, "ERROR")
// end the action
webSocketAction.leaveAction()
}
})
Crash reporting
OneAgent captures all unhandled exceptions and errors and sends the crash report to the server immediately. The Android crash report includes the occurrence time and the full stack trace of the exception.
You can deactivate crash reporting using the withCrashReporting
method:
new DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconURL>")
.withCrashReporting(false)
.buildConfiguration();
DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconURL>")
.withCrashReporting(false)
.buildConfiguration()
Tag specific users
You can tag each user of your mobile apps with a unique user name. This enables you to search and filter specific user sessions and analyze individual user behavior over time.
The following steps explain how to tag an individual user via the Dynatrace API.
Dynatrace.identifyUser("john.doe@example.com");
Dynatrace.identifyUser("john.doe@example.com")
OneAgent for Android version 237+ Sessions split due to idle or duration timeout are re-tagged automatically.
When OneAgent ends a tagged session because the session duration has reached its set limit or due to the user's inactivity, the subsequent session is re-tagged automatically. You don't need to provide the user identification information again.
However, note that OneAgent does not re-tag the subsequent session in the following cases:
- When you explicitly end a tagged user session via
endVisit
- When the user or the mobile operating system closes or force stops the app
- When OneAgent ends the current user session and generates a new session after the privacy settings have been changed
See User sessions > Session end to learn when OneAgent ends a mobile user session.
End a session
You can force a session to end via the Dynatrace API. This also closes all open actions and starts a new session.
Dynatrace.endVisit();
Dynatrace.endVisit()
Configure data privacy
With the user opt-in mode for mobile apps, you can dynamically adjust data privacy settings and build your apps in compliance with data protection laws and regulations.
To activate the user opt-in mode, enable the userOptIn
flag via the DSL from the Dynatrace Android Gradle plugin or use the ConfigurationBuilder.withUserOptIn
method.
With the Dynatrace.applyUserPrivacyOptions
method, you can adjust privacy settings based on the user's decision.
Dynatrace.applyUserPrivacyOptions(UserPrivacyOptions.builder()
.withDataCollectionLevel(DataCollectionLevel.USER_BEHAVIOR)
.withCrashReportingOptedIn(true)
.build()
);
Dynatrace.applyUserPrivacyOptions(UserPrivacyOptions.builder()
.withDataCollectionLevel(DataCollectionLevel.USER_BEHAVIOR)
.withCrashReportingOptedIn(true)
.build()
)
OneAgent persists the privacy settings and automatically applies them when the app is restarted. Additionally, OneAgent generates a new session whenever the privacy settings are changed via the Dynatrace.applyUserPrivacyOptions
method.
You can also retrieve the privacy settings with the Dynatrace.getUserPrivacyOptions
method. However, you should use this method after OneAgent starts.
Configure hybrid apps
For hybrid applications that use the RUM JavaScript inside WebView
(Android) or WKWebView
(iOS), cookies must be set for each instrumented domain or server that the application communicates with. When the hybrid app monitoring feature is enabled, OneAgent generates these cookies for every specified domain and stores them in CookieManager
.
Enable hybrid app monitoring
You can activate the hybrid app monitoring feature with the withHybridMonitoring
method. Specify all used domains, hosts, and IP addresses via the withMonitoredDomains
or the withMonitoredHttpsDomains
method. Start domains and sub-domains with a dot (.
).
withMonitoredDomains
method
new DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconURL>")
.withHybridMonitoring(true)
.withMonitoredDomains("<domain1>", "<domain2>")
.buildConfiguration();
DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconURL>")
.withHybridMonitoring(true)
.withMonitoredDomains("<domain1>", "<domain2>")
.buildConfiguration()
withMonitoredHttpsDomains
method
OneAgent for Android version 8.237+
Dynatrace allows you to add the Secure
cookie attribute for all cookies that are set by Dynatrace. This ensures that the browser sends these cookies only over secure connections.
new DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconURL>")
.withHybridMonitoring(true)
.withMonitoredHttpsDomains("https://<domain1>", "https://<domain2>")
.buildConfiguration();
DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconURL>")
.withHybridMonitoring(true)
.withMonitoredHttpsDomains("https://<domain1>", "https://<domain2>")
.buildConfiguration()
Instrument WebView
To enable communication between the RUM JavaScript and OneAgent for Android, instrument all WebView
objects before the URL is loaded with WebView.loadUrl(String)
. Instrument the Dynatrace.instrumentWebView
method for every WebView
that contains the RUM JavaScript. Without this, the monitoring data may not be associated with the same session.
WebView myWebView = (WebView) findViewById(R.id.webview);
Dynatrace.instrumentWebView(myWebView);
myWebView.loadUrl("http://www.example.com");
val myWebView: WebView = findViewById(R.id.webview)
Dynatrace.instrumentWebView(myWebView)
myWebView.loadUrl("http://www.example.com")
Due to security reasons, this API call is ignored on devices with API versions 15 and 16.
Preserve Dynatrace cookies
For hybrid apps, it is important to ensure that the Dynatrace cookies are not deleted. Without these cookies, Dynatrace cannot combine the monitoring data from the RUM JavaScript and OneAgent for Android into a single session.
When you delete cookies via CookieManager#removeAllCookies(ValueCallback)
or CookieManager#removeSessionCookies(ValueCallback)
, you should also call the restoreCookies
method to restore the Dynatrace cookies.
CookieManager.getInstance().removeAllCookies(null);
Dynatrace.restoreCookies();
CookieManager.getInstance().removeAllCookies(null)
Dynatrace.restoreCookies()
Enable load balancing
OneAgent allows you to enable client-side load balancing that helps avoid unbalanced load on the server when multiple OneAgents simultaneously establish a connection to ActiveGate.
new DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconURL>")
.withStartupLoadBalancing(true)
.buildConfiguration();
DynatraceConfigurationBuilder("<YourApplicationID>", "<ProvidedBeaconURL>")
.withStartupLoadBalancing(true)
.buildConfiguration()