Skip to content

app.start.cold / app.start.warm → allow nesting; or make it be controlled somehow #5936

Closed

Description

@alwx

Currently, app.start.cold / app.start.warm is a flat child span of the root transaction. Native sub-spans (UIKit init, etc.) and JS Bundle Execution are children of it, but there's no way for user code to add custom child spans to the app start span.

Allowing nesting / control would be useful for:

  1. Granular app start breakdown — Users could instrument their own initialization phases as child spans of app.start.cold:
    • app.start.cold > fetch_remote_config
    • app.start.cold > hydrate_cache
    • app.start.cold > auth_token_refresh
    • app.start.cold > initialize_feature_flags
      This gives real visibility into what's slow during cold start, not just the total duration.
  2. Custom "control" of the app start span — If app.start.cold were exposed as an active span that users can reference, they could:
    • Add attributes/tags to it (e.g., app_version, launch_source)
    • Set custom start/end times
    • Decide when it actually ends (ties into idea 1)
  3. Framework-level instrumentation — Libraries like Redux, React Navigation, Apollo Client, or Expo modules could automatically create child spans of app start, giving SDK users out-of-the-box breakdowns without manual work.
  4. Matching native SDK capabilities — Android and iOS native Sentry SDKs already provide richer app start span trees with nested native phases. Allowing the RN layer to nest its own spans would create a unified, end-to-end app start waterfall from native init → JS bundle → React render → app ready.

Activity

  1. linear-code commented on Mar 31, 2026

    @linear-code
  2. romtsn commented on Apr 17, 2026

    @romtsn
    Contributor

    See iOS/Android issues for more details around the new API. I think we can repurpose this issue to implement that API first, which will make it possible to customize the app start span as you see fit, e.g.:

    // Must be called before the first frame is drawn
    const launchSpan = Sentry.extendAppLaunch();
    
    // 1. Granular breakdown — attach child spans to app.start.cold
    const configSpan = launchSpan?.startChild({ name: "fetch_remote_config", op: "app.init" });
    await fetchRemoteConfig();
    configSpan?.finish();
    
    const cacheSpan = launchSpan?.startChild({ name: "hydrate_cache", op: "app.init" });
    await hydrateCache();
    cacheSpan?.finish();
    
    const authSpan = launchSpan?.startChild({ name: "auth_token_refresh", op: "app.init" });
    await refreshAuthToken();
    authSpan?.finish();
    
    const flagsSpan = launchSpan?.startChild({ name: "initialize_feature_flags", op: "app.init" });
    await initFeatureFlags();
    flagsSpan?.finish();
    
    // 2. Custom attributes on the app start span itself
    launchSpan?.setAttribute("app_version", "1.4.2");
    launchSpan?.setAttribute("launch_source", "push_notification");
    
    // 3. Framework-level instrumentation (e.g. inside Redux enhancer)
    const reduxSpan = launchSpan?.startChild({ name: "redux_store_init", op: "app.init.redux" });
    const store = configureStore({ reducer });
    reduxSpan?.finish();
    
    // Mark the app as launched (or let it default to firstFrameDrawn)
    launchSpan?.finish();
    
    // Optional: separately mark full display (e.g. after data is rendered)
    launchSpan?.fullyDisplayed();
  3. self-assigned this
    on Jun 26, 2026
  4. github-actions commented on Jul 9, 2026

    @github-actions
    Contributor

    A PR closing this issue has just been released 🚀

    This issue was referenced by PR #6392, which was included in the 8.18.0 release.

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

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions