This is an automated email from the ASF dual-hosted git repository.
choo121600 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new d2161ae04cb Hide Dashboard metric percentages when a state count is
capped (#67664)
d2161ae04cb is described below
commit d2161ae04cb7a888ef2276e4dca893674bcbc565
Author: wilmerdooley <[email protected]>
AuthorDate: Sat Jun 6 00:49:42 2026 -0700
Hide Dashboard metric percentages when a state count is capped (#67664)
Signed-off-by: wilmerdooley <[email protected]>
---
.../ui/src/pages/Dashboard/HistoricalMetrics/DagRunMetrics.tsx | 5 +++++
.../ui/src/pages/Dashboard/HistoricalMetrics/MetricSection.tsx | 5 ++++-
.../ui/src/pages/Dashboard/HistoricalMetrics/TaskInstanceMetrics.tsx | 5 +++++
3 files changed, 14 insertions(+), 1 deletion(-)
diff --git
a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/DagRunMetrics.tsx
b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/DagRunMetrics.tsx
index a6578c0f383..7d0bec32d76 100644
---
a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/DagRunMetrics.tsx
+++
b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/DagRunMetrics.tsx
@@ -35,6 +35,10 @@ const DAGRUN_STATES: Array<keyof DAGRunStates> = ["queued",
"running", "success"
export const DagRunMetrics = ({ dagRunStates, endDate, startDate,
stateCountLimit }: DagRunMetricsProps) => {
const { t: translate } = useTranslation();
const total = Object.values(dagRunStates).reduce((sum, count) => sum +
count, 0);
+ // When any state hit the API's STATE_COUNT_CAP, the summed total is only a
+ // lower bound, so per-state percentages computed from it are wrong (#67336).
+ // Suppress percentages for the whole group in that case.
+ const isTotalTruncated = Object.values(dagRunStates).some((count) => count
>= stateCountLimit);
return (
<Box borderRadius={5} borderWidth={1} p={4}>
@@ -48,6 +52,7 @@ export const DagRunMetrics = ({ dagRunStates, endDate,
startDate, stateCountLimi
<MetricSection
capped={dagRunStates[state] >= stateCountLimit}
endDate={endDate}
+ isTotalTruncated={isTotalTruncated}
key={state}
kind="dag_runs"
runs={dagRunStates[state]}
diff --git
a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/MetricSection.tsx
b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/MetricSection.tsx
index e0cfff1f01c..20aae19444d 100644
---
a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/MetricSection.tsx
+++
b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/MetricSection.tsx
@@ -30,6 +30,7 @@ const BAR_HEIGHT = 5;
type MetricSectionProps = {
readonly capped?: boolean;
readonly endDate?: string;
+ readonly isTotalTruncated?: boolean;
readonly kind: string;
readonly runs: number;
readonly startDate: string;
@@ -40,6 +41,7 @@ type MetricSectionProps = {
export const MetricSection = ({
capped = false,
endDate,
+ isTotalTruncated = false,
kind,
runs,
startDate,
@@ -48,7 +50,8 @@ export const MetricSection = ({
}: MetricSectionProps) => {
const stateWidth = capped ? BAR_WIDTH : total === 0 ? 0 : (runs / total) *
BAR_WIDTH;
const remainingWidth = BAR_WIDTH - stateWidth;
- const statePercent = capped ? undefined : total === 0 ? 0 : ((runs / total)
* 100).toFixed(2);
+ const hidePercent = isTotalTruncated;
+ const statePercent = hidePercent ? undefined : total === 0 ? 0 : ((runs /
total) * 100).toFixed(2);
const stateParam = kind === "task_instances" ? SearchParamsKeys.TASK_STATE :
SearchParamsKeys.STATE;
const searchParams = new URLSearchParams(
diff --git
a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/TaskInstanceMetrics.tsx
b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/TaskInstanceMetrics.tsx
index 617d3e62b04..5cbf5811e17 100644
---
a/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/TaskInstanceMetrics.tsx
+++
b/airflow-core/src/airflow/ui/src/pages/Dashboard/HistoricalMetrics/TaskInstanceMetrics.tsx
@@ -55,6 +55,10 @@ export const TaskInstanceMetrics = ({
}: TaskInstanceMetricsProps) => {
const { t: translate } = useTranslation();
const total = Object.values(taskInstanceStates).reduce((sum, count) => sum +
count, 0);
+ // When any state hit the API's STATE_COUNT_CAP, the summed total is only a
+ // lower bound, so per-state percentages computed from it are wrong (#67336).
+ // Suppress percentages for the whole group in that case.
+ const isTotalTruncated = Object.values(taskInstanceStates).some((count) =>
count >= stateCountLimit);
return (
<Box borderRadius={5} borderWidth={1} mt={2} p={4}>
@@ -71,6 +75,7 @@ export const TaskInstanceMetrics = ({
<MetricSection
capped={taskInstanceStates[state] >= stateCountLimit}
endDate={endDate}
+ isTotalTruncated={isTotalTruncated}
key={state}
kind="task_instances"
runs={taskInstanceStates[state]}