> ## Documentation Index
> Fetch the complete documentation index at: https://docs.germainux.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Transaction Monitoring for Android App

> GermainUX transactions measure the duration and outcome context of important operations performed by an Android application.

Components
[`Engine`](https://docs.germainux.com/main/germain-ux-engine)
[`Mobile App`](https://docs.germainux.com/main/germain-ux-mobile-app)
[`RUM JS`](https://docs.germainux.com/main/germain-ux-rum-js)

Availability
2022.1 or later

> [card] [Transaction Design](#transaction-design)
>
> Choose stable transaction names

> [card] [Monitor a Network Request](#monitor-a-network-request)
>
> Kotlin example for transactions

> [card] [Transaction Attributes](#transaction-attributes)
>
> Safe low-cardinality context fields

> [card] [Troubleshooting](#troubleshooting)
>
> Fix missing transaction data

## 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:

* Application startup
* User interaction
* Network request
* Data synchronization
* Local database operation
* File processing

> [accordion] Show all 12
>
> * 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 | `GermainAPM.startTransaction()` |
| when it completes | `GermainAPM.endTransaction()` |

## 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:

* `Customer Search`
* `Order Submission`
* `Data Synchronization`
* `Image Download`
* `Authentication`

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

```text theme={null}
String transactionName = "Customer Search";

GermainAPM.startTransaction(
    transactionName,
    "CustomerSearchView",
    "Search request"
);
```

### Kotlin

```text theme={null}
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

```text theme={null}
GermainAPM.endTransaction(
    transactionName
);
```

### Kotlin

```text theme={null}
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.

```java theme={null}
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

```text theme={null}
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

```text theme={null}
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 | `GermainAPM.collectException()` |
| Failure without exception | `GermainAPM.collectError()` |
| Unhandled exception | **Automatic crash collection** |

Example:

```text theme={null}
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:

* 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:

* 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:

* Operation type
* Cached or remote execution
* Record category
* Workflow step
* Feature variant

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:

* Transaction name
* Duration
* Count
* Average, median, and percentile
* Application version
* Android version

> [accordion] Show all 13
>
> * 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:

* 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:

**1. Execute the operation successfully**

**2. Confirm that the transaction appears in GermainUX**

**3. Verify its name, view, duration, and session**

**4. Force a controlled failure**

**5. Confirm that the transaction still ends**

**6. Verify that the related error or exception is captured**

**7. Test cancellation and timeout paths**

**8. Test concurrent executions**

**9. Confirm that no sensitive details are collected**

**10. Compare release-build behavior with the debug build**

**11. Measure instrumentation overhead**

## Troubleshooting

### A transaction never completes

Verify that:

* `endTransaction()` executes on every path.
* Failure, timeout, and cancellation paths use `finally`.
* 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:

* 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:

* 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 Help

> [card] [Contact GermainUX Support](https://docs.germainux.com/main/support.md)
>
> The GermainUX team helps you get up and running faster, empower your team, turn data into actionable insights, and optimize performance to deliver measurable business outcomes.

> [card] Can't find what you need?
>
> Search all GermainUX docs with **Ctrl + K**, or use the feedback buttons at the bottom of this page to tell us what is missing.

The content of this document is proprietary to GERMAIN SOFTWARE.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.