Skip to content

Add API to extend app start (Android) #5553

Description

@buenaflor

Add an API to the Sentry Android SDK to extend the app start measurement past its default end point and instrument the extended region with child spans.

// Simple: extend the app start window, then finish
Sentry.extendAppStart()
initializeRemoteConfig()
Sentry.finishExtendedAppStart()
// With child spans: instrument the extended region
Sentry.extendAppStart()
val span = Sentry.getExtendedAppStartSpan()

val configSpan = span.startChild("app.init", "fetch remote config")
fetchRemoteConfig()
configSpan.finish()

Sentry.finishExtendedAppStart()

Reference: getsentry/sentry-cocoa#6886 (Done, SentryExtendedAppLaunchManager). Siblings: getsentry/sentry-dart#3767, getsentry/sentry-react-native#6303 — shared contract, per-platform deltas below.

API

  • extendAppStart(): void — creates the extended app start span (op app.start.extended, description "Extended App Start").
  • finishExtendedAppStart — finishes it (returns void); triggers finalization.
  • getExtendedAppStartSpan(): ISpan — returns the span for attaching children; a no-op span when there's no active extension.

finishExtendedAppStart is equivalent to calling .finish() on the returned span.

Lifecycle

  • extendAppStart: creates the span (start = call time). No-ops if app start already finished, if none is in progress, or on repeat calls (first wins).
  • getExtendedAppStartSpan: returns the extended span, else a no-op span.
  • finishExtendedAppStart: no-ops if not extended or called twice. Doesn't finalize directly — the parent (auto-generated, waitForChildren) finalizes when its last child finishes and trims its end to that child. Open children of the extended span are finished cancelled at the finish-call time.

Duration & measurement

  • Parent duration = end of the last child to finish (trim-to-last-child), floored at the default app start end — i.e. end = max(last child end, default app start end). Extending can only push the end later; finishing before the default end keeps the default (never shorter than a non-extended app start). The extended span is just one participant.
  • App start measurement = that final duration (process start → last child), set at finalization. The normal completion-time measurement must be suppressed in extended mode so the early (non-extended) value doesn't win.

Timeout

  • Parent's auto-finish deadline is 30s. If finishExtendedAppStart is never called, the transaction auto-finishes on the deadline (unfinished children → deadlineExceeded, snapped to transaction end), is still captured, but the app.vitals.start measurement is suppressed — never emit a ~30s app start. Same for standalone and ui.load.

Standalone & non-standalone

  • Both supported, same mechanism: standalone uses the app-start tracer, non-standalone the ui.load transaction (also waitForChildren + deadline). In non-standalone the duration is bounded by anything keeping ui.load open (TTID, other children), so it can include spans unrelated to the extension.

Android delta

Acceptance criteria

  • extendAppStart() creates the span before finish; no-ops when too late, not started, or called repeatedly.
  • getExtendedAppStartSpan() returns the span, else a no-op span (including after finish).
  • Child spans render under Extended App Start.
  • finishExtendedAppStart no-ops if not extended or called twice; finalizes via waitForChildren with transaction end = last child.
  • Exactly one App Start transaction across all paths.
  • Measurement = process start → last child, floored at the default app start end (never shorter than a non-extended app start), set at finalization.
  • Open children at finish → cancelled; on deadline → deadlineExceeded, snapped to end.
  • Deadline path: transaction captured, app.vitals.start suppressed.
  • Extended app starts carry a segmentation attribute, and inherit app_start_type metadata.
  • Docs updated.

Metadata

Metadata

Assignees

No one assigned
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions