This is an automated email from the ASF dual-hosted git repository.
pierrejeambrun pushed a commit to branch v3-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/v3-1-test by this push:
new 6fe77aa6b77 [v3-1-test] Fix duration chart duration format (#58561)
(#58564)
6fe77aa6b77 is described below
commit 6fe77aa6b776929e3667e4a146066e183b8f0c43
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Fri Nov 21 16:48:57 2025 +0100
[v3-1-test] Fix duration chart duration format (#58561) (#58564)
(cherry picked from commit 2512aa40e0372374de2a9493141f24c4566cb8b9)
Co-authored-by: Pierre Jeambrun <[email protected]>
---
.../airflow/ui/src/components/DurationChart.tsx | 24 +++++++++++++++++++---
.../src/airflow/ui/src/utils/datetimeUtils.ts | 7 +++++--
2 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/airflow-core/src/airflow/ui/src/components/DurationChart.tsx
b/airflow-core/src/airflow/ui/src/components/DurationChart.tsx
index c0fd7cf796b..5699dcc8c8d 100644
--- a/airflow-core/src/airflow/ui/src/components/DurationChart.tsx
+++ b/airflow-core/src/airflow/ui/src/components/DurationChart.tsx
@@ -36,7 +36,7 @@ import { useNavigate } from "react-router-dom";
import type { TaskInstanceResponse, GridRunsResponse } from
"openapi/requests/types.gen";
import { getComputedCSSVariableValue } from "src/theme";
-import { DEFAULT_DATETIME_FORMAT } from "src/utils/datetimeUtils";
+import { DEFAULT_DATETIME_FORMAT, renderDuration } from
"src/utils/datetimeUtils";
ChartJS.register(
CategoryScale,
@@ -94,7 +94,7 @@ export const DurationChart = ({
borderColor: "grey",
borderWidth: 1,
label: {
- content: (ctx: PartialEventContext) => average(ctx, 1).toFixed(2),
+ content: (ctx: PartialEventContext) => renderDuration(average(ctx, 1),
false) ?? "0",
display: true,
position: "end",
},
@@ -106,7 +106,7 @@ export const DurationChart = ({
borderColor: "grey",
borderWidth: 1,
label: {
- content: (ctx: PartialEventContext) => average(ctx, 0).toFixed(2),
+ content: (ctx: PartialEventContext) => renderDuration(average(ctx, 0),
false) ?? "0",
display: true,
position: "end",
},
@@ -200,6 +200,17 @@ export const DurationChart = ({
runAnnotation,
},
},
+ tooltip: {
+ callbacks: {
+ label: (context) => {
+ const datasetLabel = context.dataset.label ?? "";
+
+ const formatted = renderDuration(context.parsed.y, false) ??
"0";
+
+ return datasetLabel ? `${datasetLabel}: ${formatted}` :
formatted;
+ },
+ },
+ },
},
responsive: true,
scales: {
@@ -211,6 +222,13 @@ export const DurationChart = ({
title: { align: "end", display: true, text:
translate("common:dagRun.runAfter") },
},
y: {
+ ticks: {
+ callback: (value) => {
+ const num = typeof value === "number" ? value :
Number(value);
+
+ return renderDuration(num, false) ?? "0";
+ },
+ },
title: { align: "end", display: true, text:
translate("common:duration") },
},
},
diff --git a/airflow-core/src/airflow/ui/src/utils/datetimeUtils.ts
b/airflow-core/src/airflow/ui/src/utils/datetimeUtils.ts
index abd598e3deb..8c2f28c9541 100644
--- a/airflow-core/src/airflow/ui/src/utils/datetimeUtils.ts
+++ b/airflow-core/src/airflow/ui/src/utils/datetimeUtils.ts
@@ -26,13 +26,16 @@ dayjs.extend(tz);
export const DEFAULT_DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss";
export const DEFAULT_DATETIME_FORMAT_WITH_TZ = `${DEFAULT_DATETIME_FORMAT} z`;
-export const renderDuration = (durationSeconds: number | null | undefined):
string | undefined => {
+export const renderDuration = (
+ durationSeconds: number | null | undefined,
+ withMilliseconds: boolean = true,
+): string | undefined => {
if (durationSeconds === null || durationSeconds === undefined ||
durationSeconds <= 0.01) {
return undefined;
}
// If under 60 seconds, render milliseconds
- if (durationSeconds < 60) {
+ if (durationSeconds < 60 && withMilliseconds) {
return dayjs.duration(Number(durationSeconds.toFixed(3)),
"seconds").format("HH:mm:ss.SSS");
}