Skip to content

Feat: Improved run start timeline visibility #1732

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ffcb239
Record cold start and execution metrics on attempt executions. Add co…
ericallam Feb 24, 2025
5b2001a
Add deployed tasks run timeline metrics
ericallam Feb 25, 2025
7f7cdc5
Add Dequeued event to run timeline and cleanup the run timeline code
ericallam Feb 25, 2025
b82acec
Adds variants to storybook
samejr Feb 26, 2025
d9f8952
WIP adding new span styles
samejr Feb 26, 2025
61e4268
Added offset progress bar animation
samejr Feb 26, 2025
381d3be
More storybook states
samejr Feb 26, 2025
d199647
Adds support for the full vertical span to show the same state
samejr Feb 26, 2025
07b7374
Adds error state to timelineLine
samejr Feb 26, 2025
d8f18f7
Added additional state
samejr Feb 26, 2025
9c651b1
Added more line styling
samejr Feb 26, 2025
efe359b
Added progress state to dequeued
samejr Feb 27, 2025
0be59a1
Added another state to storybook
samejr Feb 27, 2025
d6af00b
Fixed classname error
samejr Feb 27, 2025
ca57862
Updated styles for the span timeline points
samejr Feb 27, 2025
6af7008
Fixes alignment of timeline follow cursor indicator
samejr Feb 27, 2025
53d0437
Adds help text tooltip to timeline span type titles
samejr Feb 27, 2025
f9aec47
Fixes type error
samejr Feb 27, 2025
fb93042
Tweaked wording of tooltips
samejr Feb 27, 2025
a63145f
Fixed type error (check this)
samejr Feb 27, 2025
f1e904b
Moved isAdmin to a higher level
samejr Feb 27, 2025
c36012f
removed unused admin props
samejr Feb 27, 2025
27c7ae2
Removed unused Admin filter
samejr Feb 27, 2025
490edec
Fixed border styling
samejr Feb 27, 2025
76fcff7
made the opacity of the timeline states 30% less
samejr Feb 27, 2025
74ec03b
Undo type cast
samejr Feb 27, 2025
63d6efc
Added a diminished style that’s used for spans (grey progress bar)
samejr Feb 27, 2025
2ec5234
Adds new storybook state
samejr Feb 27, 2025
53b6d6d
Fixed timeline state
samejr Feb 27, 2025
221f444
Removed state if span isn’t the first
samejr Feb 27, 2025
15680e7
Changed the timestamp span icon
samejr Feb 27, 2025
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
18 changes: 17 additions & 1 deletion apps/coordinator/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -663,9 +663,25 @@ class TaskCoordinator {

await chaosMonkey.call();

const lazyPayload = {
...lazyAttempt.lazyPayload,
metrics: [
...(message.startTime
? [
{
name: "start",
event: "lazy_payload",
timestamp: message.startTime,
duration: Date.now() - message.startTime,
},
]
: []),
],
};

socket.emit("EXECUTE_TASK_RUN_LAZY_ATTEMPT", {
version: "v1",
lazyPayload: lazyAttempt.lazyPayload,
lazyPayload,
});
} catch (error) {
if (error instanceof ChaosMonkey.Error) {
Expand Down
6 changes: 5 additions & 1 deletion apps/docker-provider/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,18 @@ class DockerTaskOperations implements TaskOperations {
`--env=POD_NAME=${containerName}`,
`--env=COORDINATOR_HOST=${COORDINATOR_HOST}`,
`--env=COORDINATOR_PORT=${COORDINATOR_PORT}`,
`--env=SCHEDULED_AT_MS=${Date.now()}`,
`--env=TRIGGER_POD_SCHEDULED_AT_MS=${Date.now()}`,
`--name=${containerName}`,
];

if (process.env.ENFORCE_MACHINE_PRESETS) {
runArgs.push(`--cpus=${opts.machine.cpu}`, `--memory=${opts.machine.memory}G`);
}

if (opts.dequeuedAt) {
runArgs.push(`--env=TRIGGER_RUN_DEQUEUED_AT_MS=${opts.dequeuedAt}`);
}

runArgs.push(`${opts.image}`);

try {
Expand Down
5 changes: 4 additions & 1 deletion apps/kubernetes-provider/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ class KubernetesTaskOperations implements TaskOperations {
name: "TRIGGER_RUN_ID",
value: opts.runId,
},
...(opts.dequeuedAt
? [{ name: "TRIGGER_RUN_DEQUEUED_AT_MS", value: String(opts.dequeuedAt) }]
: []),
],
volumeMounts: [
{
Expand Down Expand Up @@ -518,7 +521,7 @@ class KubernetesTaskOperations implements TaskOperations {
},
},
{
name: "SCHEDULED_AT_MS",
name: "TRIGGER_POD_SCHEDULED_AT_MS",
value: Date.now().toString(),
},
...this.#coordinatorEnvVars,
Expand Down
2 changes: 1 addition & 1 deletion apps/webapp/app/components/primitives/Badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const variants = {
small:
"grid place-items-center rounded-full px-[0.4rem] h-4 tracking-wider text-xxs bg-background-dimmed text-text-dimmed uppercase whitespace-nowrap",
"extra-small":
"grid place-items-center border border-charcoal-650 rounded-sm px-1 h-4 border-tracking-wider text-xxs bg-background-bright text-blue-500 whitespace-nowrap",
"grid place-items-center border border-charcoal-650 rounded-sm px-1 h-4 tracking-wide text-xxs bg-background-bright text-blue-500 whitespace-nowrap",
outline:
"grid place-items-center rounded-sm px-1.5 h-5 tracking-wider text-xxs border border-dimmed text-text-dimmed uppercase whitespace-nowrap",
"outline-rounded":
Expand Down
138 changes: 131 additions & 7 deletions apps/webapp/app/components/primitives/DateTime.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ type DateTimeProps = {
includeSeconds?: boolean;
includeTime?: boolean;
showTimezone?: boolean;
previousDate?: Date | string | null; // Add optional previous date for comparison
};

export const DateTime = ({
Expand Down Expand Up @@ -70,20 +71,116 @@ export function formatDateTime(
}).format(date);
}

export const DateTimeAccurate = ({ date, timeZone = "UTC" }: DateTimeProps) => {
// New component that only shows date when it changes
export const SmartDateTime = ({ date, previousDate = null, timeZone = "UTC" }: DateTimeProps) => {
const locales = useLocales();

const realDate = typeof date === "string" ? new Date(date) : date;
const realPrevDate = previousDate
? typeof previousDate === "string"
? new Date(previousDate)
: previousDate
: null;

// Initial formatted values
const initialTimeOnly = formatTimeOnly(realDate, timeZone, locales);
const initialWithDate = formatSmartDateTime(realDate, timeZone, locales);

// State for the formatted time
const [formattedDateTime, setFormattedDateTime] = useState<string>(
realPrevDate && isSameDay(realDate, realPrevDate) ? initialTimeOnly : initialWithDate
);

useEffect(() => {
const resolvedOptions = Intl.DateTimeFormat().resolvedOptions();
const userTimeZone = resolvedOptions.timeZone;

// Check if we should show the date
const showDatePart = !realPrevDate || !isSameDay(realDate, realPrevDate);

// Format with appropriate function
setFormattedDateTime(
showDatePart
? formatSmartDateTime(realDate, userTimeZone, locales)
: formatTimeOnly(realDate, userTimeZone, locales)
);
}, [locales, realDate, realPrevDate]);

return <Fragment>{formattedDateTime.replace(/\s/g, String.fromCharCode(32))}</Fragment>;
};

// Helper function to check if two dates are on the same day
function isSameDay(date1: Date, date2: Date): boolean {
return (
date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate()
);
}

// Format with date and time
function formatSmartDateTime(date: Date, timeZone: string, locales: string[]): string {
return new Intl.DateTimeFormat(locales, {
month: "short",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",
timeZone,
// @ts-ignore fractionalSecondDigits works in most modern browsers
fractionalSecondDigits: 3,
}).format(date);
}

// Format time only
function formatTimeOnly(date: Date, timeZone: string, locales: string[]): string {
return new Intl.DateTimeFormat(locales, {
hour: "numeric",
minute: "numeric",
second: "numeric",
timeZone,
// @ts-ignore fractionalSecondDigits works in most modern browsers
fractionalSecondDigits: 3,
}).format(date);
}

const initialFormattedDateTime = formatDateTimeAccurate(realDate, timeZone, locales);
export const DateTimeAccurate = ({
date,
timeZone = "UTC",
previousDate = null,
}: DateTimeProps) => {
const locales = useLocales();
const realDate = typeof date === "string" ? new Date(date) : date;
const realPrevDate = previousDate
? typeof previousDate === "string"
? new Date(previousDate)
: previousDate
: null;

// Use the new Smart formatting if previousDate is provided
const initialFormattedDateTime = realPrevDate
? isSameDay(realDate, realPrevDate)
? formatTimeOnly(realDate, timeZone, locales)
: formatDateTimeAccurate(realDate, timeZone, locales)
: formatDateTimeAccurate(realDate, timeZone, locales);

const [formattedDateTime, setFormattedDateTime] = useState<string>(initialFormattedDateTime);

useEffect(() => {
const resolvedOptions = Intl.DateTimeFormat().resolvedOptions();

setFormattedDateTime(formatDateTimeAccurate(realDate, resolvedOptions.timeZone, locales));
}, [locales, realDate]);
const userTimeZone = resolvedOptions.timeZone;

if (realPrevDate) {
// Smart formatting based on whether date changed
setFormattedDateTime(
isSameDay(realDate, realPrevDate)
? formatTimeOnly(realDate, userTimeZone, locales)
: formatDateTimeAccurate(realDate, userTimeZone, locales)
);
} else {
// Default behavior when no previous date
setFormattedDateTime(formatDateTimeAccurate(realDate, userTimeZone, locales));
}
}, [locales, realDate, realPrevDate]);

return <Fragment>{formattedDateTime.replace(/\s/g, String.fromCharCode(32))}</Fragment>;
};
Expand All @@ -96,7 +193,34 @@ function formatDateTimeAccurate(date: Date, timeZone: string, locales: string[])
minute: "numeric",
second: "numeric",
timeZone,
// @ts-ignore this works in 92.5% of browsers https://caniuse.com/mdn-javascript_builtins_intl_datetimeformat_datetimeformat_options_parameter_options_fractionalseconddigits_parameter
// @ts-ignore fractionalSecondDigits works in most modern browsers
fractionalSecondDigits: 3,
}).format(date);

return formattedDateTime;
}

export const DateTimeShort = ({ date, timeZone = "UTC" }: DateTimeProps) => {
const locales = useLocales();
const realDate = typeof date === "string" ? new Date(date) : date;
const initialFormattedDateTime = formatDateTimeShort(realDate, timeZone, locales);
const [formattedDateTime, setFormattedDateTime] = useState<string>(initialFormattedDateTime);

useEffect(() => {
const resolvedOptions = Intl.DateTimeFormat().resolvedOptions();
setFormattedDateTime(formatDateTimeShort(realDate, resolvedOptions.timeZone, locales));
}, [locales, realDate]);

return <Fragment>{formattedDateTime.replace(/\s/g, String.fromCharCode(32))}</Fragment>;
};

function formatDateTimeShort(date: Date, timeZone: string, locales: string[]): string {
const formattedDateTime = new Intl.DateTimeFormat(locales, {
hour: "numeric",
minute: "numeric",
second: "numeric",
timeZone,
// @ts-ignore fractionalSecondDigits works in most modern browsers
fractionalSecondDigits: 3,
}).format(date);

Expand Down
Loading