Skip to content

Commit

Permalink
docs(android): improve android README
Browse files Browse the repository at this point in the history
- add troubleshooting section
- add details about sampling
- restructure the readme
- add "identify users" section
- add "performance tracing" section

closes #1723
  • Loading branch information
abhaysood committed Feb 6, 2025
1 parent 7d04778 commit 4b8369e
Show file tree
Hide file tree
Showing 2 changed files with 200 additions and 83 deletions.
255 changes: 192 additions & 63 deletions docs/android/README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,34 @@
# Measure Android SDK

* [Minimum requirements](#minimum-requirements)
* [Self host compatibility](#self-host-compatibility)
* [Quick reference](#quick-reference)
* [Getting started](#getting-started)
* [Custom events](#custom-events)
* [Handled exceptions](#handled-exceptions)
* [Screen view](#screen-view)
* [Requirements](#requirements)
* [Quick start](#quick-start)
* [Verify integration](#verify-integration)
* [Manually start/stop the SDK](#manually-start-or-stop-the-sdk)
* [Features](#features)
* [Performance Impact](#performance-impact)
* [Benchmarks](#benchmarks)
* [Profiling](#profiling)
* [Implementation](#implementation)
* [Automatic collection](#automatic-collection)
* [Identify users](#identify-users)
* [Track custom events](#track-custom-events)
* [Performance tracing](#performance-tracing)
* [Handled exceptions](#handled-exceptions)
* [Screen views](#screen-view)
* [Configuration options](#configuration-options)
* [Concepts](#concepts)
* [Sampling](#sampling)
* [Session](#session)
* [Performance impact](#performance-impact)

# Minimum requirements
# Requirements

### Minimum requirements

| Name | Version |
|-----------------------|---------------|
| Android Gradle Plugin | 7.4 |
| Min SDK | 21 (Lollipop) |
| Target SDK | 31 |

# Self-host compatibility

### Self-host compatibility

Before updating to Android SDK version 0.9.0, make sure the deployed self-host version is *atleast* 0.5.0. For more
details, checkout the [self-host guide](../hosting/README.md).
Expand All @@ -30,14 +37,9 @@ details, checkout the [self-host guide](../hosting/README.md).
|---------------|------------------------------------|
| 0.1.0 - 0.8.2 | 0.1.1 |
| 0.9.0 | 0.5.0 |

# Quick reference

A quick reference to the entire public API for Measure Android SDK.

![Cheatsheet](images/cheatsheet_v0.9.0.png)

# Getting started
# Quick start

Once you have access to the dashboard, create a new app and follow the steps below:

Expand Down Expand Up @@ -188,21 +190,61 @@ Add the following to your app's Application class `onCreate` method.
> initialize the SDK as soon as possible in Application `onCreate` method.
```kotlin
Measure.init(context)
Measure.init(context, MeasureConfig(
// Set to 1 to track all sessions, useful for debug builds.
samplingRateForErrorFreeSessions = 1f,
)
)
```

If you wish to configure the SDK during initialization with a custom config use the overloaded function:
# Verify integration

Launch the app and use it. Data is synced to server every 30 seconds or when the app goes to background. To be sure a sync is triggered, try killing and reopening the app.

Launch the dashboard, you must be able to see some data coming in. Checkout the sessions page.

🎉 Congratulations, you have successfully integrated Measure into your app!

### Troubleshoot

If you see no data on the dashboard. Here's how to investigate:

#### Enable logs

Enable logging during SDK initialization. All Meaure SDK logs use the tag `Measure`.

```kotlin
Measure.init(
context, MeasureConfig(
// override the default configuration here
)
)
MeasureConfig(enableLogging = true)
```

By default, init also starts collection of events. To delay start to a different point in your app
use [configuration options](configuration-options.md#autostart).
#### Verify missing configuration

If logs show any of the following errors, then review [Step 1: Add API Key & URL](#1-add-the-api-key--api-url).
```
sh.measure.android.API_URL is missing in the manifest
sh.measure.android.API_KEY is missing in the manifest
```

#### Verify sampling rate

Try setting `samplingRateForErrorFreeSessions` to 1, which would enforce all sessions to be
sent to the server. It's typically a good idea to set this to `1` for debug builds.


#### Verify server connection

If logs contain `Failed to send batch` or `Request failed with unknown error`:
* Verify the API_URL in the AndroidManifest is correct
* Check server status to ensure it is reachable


In case you face any issue, feel free to reach out to us on [Discord](https://discord.gg/f6zGkBCt42).


# Manually start or stop the SDK

By default, `Measure.init` starts collection of events. To delay start to a different point in your app
use [configuration options](configuration-options.md#autostart). This can be used to control the scope of where Measure is active in your application.

```kotlin
Measure.init(
Expand All @@ -219,25 +261,49 @@ Measure.start()
Measure.stop()
```

See all the [configuration options](configuration-options.md) available.
> [!IMPORTANT]
> Some SDK instrumentation remains active even when stopped. This is to maintain state and ensure seamless data collection when it is started. However, no actual data is collected or sent to the server when the SDK is stopped.
### 5. Verify
# Features

Measure SDK operates on an event-based architecture, automatically collecting key debugging events while letting you track custom events, performance traces, screenshots and layout snapshots, etc. Read along for more details.

### Automatic collection

The SDK automatically collects data when a crash occurs. You can verify if the SDK is working by triggering a crash
after the SDK is initialized:
The following data is automatically collected by Measure. Read the individual docs for more details.

* [Crash tracking](features/feature_crash_tracking.md)
* [ANR tracking](features/feature_anr_tracking.md)
* [Network monitoring](features/feature_network_monitoring.md)
* [Network changes](features/feature_network_changes.md)
* [Gesture tracking](features/feature_gesture_tracking.md)
* [Layout Snapshots](features/feature_layout_snapshots.md)
* [Navigation & Lifecycle](features/feature_navigation_and_lifecycle.md)
* [App launch](features/feature_app_launch.md)
* [App exit info](features/feature_app_exit_info.md)
* [CPU monitoring](features/feature_cpu_monitoring.md)
* [Memory monitoring](features/feature_memory_monitoring.md)
* [App size](features/feature_app_size.md)

## Identify users
Corelating sessions with users is crutial for debugging certain issues. Measure allows setting a user ID which can then be used to query sessions and events on the dashboard. User Id is persisted across app
launches.

```kotlin
throw RuntimeException("This is a test crash")
Measure.setUserId("user-id")
```

Reopen the app and launch the dashboard, you should see the crash report in the dashboard.
To clear a user ID.
```kotlin
Measure.clearUserId()
```

> [!CAUTION]
> Make sure to remove the test crash code before releasing the app to production.
> It is recommended to avoid the use of PII (Personally Identifiable Information) in the
user ID like email, phone number or any other sensitive information. Instead, use a hashed
or anonymized user ID to protect user privacy.

🎉 Congratulations, you have successfully integrated Measure into your app!

# Custom events
## Track custom events

Custom events provide more context on top of automatically collected events. They provide the context
specific to the app to debug issues and analyze impact.
Expand Down Expand Up @@ -269,16 +335,73 @@ since epoch.
Measure.trackEvent("event_name", timestamp = 1734443973879L)
```

Apart from sending a custom event, the following events can be tracked with a predefined scehama:
### Performance tracing

Use the [performance tracing](features/feature_performance_tracing.md) APIs to track performance of any part of your application - API calls,

DB queries, any function, user journey, etc.
The SDK supports nested spans to track hierarchical operations. Following are some *simplified* examples:

Example - track a user flow

```kotlin
val onboardingSpan = Measure.startSpan("onboarding-flow")
try {
val signupSpan = Measure.startSpan("signup", parent = onboardingSpan)
userSignup()
signupSpan.end()

val tutorialSpan = Measure.startSpan("tutorial", parent = onboardingSpan)
showTutorial()
tutorialSpan.end(SpanStatus.Ok)
} finally {
onboardingSpan.end(SpanStatus.Error)
}
```

This will result in a trace like the following:

```
onboarding-flow ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [2.4s] ✓
┣━ signup ━━━━━━━━━ [800ms]
┗━ tutorial ━━━━━━━━━━━━━━━━ [1.6s]
```

Example - track HTTP calls using an interceptor

* [Handled exceptions](#handled-exceptions)
* [ScreenView](#screen-view)
```kotlin
class HttpInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val span = Measure.startSpan("${request.method} /${request.url.redact()}")

return try {
val response = chain.proceed(request)
span.end(SpanStatus.SUCCESS)
response
} catch (e: Exception) {
span.end(SpanStatus.ERROR)
throw e
}
}
}
```

This will result in a trace like the following:

```
GET /orders ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [2.4s] ✗
```

For more detailed API documentation and examples, checkout [performance tracing docs](features/feature_performance_tracing.md).


### Handled exceptions

To track exceptions which were caught and handled by the app, use the `trackHandledException`
method.
method. While your app gracefully recovers from these exceptions, tracking them helps identify potential degraded app experience.

```kotlin
try {
Expand All @@ -305,24 +428,36 @@ a track of the user flow.
Measure.trackScreenView("checkout")
```

# Features
# Configuration options

All the features supported by the Measure SDK are listed below.
See all the [configuration options](configuration-options.md) available.

* [Crash tracking](features/feature_crash_tracking.md)
* [ANR tracking](features/feature_anr_tracking.md)
* [Network monitoring](features/feature_network_monitoring.md)
* [Network changes](features/feature_network_changes.md)
* [Gesture tracking](features/feature_gesture_tracking.md)
* [Layout Snapshots](features/feature_layout_snapshots.md)
* [Navigation & Lifecycle](features/feature_navigation_and_lifecycle.md)
* [App launch](features/feature_app_launch.md)
* [App exit info](features/feature_app_exit_info.md)
* [CPU monitoring](features/feature_cpu_monitoring.md)
* [Memory monitoring](features/feature_memory_monitoring.md)
* [App size](features/feature_app_size.md)
# Concepts

# Session
## Sampling

Sampling controls what percentage of data is collected and sent to the server, helping balance data quality with system performance and storage costs.

#### Session Sampling

Set [samplingRateForErrorFreeSessions](configuration-options.md#samplingrateforerrorfreesessions) to control event collection from sessions without errors. By default, the SDK sends all events from crashed sessions to the server, while collecting no events from error-free sessions.

* 0.0 — No events from error-free sessions (default)
* 0.1 — 10% of error-free sessions
* 1.0 — All sessions

Session sampling helps optimize data collection for crash and error analysis.

#### Trace Sampling

[traceSamplingRate](configuration-options.md#tracesamplingrate) controls performance trace collection independently of session sampling. While session sampling determines which session-level events are sent, trace sampling specifically controls performance monitoring data.

This separation ensures:
- Performance traces are collected based on their own sampling rate.
- Critical performance data is captured regardless of session errors.
- Session data remains focused on crash analysis and debugging.

## Session

A session represents a continuous period of activity in the app. A new session begins when an app is launched for the first time,
or when there's been no activity for a 20-minute period. A single session can continue across multiple app background and
Expand All @@ -335,7 +470,6 @@ The current session can be retrived by using `getSessionId` method.
val sessionId = Measure.getSessionId()
```


# Performance Impact

## Benchmarks
Expand Down Expand Up @@ -366,8 +500,3 @@ or by using [Perfetto](https://perfetto.dev/docs/quickstart/android-tracing) dir
thread.
* `msr-trackGesture` — time spent on the main thread to track a gesture.
* `msr-generateSvgAttachment` — time spent on background thread to generate a SVG layout.

## Implementation

For details on data storage, syncing behavior, and threading, see
our [Internal Documentation](../../android/docs/internal-documentation.md).
28 changes: 8 additions & 20 deletions docs/android/configuration-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Measure.init(
* [**httpHeadersBlocklist**](#httpHeadersBlocklist)
* [**trackHttpBody**](#trackHttpBody)
* [**trackActivityIntentData**](#trackActivityIntentData)
* [**sessionSamplingRate**](#sessionSamplingRate)
* [**samplingRateForErrorFreeSessions**](#samplingRateForErrorFreeSessions)
* [**enableLogging**](#enableLogging)
* [**eventTrackingLevel**](#eventTrackingLevel)
* [**traceSamplingRate**](#traceSamplingRate)
Expand Down Expand Up @@ -170,18 +170,16 @@ checking what data was passed as part of the bundle, it might also contain sensi

Disabled by default.

## `sessionSamplingRate`

Measure SDK by default collects events for crashed sessions only. However, in case you want to collect
events at a sampled rate for non-crashed sessions, use `sessionSamplingRate.
## `samplingRateForErrorFreeSessions`

Defaults to 0.0, meaning no events for non-crashed sessions are exported by default.
Controls sampling rate for non-crashed sessions. Defaults to 0.

The sampling rate is a value between 0 and 1. For example, a value of `0.1` will export only 10%
of the non-crashed sessions, a value of `0` will disable exporting of non-crashed sessions.
A value between 0.0 and 1.0 can be set:
* 0.0 (default): Only collect crashed sessions
* 0.1: Collect 10% of non-crashed sessions
* 1.0: Collect all sessions

Note that events for crashed sessions are always exported. And certain events like `cold_launch`, `warm_launch`,
`hot_launch`, `lifecycle_activity`, `lifecycle_fragment` are always exported regardless of the sampling rate.
Note that all crashed sessions are collected regardless of this setting.

## `traceSamplingRate`

Expand All @@ -196,16 +194,6 @@ of the traces, a value of `0` will disable exporting of traces completely.
Allows enabling/disabling internal logging of Measure SDK. This is useful to debug issues with the SDK
itself. By default, logging is disabled.

## `samplingRateForErrorFreeSessions`

By default, sessions with errors (crashes and ANRs) are reported. Sessions without
errors can also be reported with a sampling rate.

Defaults to 0.0, meaning no error-free sessions are reported by default.

The sampling rate is a value between 0 and 1. For example, a value of `0.1` will report only 10%
of the error-free sessions, a value of `0` will disable reporting of error-free sessions.

## `autoStart`

Controls whether to start tracking immediately or delay starting the SDK.
Expand Down

0 comments on commit 4b8369e

Please sign in to comment.