diff --git a/apps/webapp/app/assets/icons/MachineIcon.tsx b/apps/webapp/app/assets/icons/MachineIcon.tsx new file mode 100644 index 0000000000..a58023a283 --- /dev/null +++ b/apps/webapp/app/assets/icons/MachineIcon.tsx @@ -0,0 +1,221 @@ +import { cn } from "~/utils/cn"; + +export function MachineIcon({ preset, className }: { preset?: string; className?: string }) { + if (!preset) { + return ; + } + + switch (preset) { + case "no-machine": + return ; + case "micro": + return ; + case "small-1x": + return ; + case "small-2x": + return ; + case "medium-1x": + return ; + case "medium-2x": + return ; + case "large-1x": + return ; + case "large-2x": + return ; + default: + return ; + } +} + +function MachineDefaultIcon({ className }: { className?: string }) { + return ( + + + + + + ); +} + +function MachineIconNoMachine({ className }: { className?: string }) { + return ( + + + + + + + ); +} + +function MachineIconMicro({ className }: { className?: string }) { + return ( + + + + + + ); +} + +function MachineIconSmall1x({ className }: { className?: string }) { + return ( + + + + + + ); +} + +function MachineIconSmall2x({ className }: { className?: string }) { + return ( + + + + + + ); +} + +function MachineIconMedium1x({ className }: { className?: string }) { + return ( + + + + + + ); +} + +function MachineIconMedium2x({ className }: { className?: string }) { + return ( + + + + + + ); +} + +function MachineIconLarge1x({ className }: { className?: string }) { + return ( + + + + + + ); +} + +function MachineIconLarge2x({ className }: { className?: string }) { + return ( + + + + + + ); +} diff --git a/apps/webapp/app/components/MachineLabelCombo.tsx b/apps/webapp/app/components/MachineLabelCombo.tsx new file mode 100644 index 0000000000..40a37e59a6 --- /dev/null +++ b/apps/webapp/app/components/MachineLabelCombo.tsx @@ -0,0 +1,59 @@ +import { type MachinePresetName } from "@trigger.dev/core/v3"; +import { MachineIcon } from "~/assets/icons/MachineIcon"; +import { cn } from "~/utils/cn"; + +export function MachineLabelCombo({ + preset, + className, + iconClassName, + labelClassName, +}: { + preset?: MachinePresetName | null; + className?: string; + iconClassName?: string; + labelClassName?: string; +}) { + return ( + + + + + ); +} + +export function MachineLabel({ + preset, + className, +}: { + preset?: MachinePresetName | null; + className?: string; +}) { + return ( + {formatMachinePresetName(preset)} + ); +} + +export function formatMachinePresetName(preset?: MachinePresetName | null): string { + if (!preset) { + return "No machine yet"; + } + + switch (preset) { + case "micro": + return "Micro"; + case "small-1x": + return "Small 1x"; + case "small-2x": + return "Small 2x"; + case "medium-1x": + return "Medium 1x"; + case "medium-2x": + return "Medium 2x"; + case "large-1x": + return "Large 1x"; + case "large-2x": + return "Large 2x"; + default: + return preset; + } +} diff --git a/apps/webapp/app/components/MachineTooltipInfo.tsx b/apps/webapp/app/components/MachineTooltipInfo.tsx new file mode 100644 index 0000000000..3b3616288b --- /dev/null +++ b/apps/webapp/app/components/MachineTooltipInfo.tsx @@ -0,0 +1,63 @@ +import { MachineIcon } from "~/assets/icons/MachineIcon"; +import { docsPath } from "~/utils/pathBuilder"; +import { LinkButton } from "./primitives/Buttons"; +import { Header3 } from "./primitives/Headers"; +import { Paragraph } from "./primitives/Paragraph"; +import { BookOpenIcon } from "@heroicons/react/20/solid"; + +export function MachineTooltipInfo() { + return ( +
+
+
+ + No machine yet +
+ + The machine is set at the moment the run is dequeued. + +
+
+
+ + Micro +
+ + The smallest and cheapest machine available. + +
+
+
+ Small 1x & 2x +
+ + Smaller machines for basic workloads. Small 1x is the default machine. + +
+
+
+ Medium 1x & 2x +
+ + Medium machines for more demanding workloads. + +
+
+
+ Large 1x & 2x +
+ + Larger machines for the most demanding workloads such as video processing. The larger the + machine, the more expensive it is. + +
+ + Read docs + +
+ ); +} diff --git a/apps/webapp/app/components/runs/v3/TaskRunsTable.tsx b/apps/webapp/app/components/runs/v3/TaskRunsTable.tsx index f555f26cb4..4a76cd18dd 100644 --- a/apps/webapp/app/components/runs/v3/TaskRunsTable.tsx +++ b/apps/webapp/app/components/runs/v3/TaskRunsTable.tsx @@ -8,7 +8,11 @@ import { } from "@heroicons/react/20/solid"; import { BeakerIcon, BookOpenIcon, CheckIcon } from "@heroicons/react/24/solid"; import { useLocation } from "@remix-run/react"; -import { formatDuration, formatDurationMilliseconds } from "@trigger.dev/core/v3"; +import { + formatDuration, + formatDurationMilliseconds, + MachinePresetName, +} from "@trigger.dev/core/v3"; import { useCallback, useRef } from "react"; import { Badge } from "~/components/primitives/Badge"; import { Button, LinkButton } from "~/components/primitives/Buttons"; @@ -52,6 +56,9 @@ import { filterableTaskRunStatuses, TaskRunStatusCombo, } from "./TaskRunStatus"; +import { MachineIcon } from "~/assets/icons/MachineIcon"; +import { MachineLabelCombo } from "~/components/MachineLabelCombo"; +import { MachineTooltipInfo } from "~/components/MachineTooltipInfo"; type RunsTableProps = { total: number; @@ -201,6 +208,9 @@ export function TaskRunsTable({ Compute )} + }> + Machine + Test Created at )} + + + {run.isTest ? : "–"} diff --git a/apps/webapp/app/presenters/v3/NextRunListPresenter.server.ts b/apps/webapp/app/presenters/v3/NextRunListPresenter.server.ts index bc061b36d7..9217c5039d 100644 --- a/apps/webapp/app/presenters/v3/NextRunListPresenter.server.ts +++ b/apps/webapp/app/presenters/v3/NextRunListPresenter.server.ts @@ -9,6 +9,7 @@ import { timeFilters } from "~/components/runs/v3/SharedFilters"; import { findDisplayableEnvironment } from "~/models/runtimeEnvironment.server"; import { getAllTaskIdentifiers } from "~/models/task.server"; import { RunsRepository } from "~/services/runsRepository.server"; +import { machinePresetFromRun } from "~/v3/machinePresets.server"; import { ServiceValidationError } from "~/v3/services/baseService.server"; import { isCancellableRunStatus, isFinalRunStatus, isPendingRunStatus } from "~/v3/taskStatus"; @@ -231,6 +232,7 @@ export class NextRunListPresenter { rootTaskRunId: run.rootTaskRunId, metadata: run.metadata, metadataType: run.metadataType, + machinePreset: run.machinePreset ? machinePresetFromRun(run)?.name : undefined, }; }), pagination: { diff --git a/apps/webapp/app/presenters/v3/SpanPresenter.server.ts b/apps/webapp/app/presenters/v3/SpanPresenter.server.ts index 0c16a5cc99..7d3c219bee 100644 --- a/apps/webapp/app/presenters/v3/SpanPresenter.server.ts +++ b/apps/webapp/app/presenters/v3/SpanPresenter.server.ts @@ -8,7 +8,7 @@ import { getMaxDuration } from "@trigger.dev/core/v3/isomorphic"; import { RUNNING_STATUSES } from "~/components/runs/v3/TaskRunStatus"; import { logger } from "~/services/logger.server"; import { eventRepository, rehydrateAttribute } from "~/v3/eventRepository.server"; -import { machinePresetFromName } from "~/v3/machinePresets.server"; +import { machinePresetFromName, machinePresetFromRun } from "~/v3/machinePresets.server"; import { getTaskEventStoreTableForRun, type TaskEventStoreTable } from "~/v3/taskEventStore.server"; import { isFailedRunStatus, isFinalRunStatus } from "~/v3/taskStatus"; import { BasePresenter } from "./basePresenter.server"; @@ -269,6 +269,8 @@ export class SpanPresenter extends BasePresenter { }) : undefined; + const machine = run.machinePreset ? machinePresetFromRun(run) : undefined; + const context = { task: { id: run.taskIdentifier, @@ -307,9 +309,7 @@ export class SpanPresenter extends BasePresenter { slug: run.project.slug, name: run.project.name, }, - machine: run.machinePreset - ? machinePresetFromName(run.machinePreset as MachinePresetName) - : undefined, + machine, }; return { @@ -372,6 +372,7 @@ export class SpanPresenter extends BasePresenter { workerQueue: run.workerQueue, spanId: run.spanId, isCached: !!span.originalRun, + machinePreset: machine?.name, }; } diff --git a/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx b/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx index 2c85b0aa56..7158c57b01 100644 --- a/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx +++ b/apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.runs.$runParam.spans.$spanParam/route.tsx @@ -7,6 +7,7 @@ import { import { type LoaderFunctionArgs } from "@remix-run/server-runtime"; import { formatDurationMilliseconds, + MachinePresetName, type TaskRunError, taskRunErrorEnhancer, } from "@trigger.dev/core/v3"; @@ -18,6 +19,8 @@ import { AdminDebugRun } from "~/components/admin/debugRun"; import { CodeBlock } from "~/components/code/CodeBlock"; import { EnvironmentCombo } from "~/components/environments/EnvironmentLabel"; import { Feedback } from "~/components/Feedback"; +import { MachineLabelCombo } from "~/components/MachineLabelCombo"; +import { MachineTooltipInfo } from "~/components/MachineTooltipInfo"; import { Button, LinkButton } from "~/components/primitives/Buttons"; import { Callout } from "~/components/primitives/Callout"; import { DateTime, DateTimeAccurate } from "~/components/primitives/DateTime"; @@ -36,7 +39,6 @@ import { import { TabButton, TabContainer } from "~/components/primitives/Tabs"; import { TextLink } from "~/components/primitives/TextLink"; import { InfoIconTooltip, SimpleTooltip } from "~/components/primitives/Tooltip"; -import { RuntimeIcon } from "~/components/RuntimeIcon"; import { RunTimeline, RunTimelineEvent, SpanTimeline } from "~/components/run/RunTimeline"; import { PacketDisplay } from "~/components/runs/v3/PacketDisplay"; import { RunIcon } from "~/components/runs/v3/RunIcon"; @@ -46,6 +48,7 @@ import { SpanTitle } from "~/components/runs/v3/SpanTitle"; import { TaskRunAttemptStatusCombo } from "~/components/runs/v3/TaskRunAttemptStatus"; import { TaskRunStatusCombo, TaskRunStatusReason } from "~/components/runs/v3/TaskRunStatus"; import { WaitpointDetailTable } from "~/components/runs/v3/WaitpointDetails"; +import { RuntimeIcon } from "~/components/RuntimeIcon"; import { WarmStartCombo } from "~/components/WarmStarts"; import { useEnvironment } from "~/hooks/useEnvironment"; import { useOrganization } from "~/hooks/useOrganizations"; @@ -615,6 +618,7 @@ function RunBody({ )} + {run.schedule && ( Schedule @@ -681,6 +685,17 @@ function RunBody({ : "–"} + + + + Machine + } /> + + + + + + Run invocation cost @@ -724,12 +739,15 @@ function RunBody({ {run.engine} {isAdmin && ( - <> +
+ + Admin only + Worker queue {run.workerQueue} - +
)} diff --git a/apps/webapp/app/routes/resources.runs.$runParam.ts b/apps/webapp/app/routes/resources.runs.$runParam.ts index 7866ee9327..899dbb63f0 100644 --- a/apps/webapp/app/routes/resources.runs.$runParam.ts +++ b/apps/webapp/app/routes/resources.runs.$runParam.ts @@ -5,7 +5,7 @@ import { RUNNING_STATUSES } from "~/components/runs/v3/TaskRunStatus"; import { $replica } from "~/db.server"; import { requireUserId } from "~/services/session.server"; import { v3RunParamsSchema } from "~/utils/pathBuilder"; -import { machinePresetFromName } from "~/v3/machinePresets.server"; +import { machinePresetFromName, machinePresetFromRun } from "~/v3/machinePresets.server"; import { FINAL_ATTEMPT_STATUSES, isFinalRunStatus } from "~/v3/taskStatus"; export type RunInspectorData = UseDataFunctionReturn; @@ -183,9 +183,7 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => { slug: run.project.slug, name: run.project.name, }, - machine: run.machinePreset - ? machinePresetFromName(run.machinePreset as MachinePresetName) - : undefined, + machine: run.machinePreset ? machinePresetFromRun(run) : undefined, }; return typedjson({ diff --git a/apps/webapp/app/services/runsRepository.server.ts b/apps/webapp/app/services/runsRepository.server.ts index 156efa45e3..acc3670206 100644 --- a/apps/webapp/app/services/runsRepository.server.ts +++ b/apps/webapp/app/services/runsRepository.server.ts @@ -169,6 +169,7 @@ export class RunsRepository { batchId: true, metadata: true, metadataType: true, + machinePreset: true, }, });