diff --git a/site/src/modules/workspaces/WorkspaceTiming/Chart/utils.ts b/site/src/modules/workspaces/WorkspaceTiming/Chart/utils.ts index 45c6f5bf681d1..55df5b9ffad48 100644 --- a/site/src/modules/workspaces/WorkspaceTiming/Chart/utils.ts +++ b/site/src/modules/workspaces/WorkspaceTiming/Chart/utils.ts @@ -29,7 +29,20 @@ export const calcDuration = (range: TimeRange): number => { // data in 200ms intervals. However, if the total time is 1 minute, we should // display the data in 5 seconds intervals. To achieve this, we define the // dimensions object that contains the time intervals for the chart. -const scales = [5_000, 500, 100]; +const second = 1_000; +const minute = 60 * second; +const hour = 60 * minute; +const day = 24 * hour; +const scales = [ + day, + hour, + 5 * minute, + minute, + 10 * second, + 5 * second, + 500, + 100, +]; const pickScale = (totalTime: number): number => { for (const s of scales) { @@ -48,7 +61,29 @@ export const makeTicks = (time: number) => { }; export const formatTime = (time: number): string => { - return `${time.toLocaleString()}ms`; + const seconds = Math.floor(time / 1000); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + + const parts: string[] = []; + if (days > 0) { + parts.push(`${days}d`); + } + if (hours > 0) { + parts.push(`${hours % 24}h`); + } + if (minutes > 0) { + parts.push(`${minutes % 60}m`); + } + if (seconds > 0) { + parts.push(`${seconds % 60}s`); + } + if (time % 1000 > 0) { + parts.push(`${time % 1000}ms`); + } + + return parts.join(" "); }; export const calcOffset = (range: TimeRange, baseRange: TimeRange): number => { diff --git a/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.stories.tsx b/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.stories.tsx index 0210353488257..9c93b4bf6806e 100644 --- a/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.stories.tsx +++ b/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.stories.tsx @@ -126,3 +126,29 @@ export const LoadingWhenAgentScriptTimingsAreEmpty: Story = { agentScriptTimings: undefined, }, }; + +export const LongTimeRange = { + args: { + provisionerTimings: [ + { + ...WorkspaceTimingsResponse.provisioner_timings[0], + started_at: "2021-09-01T00:00:00Z", + ended_at: "2021-09-01T00:10:00Z", + }, + ], + agentConnectionTimings: [ + { + ...WorkspaceTimingsResponse.agent_connection_timings[0], + started_at: "2021-09-01T00:10:00Z", + ended_at: "2021-09-01T00:35:00Z", + }, + ], + agentScriptTimings: [ + { + ...WorkspaceTimingsResponse.agent_script_timings[0], + started_at: "2021-09-01T00:35:00Z", + ended_at: "2021-09-01T01:00:00Z", + }, + ], + }, +}; diff --git a/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.tsx b/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.tsx index 63fc03ad2a3de..2cb0a7c20d5d8 100644 --- a/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.tsx +++ b/site/src/modules/workspaces/WorkspaceTiming/WorkspaceTimings.tsx @@ -12,7 +12,12 @@ import type { import sortBy from "lodash/sortBy"; import uniqBy from "lodash/uniqBy"; import { type FC, useState } from "react"; -import { type TimeRange, calcDuration, mergeTimeRanges } from "./Chart/utils"; +import { + type TimeRange, + calcDuration, + formatTime, + mergeTimeRanges, +} from "./Chart/utils"; import { ResourcesChart, isCoderResource } from "./ResourcesChart"; import { ScriptsChart } from "./ScriptsChart"; import { @@ -85,7 +90,7 @@ export const WorkspaceTimings: FC = ({ const displayProvisioningTime = () => { const totalRange = mergeTimeRanges(timings.map(toTimeRange)); const totalDuration = calcDuration(totalRange); - return humanizeDuration(totalDuration); + return formatTime(totalDuration); }; return (