Measure logo

SDK API Reference

Public API reference for the Measure SDK, with per-platform code examples for Android, iOS, Flutter, React Native and Kotlin Multiplatform.

Initialize the SDK

Initialize the SDK with init before calling any other method. Call it as early as possible in app startup so crashes, errors and events are captured from the beginning.

import sh.measure.android.Measure
import sh.measure.android.config.MeasureConfig

Measure.init(this, MeasureConfig())

SDK configuration options

Pass a config object to init to customize the SDK. The available options differ by platform.

OptionTypeDefaultDescription
enableLoggingBooleanfalseTurn on internal SDK logs.
autoStartBooleantrueStart tracking automatically on init. Set to false to delay starting collection.
maxDiskUsageInMbInt50Cap the disk space used for buffered data. Clamped between 20MB and 1500MB.
trackActivityIntentDataBooleanfalseCapture the intent data used to launch an Activity.
requestHeadersProviderMsrRequestHeadersProvider?nullAdd custom HTTP headers to requests the SDK sends to the Measure API, useful for self-hosted setups.
enableFullCollectionModeBooleanfalseOverride all sampling and collect every event and trace. Increases cost, so use it for debugging only.
enableDiagnosticModeBooleanfalseWrite all SDK logs to a file you can attach when reporting an SDK bug.

Start tracking

The SDK starts collecting data automatically after init. If you set autoStart to false in the config, call start when you're ready to begin tracking.

import sh.measure.android.Measure

Measure.start()

Stop tracking

Pause data collection with stop. While stopped, the SDK collects no data. Call start to resume.

import sh.measure.android.Measure

Measure.stop()

Track errors

You can report errors you catch and recover from. These don't crash the app but often point to problems worth fixing. Crashes and ANRs are captured automatically, so you don't need to track those yourself.

Track a handled error

import sh.measure.android.Measure

try {
    methodThatThrows()
} catch (e: Exception) {
    Measure.trackHandledException(e)
}

Add attributes

See Attribute limits for allowed keys and values.

import sh.measure.android.Measure
import sh.measure.android.attributes.AttributesBuilder

val attributes = AttributesBuilder().put("screen", "Login").build()
Measure.trackHandledException(e, attributes)

Track custom events

Track app-specific events like user actions or feature usage with trackEvent.

  • Event names can be up to 64 characters.
  • Event names can contain only letters, numbers, hyphens and underscores.

Track an event

import sh.measure.android.Measure

Measure.trackEvent("event_name")

Set a custom timestamp

Record an event at a specific time, in milliseconds since epoch. Use getCurrentTime for an accurate monotonic value.

import sh.measure.android.Measure

Measure.trackEvent("event_name", timestamp = Measure.getCurrentTime())

Add attributes

See Attribute limits for allowed keys and values.

import sh.measure.android.Measure
import sh.measure.android.attributes.AttributesBuilder

val attributes = AttributesBuilder().put("is_premium_user", true).build()
Measure.trackEvent("event_name", attributes = attributes)

Track screen views

The SDK automatically tracks screen views from each platform's navigation system. Record a screen from a custom navigation setup with trackScreenView.

Track a screen view

import sh.measure.android.Measure

Measure.trackScreenView("Home")

Add attributes

See Attribute limits for allowed keys and values.

import sh.measure.android.Measure
import sh.measure.android.attributes.AttributesBuilder

val attributes = AttributesBuilder().put("source", "deep_link").build()
Measure.trackScreenView("Home", attributes)

Automatic tracking on Flutter

Add MsrNavigatorObserver to your app's navigatorObservers to track screen views automatically. It works best with named routes.

import 'package:flutter/material.dart';
import 'package:measure_flutter/measure_flutter.dart';

MaterialApp(
  navigatorObservers: [MsrNavigatorObserver()],
  home: HomeScreen(),
);

Track performance traces

Measure how long any operation takes with a span. A span represents one unit of work. Set a parent to trace a multi-step flow.

  • Span names can be up to 64 characters.
  • Span names cannot be empty.

Start a span

Start a span immediately with startSpan.

import sh.measure.android.Measure

val span = Measure.startSpan("span-name")

Start with a timestamp

Trace an operation that already started by passing a start time from getCurrentTime, which returns epoch time from a monotonic clock.

import sh.measure.android.Measure

val span = Measure.startSpan("span-name", timestamp = Measure.getCurrentTime())

End a span

End a span with end. Set the status before ending.

import sh.measure.android.Measure
import sh.measure.android.tracing.SpanStatus

val span = Measure.startSpan("span-name")
span.setStatus(SpanStatus.Ok).end()

End with a timestamp

End a span that already finished by passing an end time from getCurrentTime.

import sh.measure.android.Measure
import sh.measure.android.tracing.SpanStatus

val span = Measure.startSpan("span-name")
span.setStatus(SpanStatus.Ok).end(timestamp = Measure.getCurrentTime())

Set the status

Set the outcome of the operation with setStatus. Values are Ok, Error and Unset (the default).

import sh.measure.android.Measure
import sh.measure.android.tracing.SpanStatus

val span = Measure.startSpan("span-name")
span.setStatus(SpanStatus.Ok)

Set a parent

Build a hierarchy of operations by setting a parent span with setParent.

import sh.measure.android.Measure

val parent = Measure.startSpan("parent-span")
val child = Measure.startSpan("child-span").setParent(parent)

Add attributes

Attach key-value context to a span. Add one attribute at a time, several at once with setAttributes, or remove one with removeAttribute. See Attribute limits for allowed keys and values.

import sh.measure.android.Measure
import sh.measure.android.attributes.AttributesBuilder

val span = Measure.startSpan("span-name")
span.setAttribute("key", "value")
span.setAttribute("count", 10)

val attributes = AttributesBuilder().put("key", "value").put("count", 10).build()
span.setAttributes(attributes)

span.removeAttribute("key")

Rename a span

Update a span's name after it starts with setName.

import sh.measure.android.Measure

val span = Measure.startSpan("span-name")
span.setName("updated-name")

Add a checkpoint

Mark a significant moment during a span with setCheckpoint. A span can hold up to 100 checkpoints.

import sh.measure.android.Measure

val span = Measure.startSpan("span-name")
span.setCheckpoint("checkpoint-name")

Defer a span

Configure a span now and start it later with createSpanBuilder.

import sh.measure.android.Measure

val builder = Measure.createSpanBuilder("span-name")
val span = builder?.startSpan()

Distributed tracing

Propagate a trace across services by adding the W3C traceparent header to outgoing requests. Get the header key with getTraceParentHeaderKey and its value for a span with getTraceParentHeaderValue.

import sh.measure.android.Measure

val span = Measure.startSpan("http")
val key = Measure.getTraceParentHeaderKey()
val value = Measure.getTraceParentHeaderValue(span)

Track HTTP events

Measure automatically tracks OkHttp on Android and, with the measure_dio package, Dio on Flutter. Use trackHttpEvent to record requests from any other HTTP client. Use getCurrentTime for the start and end time to avoid clock skew.

import sh.measure.android.Measure

val startTime = Measure.getCurrentTime()
// make the request
val endTime = Measure.getCurrentTime()

Measure.trackHttpEvent(
    url = "https://api.example.com/users",
    method = "GET",
    startTime = startTime,
    endTime = endTime,
    statusCode = 200,
)

Track bug reports

Let users report bugs from inside the app. Open the bug report UI with a single call, or submit a report from your own UI with trackBugReport. Descriptions can be up to 4000 characters, with a maximum of 5 attachments. Attach a screenshot with captureScreenshot, and trigger reports on device shake.

Open bug report screen

import sh.measure.android.Measure

Measure.launchBugReportActivity(takeScreenshot = true)

Track a bug report

Build a custom bug report flow and submit it with trackBugReport.

import sh.measure.android.Measure

Measure.trackBugReport(description = "Cart items disappear after reopening the app")

Add attributes

Attach metadata to a report. Pass attributes when you open the bug report UI or track a report from your own UI. See Attribute limits for allowed keys and values.

import sh.measure.android.Measure
import sh.measure.android.attributes.AttributesBuilder

val attributes = AttributesBuilder().put("screen", "Cart").build()

Measure.launchBugReportActivity(takeScreenshot = true, attributes = attributes)
Measure.trackBugReport(description = "...", attributes = attributes)

Shake to report

Register a shake handler so users can open a bug report by shaking their device. Pass a null handler to disable it.

import sh.measure.android.Measure
import sh.measure.android.bugreport.MsrShakeListener

Measure.setShakeListener(object : MsrShakeListener {
    override fun onShake() {
        Measure.launchBugReportActivity()
    }
})

Track logs

Record a log at one of five severity levels, using logDebug, logInfo, logWarning, logError or logFatal. Logs appear in the session replay and add context when debugging. Bodies longer than 1000 characters are truncated.

Track a log

import sh.measure.android.Measure

Measure.logDebug("Cache miss for key user_42")
Measure.logInfo("User signed in")
Measure.logWarning("Payment failed, retrying")
Measure.logError("Checkout request failed")
Measure.logFatal("Unrecoverable database error")

Add attributes

See Attribute limits for allowed keys and values.

import sh.measure.android.Measure
import sh.measure.android.attributes.AttributesBuilder

val attributes = AttributesBuilder().put("screen", "Checkout").build()
Measure.logWarning("Payment failed", attributes)

Identify users

Set a user ID to correlate sessions with a user when debugging. The ID persists across app launches. Clear it when the user logs out.

Avoid personally identifiable information (PII) like email or phone number in the user ID. Use a hashed or anonymized value instead.

import sh.measure.android.Measure

Measure.setUserId("user-id")
Measure.clearUserId()

Get session ID

Read the current session ID to correlate app data with a Measure session. Returns null if the SDK isn't initialized.

import sh.measure.android.Measure

val sessionId: String? = Measure.getSessionId()

Get current time

Read epoch time in milliseconds from a monotonic clock. Use it for event, span and HTTP timestamps to avoid clock skew.

import sh.measure.android.Measure

val currentTime: Long = Measure.getCurrentTime()

Mask SwiftUI views

Screenshots mask all SwiftUI content by default, whatever the mask level, because SwiftUI views can't be inspected individually. Reveal a view that isn't sensitive with .msrUnmask(), or force masking with .msrMask() for a view automatic detection misses, like a standalone Text outside a List.

import Measure

VStack {
    Text("Order confirmed")
        .msrUnmask()
    Text(cardNumber)
        .msrMask()
}

Mask Flutter widgets

Screenshots mask Flutter text, input and image widgets automatically based on the mask level, and a TextField with obscureText or a password, email or phone keyboard type is always masked. Wrap anything automatic detection misses, like a custom-painted widget showing sensitive data, with MsrMask to always redact its area regardless of the mask level.

import 'package:measure_flutter/measure_flutter.dart';

MsrMask(
  child: AccountBalance(amount: balance),
)

Attribute limits

Attributes are the key-value pairs you attach to events, spans, logs, bug reports, screen views and errors. They follow the same rules everywhere:

  • Keys are strings, up to 256 characters.
  • Keys can contain only letters, numbers, hyphens and underscores.
  • Values are a string, integer, long, double, float or boolean. On React Native, values are a string, number or boolean.
  • String values can be up to 256 characters.

Think this page can be better?

Open an issue