Skip to content

feat(sentry): report active runs, actions and apps as gauges (umbrella) #8235

Open

Description

@pingsutw

Why

Flyte 2 reports anonymous usage to Sentry so we can see how OSS deployments are used (flytestdlib/sentryutils, opt out with FLYTE_DISABLE_SENTRY=true). Today that is counters only: create_run, deploy_task, deploy_trigger (#7672, #7855) and deploy_app (#7855). Counters tell us how often something was created, but not how much is live right now. We cannot answer "how many runs are executing across OSS clusters at this moment", "how many actions are in flight", or "how many apps are serving traffic".

This umbrella tracks adding gauges for the live state of a deployment. Each bullet is a self-contained change; file or pick up one at a time and link it here.

What to change

All three ride on the existing Sentry plumbing. sentry-go v0.49 already exposes Meter.Gauge(name, value, opts...) next to the Count we use, so the work is: add a sentryutils.Gauge(ctx, name, value) helper, then in each service register a background worker (SetupContext.AddWorker, same place the *-sentry-flush workers live) that samples the live count on an interval (60s is fine) and emits it.

  • flytestdlib/sentryutils/sentryutils.go — add Gauge(ctx, name string, value float64) mirroring Count. Each gauge is its own metric name (flyte.active_runs, flyte.active_actions, flyte.active_apps), no attributes. Keep the Disabled() / Init gate so a disabled process is a no-op.
  • Actions repo count (runs/repository/impl/action.go, runs/repository/interfaces/action.go) — add one method, e.g. CountActionsByPhase(ctx) (map[int32]int64, error) returning SELECT phase, parent_action_name IS NULL AS is_root, COUNT(*) ... GROUP BY 1, 2. idx_actions_phase (runs/migrations/sql/20260408110000_init_schema.sql) already exists, so this is an index-only aggregate, no scan. Both gauges below read from this one query so a single sampler tick costs one round trip.
  • Active runs (runs/setup.go) — gauge flyte.active_runs: rows from the count above where is_root and phase is not terminal. The terminal set is already spelled out in runs/repository/impl/action.go (terminalPhases, ~L541); reuse it rather than redefining.
  • Active actions (runs/setup.go) — gauge flyte.active_actions: same count, all rows with a non-terminal phase (root and child). The DB is the source of truth here: it covers every action the runs service knows about, including ones queued before the executor has created a TaskAction CRD. The executor's taskaction.active{phase} OTel observable (executor/pkg/controller/metrics.go) stays as the cluster-side view; do not report it to Sentry as well or the two numbers will disagree during queueing.
  • Apps running (app/setup.go) — gauge flyte.active_apps: count of apps whose status substate is RUNNING (flyteidl2.app.Status.Substate, app/internal/k8s). Sample from the app service's existing view of app status rather than a fresh K8s list per tick.

Design notes for whoever picks these up:

  • No attributes. These are process-wide totals, one metric name each; the operation attribute is only for the flyte.operation counter. Do not attach project/domain/run names; the point of this telemetry is aggregate counts, not per-tenant data.
  • Sampling, not events: one gauge emission per interval per process. Do not emit on every state transition.
  • Keep it off the request path. Workers only; no interceptor changes.

Outcome

  • A fresh OSS deployment with Sentry enabled reports the flyte.active_runs, flyte.active_actions and flyte.active_apps gauges within one sampling interval of startup.
  • Setting FLYTE_DISABLE_SENTRY=true produces no gauge traffic and no background worker.
  • Each sampler has a unit test covering the non-terminal filter (runs/actions) or the RUNNING substate filter (apps).
  • The sampler's cost is bounded: a COUNT(*) with an indexed phase filter or an in-memory cache read, not a full table scan or K8s list per tick.

Getting started

  • Read first: flytestdlib/sentryutils/sentryutils.go (the whole package is ~100 lines), then how runs/setup.go and app/setup.go wire sentryutils.Init + AddWorker.
  • Prior art for a phase-bucketed gauge: executor/pkg/controller/metrics.go (taskaction.active).
  • Verify locally: make devbox-run, run a workflow, and check the Sentry project for the flyte.active_* gauges. Or point sentry.Init at a local DSN via sentry-cli if you do not have access to the shared project.
  • Tests: go test ./flytestdlib/sentryutils/... ./runs/... ./app/...
  • Setup: CONTRIBUTING.md

Activity

  1. runllm commented on Oct 23, 2026

    @runllm

    It could be possible to add periodic active-state reporting through the existing Sentry plumbing: the code currently records operation counters and honors FLYTE_DISABLE_SENTRY=true (Sentry utilities). However, the provided sources do not confirm sentry-go’s Meter.Gauge API or the runs/actions/apps status queries and workers described in the issue, so I can’t verify those implementation details.

    Would you like a concise issue review or an implementation plan based only on the available sources?

    Sources:


    This is an AI-generated response and your feedback is appreciated! Please leave a 👍 if this is helpful and 👎 if it is not.

    Mention @Herald to ask follow-up questions. See runllm.com for more!

  2. Icewind52 commented on Oct 23, 2026

    @Icewind52
    Contributor

    #take

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions