Transaction Monitoring for Android App

⚙️ 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

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:

Literal

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

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.

Java
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.

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

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:

  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:

Check

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:

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.

Contact GermainUX Support.

Component: Engine, Mobile App

Feature Availability: 2022.1 or later