⚙️ Configure Transaction Monitoring for an Android Application
📄 Overview
GermainUX transactions measure the duration and outcome context of important operations performed by an Android application.
A transaction can represent:
|
Transaction example |
|---|
|
Application startup |
|
User interaction |
|
Network request |
|
Data synchronization |
|
Local database operation |
|
File processing |
|
Authentication |
|
Search |
|
Form submission |
|
Order or payment processing |
|
Business-process step |
|
Any custom operation whose duration should be measured |
Custom transaction monitoring requires the application to call:
|
When |
API call |
|---|---|
|
when the operation begins |
|
|
when it completes |
|
✏️ Transaction Design
Before adding instrumentation, define:
|
Property |
Purpose |
|---|---|
|
Transaction name |
Stable category used to aggregate similar operations |
|
View name |
Screen, activity, fragment, or application area where it occurs |
|
Details |
Optional non-sensitive context |
|
Start point |
Moment the measured operation begins |
|
End point |
Moment the operation completes or fails |
|
Failure reporting |
Related error or exception submitted separately |
Use stable transaction names such as:
|
Literal |
|---|
|
|
|
|
|
|
|
|
|
|
Do not generate a different transaction name for every execution. Dynamic values should not be included in the name because they prevent meaningful aggregation.
🚀 Start a Transaction
Start the transaction immediately before the operation being measured.
☕ Java
String transactionName = "Customer Search";
GermainAPM.startTransaction(
transactionName,
"CustomerSearchView",
"Search request"
);
🍃 Kotlin
val transactionName = "Customer Search"
GermainAPM.startTransaction(
transactionName,
"CustomerSearchView",
"Search request"
)
The view name and additional information are optional. Use them only when they add useful, non-sensitive context.
🛑 End a Transaction
End the transaction after the operation completes:
Java
GermainAPM.endTransaction(
transactionName
);
Kotlin
GermainAPM.endTransaction(
transactionName
)
The name supplied to endTransaction() must match the transaction started by startTransaction().
Every started transaction should have a corresponding end call. Otherwise, GermainUX cannot calculate its complete duration.
🔧 Monitor an Asynchronous Java Operation
Use try, catch, and finally so that the transaction ends whether the operation succeeds or fails.
private final ExecutorService executor =
Executors.newSingleThreadExecutor();
public void loadCustomerData() {
String transactionName = "Customer Data Load";
GermainAPM.startTransaction(
transactionName,
"CustomerView",
"Load customer data"
);
executor.execute(() -> {
try {
customerRepository.load();
} catch (IOException error) {
GermainAPM.collectException(
"CustomerDataLoadException",
error,
false
);
handleLoadFailure(error);
} finally {
GermainAPM.endTransaction(
transactionName
);
}
});
}
Do not use Android AsyncTask for new implementations because it is deprecated. Use the concurrency mechanism already approved for the application.
🎯 Monitor a Kotlin Coroutine
fun loadCustomerData() {
val transactionName = "Customer Data Load"
GermainAPM.startTransaction(
transactionName,
"CustomerView",
"Load customer data"
)
applicationScope.launch {
try {
customerRepository.load()
} catch (error: IOException) {
GermainAPM.collectException(
"CustomerDataLoadException",
error,
false
)
handleLoadFailure(error)
} finally {
GermainAPM.endTransaction(
transactionName
)
}
}
}
Start and end the transaction around the actual operation being measured. Starting too early can include unrelated user or scheduling time, while starting too late can exclude important preparation work.
🛰️ Monitor a Network Request
fun submitOrder() {
val transactionName = "Order Submission"
GermainAPM.startTransaction(
transactionName,
"CheckoutView",
"Submit order"
)
applicationScope.launch {
try {
val response = orderService.submitOrder()
if (!response.isSuccessful) {
GermainAPM.collectError(
"OrderSubmissionFailed",
"Order service returned an unsuccessful response."
)
}
} catch (error: IOException) {
GermainAPM.collectException(
"OrderSubmissionException",
error,
false
)
} finally {
GermainAPM.endTransaction(
transactionName
)
}
}
}
Do not include request bodies, authentication headers, payment information, or sensitive response content in the transaction details.
Report Transaction Failures
endTransaction() completes the duration measurement. When an operation fails, also report the failure using the appropriate API:
|
Failure type |
API |
|---|---|
|
Caught exception |
|
|
Failure without exception |
|
|
Unhandled exception |
Automatic crash collection |
Example:
try {
performSynchronization();
} catch (IOException error) {
GermainAPM.collectException(
"SynchronizationException",
error,
false
);
} finally {
GermainAPM.endTransaction(
"Data Synchronization"
);
}
Use GermainUX categorization and correlation to associate the error or exception with the transaction and user session.
🤝 Nested and Concurrent Transactions
Transactions may overlap when the application performs concurrent operations.
When adding instrumentation:
|
Guideline |
|---|
|
Give different operations distinct names. |
|
Avoid starting multiple simultaneous transactions with the same name unless the installed library explicitly supports it. |
|
End each transaction from the corresponding operation path. |
|
Do not use a shared mutable variable for unrelated concurrent transactions. |
|
Test nested and parallel execution before production deployment. |
If individual concurrent instances must be distinguished, use the correlation capabilities supported by the installed library rather than adding a unique value to the transaction name.
💼 Business-Process Transactions
Transactions can represent individual steps in a larger business process.
For example:
|
Business process |
Transactions |
|---|---|
|
Customer onboarding |
Validate identity, create account, load profile |
|
Field service |
Load work order, update status, upload evidence |
|
Checkout |
Validate cart, calculate payment, submit order |
|
Data synchronization |
Download data, process records, save locally |
|
Authentication |
Request login, validate response, load user context |
GermainUX can use these transactions with screens, events, sessions, and errors to analyze:
|
Analysis area |
|---|
|
End-to-end process duration |
|
Step duration |
|
Failures |
|
Abandonment |
|
Repeated steps |
|
Process overrun |
|
Lost productivity |
🏷️ Transaction Attributes
The basic startTransaction() call supports a transaction name, view name, and additional information.
Use additional information only for low-cardinality, non-sensitive context. Suitable examples include:
|
Attribute |
|---|
|
Operation type |
|
Cached or remote execution |
|
Record category |
|
Workflow step |
|
Feature variant |
Avoid:
|
Avoid |
|---|
|
User-entered text |
|
Names and email addresses |
|
Account or record numbers |
|
Authentication tokens |
|
Full URLs with query parameters |
|
Request or response payloads |
|
Unique values that create excessive cardinality |
📊 Analyze Transactions
In GermainUX, transactions can be analyzed by:
|
Dimension |
|---|
|
Transaction name |
|
Duration |
|
Count |
|
Average, median, and percentile |
|
Application version |
|
Android version |
|
Device model |
|
Screen or fragment |
|
User session |
|
Related error or exception |
|
Business process |
|
Success or failure context |
|
Release or environment |
Use percentiles and affected-user counts alongside averages. Averages can hide severe delays experienced by a subset of users.
🔔 Alerts
Configure alerts for conditions such as:
|
Condition |
|---|
|
Transaction duration above its SLA |
|
Increased transaction failures |
|
New exception associated with a critical transaction |
|
Significant performance regression after a release |
|
Missing expected transaction completions |
|
Increased business-process abandonment |
Use minimum-volume and sustained-duration conditions to reduce noise.
✅ Validation
After adding transaction monitoring:
-
Execute the operation successfully.
-
Confirm that the transaction appears in GermainUX.
-
Verify its name, view, duration, and session.
-
Force a controlled failure.
-
Confirm that the transaction still ends.
-
Verify that the related error or exception is captured.
-
Test cancellation and timeout paths.
-
Test concurrent executions.
-
Confirm that no sensitive details are collected.
-
Compare release-build behavior with the debug build.
-
Measure instrumentation overhead.
🐛 Troubleshooting
A transaction never completes
Verify that:
|
Check |
|---|
|
|
|
Failure, timeout, and cancellation paths use |
|
The application process did not terminate before the end call. |
|
The transaction name matches exactly. |
|
Async callbacks reach their completion handler. |
Transaction durations are too long
Check whether the transaction begins before unrelated work, user input, queue waiting, or background scheduling. Move the start point to the actual beginning of the operation if those delays are not part of the intended measurement.
Transaction durations are too short
Confirm that the transaction does not end before an asynchronous operation finishes. End it from the completion, failure, or cancellation path rather than immediately after starting the async request.
Transactions are combined incorrectly
Verify that:
|
Check |
|---|
|
Transaction names are stable but distinct by operation. |
|
Concurrent transactions do not use an unsupported shared name. |
|
Dynamic values have not been embedded in transaction names. |
|
The correct application and environment are assigned. |
Errors are not associated with transactions
Confirm that:
|
Check |
|---|
|
The error is reported before the transaction ends. |
|
Both events contain the same user-session context. |
|
GermainUX correlation and categorization rules are enabled. |
|
System clocks and timestamps are consistent. |
ℹ️ Get More Information
GermainUX can help determine which monitoring, analytics and automation capabilities are appropriate for your Android App environment.
Component: Engine, Mobile App
Feature Availability: 2022.1 or later