Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/main/frontend/common/utils/live-total.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { useEffect, useState } from "react";

import { Total } from "./timings.tsx";

export default function LiveTotal({
total,
start,
}: {
total: number | undefined;
start: number;
}) {
const sinceStart = () => Date.now() - start;
const [duration, setDuration] = useState<number>(total ?? sinceStart());
useEffect(() => {
if (total == null) {
const interval = setInterval(() => {
setDuration(sinceStart());
}, 3001); // to match step polling interval
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I increased this in b25d987

As I was noticing while watching live that numbers were going higher than the final result.

Added + 1 so that this starts just after it and is less likely to go over the final result

return () => clearInterval(interval);
} else {
setDuration(total);
}
}, [total]);

return <Total ms={duration} />;
}
5 changes: 3 additions & 2 deletions src/main/frontend/common/utils/run-estimator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ export default class RunEstimator {
if (previous === undefined) {
return 0; // No previous run, so no estimate
}
const previousTiming = previous.totalDurationMillis;
const currentTiming = stage.totalDurationMillis;
const previousTiming = previous.totalDurationMillis!;
const currentTiming =
stage.totalDurationMillis ?? Date.now() - stage.startTimeMillis;
if (previousTiming <= currentTiming) {
return 99; // Assume 99% complete if the previous run was longer than the current run
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import StatusIcon from "../../../common/components/status-icon.tsx";
import Tooltip from "../../../common/components/tooltip.tsx";
import { LocalizedMessageKey, useMessages } from "../../../common/i18n";
import { classNames } from "../../../common/utils/classnames.ts";
import { Total } from "../../../common/utils/timings.tsx";
import LiveTotal from "../../../common/utils/live-total.tsx";
import {
LOG_FETCH_SIZE,
StepInfo,
Expand Down Expand Up @@ -122,7 +122,10 @@ export default function ConsoleLogCard(props: ConsoleLogCardProps) {
fontWeight: "normal",
}}
>
<Total ms={props.step.totalDurationMillis} />
<LiveTotal
total={props.step.totalDurationMillis}
start={props.step.startTimeMillis}
/>
</span>
</div>
</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
import Filter from "../../../common/components/filter.tsx";
import StatusIcon from "../../../common/components/status-icon.tsx";
import { classNames } from "../../../common/utils/classnames.ts";
import { Total } from "../../../common/utils/timings.tsx";
import LiveTotal from "../../../common/utils/live-total.tsx";
import {
Result,
StageInfo,
Expand Down Expand Up @@ -190,7 +190,10 @@ const TreeNode = memo(function TreeNode({
{stage.name}
</div>
<div className="pgv-tree-item__description">
<Total ms={stage.totalDurationMillis} />
<LiveTotal
start={stage.startTimeMillis}
total={stage.totalDurationMillis}
/>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,8 @@ import StatusIcon, {
} from "../../../common/components/status-icon.tsx";
import { DOCUMENT } from "../../../common/components/symbols.tsx";
import Tooltip from "../../../common/components/tooltip.tsx";
import {
exact,
Paused,
Started,
Total,
} from "../../../common/utils/timings.tsx";
import LiveTotal from "../../../common/utils/live-total.tsx";
import { exact, Paused, Started } from "../../../common/utils/timings.tsx";
import { StageInfo } from "../../../pipeline-graph-view/pipeline-graph/main/PipelineGraphModel.tsx";
import StageNodeLink from "./StageNodeLink.tsx";

Expand Down Expand Up @@ -39,7 +35,11 @@ export default function StageDetails({ stage }: StageDetailsProps) {
</div>
<ul>
<li>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
aria-label={"Total duration"}
>
<path
d="M112.91 128A191.85 191.85 0 0064 254c-1.18 106.35 85.65 193.8 192 194 106.2.2 192-85.83 192-192 0-104.54-83.55-189.61-187.5-192a4.36 4.36 0 00-4.5 4.37V152"
fill="none"
Expand All @@ -53,7 +53,10 @@ export default function StageDetails({ stage }: StageDetailsProps) {
fill="currentColor"
/>
</svg>
<Total ms={stage.totalDurationMillis} />
<LiveTotal
total={stage.totalDurationMillis}
start={stage.startTimeMillis}
/>
</li>
<li>
<Tooltip content={exact(stage.startTimeMillis)}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,20 +401,13 @@ function createTimings(
}
const stage = column.topStage;

const text = stage?.totalDurationMillis + "";
if (!text) {
// shouldn't happen
continue;
}
Comment on lines -405 to -408
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timja what was the reason for this having to be accounted for?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

umm I think was just a safety thing, if it says shouldn't happen then likely wasn't expected in practice

const key = "l_t_" + node.key;

labels.push({
x: column.centerX,
y: node.y + 55,
node,
stage,
text,
key,
text: "", // we take the duration from the stage itself at render time
key: `l_t_${node.key}`,
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export interface StageInfo {
synthetic?: boolean;
pauseDurationMillis: number;
startTimeMillis: number;
totalDurationMillis: number;
totalDurationMillis?: number; // will be null if the stage is still running
agent: string;
url: string;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CSSProperties } from "react";

import { Total } from "../../../../common/utils/timings.tsx";
import LiveTotal from "../../../../common/utils/live-total.tsx";
import { sequentialStagesLabelOffset } from "../PipelineGraphLayout.ts";
import { LayoutInfo, NodeLabelInfo } from "../PipelineGraphModel.tsx";
import { TooltipLabel } from "./convertLabelToTooltip.tsx";
Expand Down Expand Up @@ -124,7 +124,10 @@ export function TimingsLabel({

return (
<div className={classNames.join(" ")} style={style} key={details.key}>
<Total ms={parseInt(details.text, 10)} />
<LiveTotal
total={details.stage?.totalDurationMillis}
start={details.stage?.startTimeMillis ?? Date.now()}
/>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import StatusIcon, {
} from "../../../../common/components/status-icon.tsx";
import Tooltip from "../../../../common/components/tooltip.tsx";
import { classNames } from "../../../../common/utils/classnames.ts";
import { Total } from "../../../../common/utils/timings.tsx";
import LiveTotal from "../../../../common/utils/live-total.tsx";
import { CounterNodeInfo } from "../PipelineGraphLayout.ts";
import {
LayoutInfo,
Expand Down Expand Up @@ -58,7 +58,10 @@ export function Node({
/>
{stage.name}
<span style={{ color: "var(--text-color-secondary)" }}>
<Total ms={stage.totalDurationMillis} />
<LiveTotal
total={stage.totalDurationMillis}
start={stage.startTimeMillis}
/>
</span>
</a>
</li>
Expand Down Expand Up @@ -143,14 +146,20 @@ export function Node({
<div className="pgv-node-tooltip">
<div>{title}</div>
<div>
<Total ms={node.stage.totalDurationMillis} />
<LiveTotal
total={node.stage.totalDurationMillis}
start={node.stage.startTimeMillis}
/>
</div>
</div>
);
} else {
tooltip = (
<div className="pgv-node-tooltip">
<Total ms={node.stage.totalDurationMillis} />
<LiveTotal
total={node.stage.totalDurationMillis}
start={node.stage.startTimeMillis}
/>
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ public long getStartTimeMillis() {
return timingInfo.getStartTimeMillis();
}

public long getTotalDurationMillis() {
return totalDurationMillis;
public Long getTotalDurationMillis() {
return state.isInProgress() ? null : totalDurationMillis;
}

public String getId() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
UNKNOWN,
ABORTED;

public boolean isInProgress() {
return this == RUNNING || this == QUEUED || this == PAUSED;

Check warning on line 24 in src/main/java/io/jenkins/plugins/pipelinegraphview/utils/PipelineState.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 24 is only partially covered, one branch is missing
}

public static PipelineState of(WorkflowRun run) {
Result result = run.getResult();
if (result == Result.SUCCESS) {
Expand Down