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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions