diff --git a/.gitignore b/.gitignore index 2363727be2..d7ab25f22b 100644 --- a/.gitignore +++ b/.gitignore @@ -28,4 +28,4 @@ go.work.sum .claude/* !.claude/skills/ .sisyphus/* -.omc \ No newline at end of file +.omc diff --git a/src/lib/components/lines-and-dots/workflow-details.svelte b/src/lib/components/lines-and-dots/workflow-details.svelte index c5c7e03698..9845877538 100644 --- a/src/lib/components/lines-and-dots/workflow-details.svelte +++ b/src/lib/components/lines-and-dots/workflow-details.svelte @@ -6,7 +6,7 @@ import { translate } from '$lib/i18n/translate'; import { fetchWorkflow } from '$lib/services/workflow-service'; import { isCloud } from '$lib/stores/advanced-visibility'; - import { fullEventHistory } from '$lib/stores/events'; + import { fullEventHistory, sdkInfo } from '$lib/stores/events'; import { relativeTime, timeFormat, @@ -19,8 +19,6 @@ formatDuration, } from '$lib/utilities/format-time'; import { getBuildIdFromVersion } from '$lib/utilities/get-deployment-build-id'; - import { getSDKandVersion } from '$lib/utilities/get-sdk-version'; - import { isWorkflowTaskCompletedEvent } from '$lib/utilities/is-event-type'; import { routeForSchedule, routeForTaskQueue, @@ -81,16 +79,12 @@ ], ); let totalActions = $derived( - $fullEventHistory.reduce((acc, e) => e.billableActions + acc, 0).toString(), + $fullEventHistory + .reduce((acc, e) => (e?.billableActions ?? 0) + acc, 0) + .toString(), ); - const workflowCompletedTasks = $derived( - $fullEventHistory.filter(isWorkflowTaskCompletedEvent), - ); - - const { sdk, version: sdkVersion } = $derived( - getSDKandVersion(workflowCompletedTasks), - ); + const { sdk, version: sdkVersion } = $derived($sdkInfo); const fetchLatestRun = async () => { const result = await fetchWorkflow({ @@ -166,18 +160,20 @@ href={routeForWorkflowsWithQuery({ namespace, query: `WorkflowType="${workflow?.name}"`, - })} + }) ?? ''} iconName="filter" /> - {translate('common.task-queue')} - + {#if workflow?.taskQueue} + {translate('common.task-queue')} + + {/if} {#if workflow?.priority} {@const { priorityKey, fairnessKey } = workflow.priority} @@ -214,11 +210,11 @@ copyableText={versioningBuildId} text={versioningBuildId} href={deploymentVersion - ? routeForWorkflowsWithQuery({ + ? (routeForWorkflowsWithQuery({ namespace, query: `TemporalWorkerDeploymentVersion="${deploymentVersion}"`, - }) - : undefined} + }) ?? '') + : ''} iconName={deploymentVersion ? 'filter' : undefined} /> {/if} @@ -234,7 +230,7 @@ href={routeForWorkflowsWithQuery({ namespace, query: `TemporalWorkflowVersioningBehavior="${versioningBehavior}"`, - })} + }) ?? ''} iconName="filter" /> {/if} @@ -252,15 +248,15 @@ })} /> {/if} - {#if parent} + {#if parent?.workflowId && parent?.runId} {translate('workflows.parent-workflow')} {/if} @@ -305,7 +301,7 @@ {/if} {#if sdk && sdkVersion} - SDK + {translate('workflows.sdk')} diff --git a/src/lib/components/shared-search-attribute-filter/filter-bar.svelte b/src/lib/components/shared-search-attribute-filter/filter-bar.svelte new file mode 100644 index 0000000000..f1d5dd0e85 --- /dev/null +++ b/src/lib/components/shared-search-attribute-filter/filter-bar.svelte @@ -0,0 +1,56 @@ + + +
+
+
+ + +
+
+ +
+
+ {#if viewManualQuery} + + {/if} +
diff --git a/src/lib/components/shared-search-attribute-filter/filter-list.svelte b/src/lib/components/shared-search-attribute-filter/filter-list.svelte new file mode 100644 index 0000000000..e36bbb5a70 --- /dev/null +++ b/src/lib/components/shared-search-attribute-filter/filter-list.svelte @@ -0,0 +1,131 @@ + + +{#if visibleFilters.length > 0} +
+ {#each visibleFilters as filterItem, i (filterItem.id)} + {#if statusAttribute && isStatusFilter(filterItem) && i === firstExecutionStatusIndex} + + updateStatusFilters(i, updatedStatusFilters)} + /> + {:else if !isStatusFilter(filterItem) && filterItem.attribute} + updateFilter(i, updatedFilter)} + onRemove={() => removeFilter(i)} + /> + {/if} + {/each} + + {#if hasMoreFilters} + + {/if} +
+{/if} diff --git a/src/lib/components/standalone-activities/activities-summary-filter-bar/filter.svelte b/src/lib/components/shared-search-attribute-filter/filter.svelte similarity index 55% rename from src/lib/components/standalone-activities/activities-summary-filter-bar/filter.svelte rename to src/lib/components/shared-search-attribute-filter/filter.svelte index 2b85cb82d4..1ad792ac2d 100644 --- a/src/lib/components/standalone-activities/activities-summary-filter-bar/filter.svelte +++ b/src/lib/components/shared-search-attribute-filter/filter.svelte @@ -1,29 +1,45 @@
- - + +
diff --git a/src/lib/components/standalone-activities/activities-summary-filter-bar/manual-query.svelte b/src/lib/components/shared-search-attribute-filter/manual-query.svelte similarity index 75% rename from src/lib/components/standalone-activities/activities-summary-filter-bar/manual-query.svelte rename to src/lib/components/shared-search-attribute-filter/manual-query.svelte index 1221aa6f23..701649a394 100644 --- a/src/lib/components/standalone-activities/activities-summary-filter-bar/manual-query.svelte +++ b/src/lib/components/shared-search-attribute-filter/manual-query.svelte @@ -1,4 +1,5 @@
-
-{/if} diff --git a/src/lib/components/standalone-activities/activities-summary-filter-bar/filter-bar.svelte b/src/lib/components/standalone-activities/activities-summary-filter-bar/filter-bar.svelte index d46b7a3e58..c0677a53de 100644 --- a/src/lib/components/standalone-activities/activities-summary-filter-bar/filter-bar.svelte +++ b/src/lib/components/standalone-activities/activities-summary-filter-bar/filter-bar.svelte @@ -1,40 +1,19 @@ -{#snippet actionToggleButtons()} -
- -
-{/snippet} - -
-
-
- - -
- {@render actionToggleButtons()} -
- {#if viewManualQuery} - - {/if} -
+ diff --git a/src/lib/components/standalone-activities/standalone-activities-disabled.svelte b/src/lib/components/standalone-activities/standalone-activities-disabled.svelte index 838cf7b673..71d3a71648 100644 --- a/src/lib/components/standalone-activities/standalone-activities-disabled.svelte +++ b/src/lib/components/standalone-activities/standalone-activities-disabled.svelte @@ -36,6 +36,7 @@ activity.enableStandalone:

{translate('standalone-activities.standalone-activities-enablement')}

diff --git a/src/lib/components/worker-table.svelte b/src/lib/components/worker-table.svelte index 52737720ca..2af0455b96 100644 --- a/src/lib/components/worker-table.svelte +++ b/src/lib/components/worker-table.svelte @@ -178,7 +178,7 @@ {:else} - + {/each} diff --git a/src/lib/components/workers/no-workers-polling-alert.svelte b/src/lib/components/workers/no-workers-polling-alert.svelte new file mode 100644 index 0000000000..691d68ce66 --- /dev/null +++ b/src/lib/components/workers/no-workers-polling-alert.svelte @@ -0,0 +1,32 @@ + + + diff --git a/src/lib/components/workers/worker-details/skeleton.svelte b/src/lib/components/workers/worker-details/skeleton.svelte new file mode 100644 index 0000000000..20ec1912c0 --- /dev/null +++ b/src/lib/components/workers/worker-details/skeleton.svelte @@ -0,0 +1,122 @@ + + +
+ {@render breadcrumb()} + + +
+ +
+
+ + +
+ +
+ {#each Array(3) as _, i (i)} +
+ + + + +
+ {/each} +
+ +
+
+ {#each Array(4) as _, i (i)} + + +
+
+ + + + +
+
+ + +
+
+ + + +
+
+
+ {/each} +
+ + +
+
diff --git a/src/lib/components/workers/worker-details/worker-details.svelte b/src/lib/components/workers/worker-details/worker-details.svelte new file mode 100644 index 0000000000..a0b542f6a8 --- /dev/null +++ b/src/lib/components/workers/worker-details/worker-details.svelte @@ -0,0 +1,419 @@ + + +
+ {@render breadcrumb()} + {#if heartbeat?.workerInstanceKey} + + {heartbeat.workerInstanceKey} + {/if} +
+ +
+
+ +

+ +

+
+ + + + {translate('workflows.last-heartbeat')} + + {translate('common.start')} + + + + + {#if heartbeat?.taskQueue} + {translate('common.task-queue')} + + {/if} + {translate('workers.sdk')} + + + + + + + {translate('deployments.build-id')} + + {translate('deployments.deployment')} + + + + +
+
+ {@render taskSlotCard( + translate('common.workflows-plural', { count: 1 }), + heartbeat?.workflowTaskSlotsInfo, + heartbeat?.workflowPollerInfo, + )} + {@render taskSlotCard( + translate('common.activities-plural', { count: 1 }), + heartbeat?.activityTaskSlotsInfo, + heartbeat?.activityPollerInfo, + )} + {@render taskSlotCard( + translate('workers.nexus-tasks'), + heartbeat?.nexusTaskSlotsInfo, + heartbeat?.nexusPollerInfo, + )} + {@render taskSlotCard( + translate('workers.local-activities'), + heartbeat?.localActivitySlotsInfo, + null, + )} +
+ + +
+
+ +{#snippet taskSlotCard( + title: string, + slots: WorkerSlotsInfo | null | undefined, + poller: WorkerPollerInfo | null | undefined, +)} + +
+

{title}

+ {#if slots?.slotSupplierKind} + {slots.slotSupplierKind} + {/if} +
+ +
+
+
+ {translate('workers.slots')} +
+
+
+

+ {slots?.currentUsedSlots ?? 0} +

+

+ {#if slots?.currentAvailableSlots} + {slots.currentAvailableSlots - (slots?.currentUsedSlots ?? 0)} + {:else} + - + {/if} +

+
+
+

{translate('workers.used')}

+

+ {#if slots?.currentAvailableSlots} + {translate('workers.available-out-of', { + count: slots.currentAvailableSlots, + })} + {:else} + {translate('workers.none-available')} + {/if} +

+
+
+ {@render meterBar( + `slots-${title}`, + slots?.currentUsedSlots ?? 0, + slots?.currentAvailableSlots + ? slots.currentAvailableSlots + : (slots?.currentUsedSlots ?? 0), + )} +
+ +
+
+ {translate('workers.tasks-processed')} +
+
+ {(slots?.totalProcessedTasks ?? 0).toLocaleString()} +
+
+ + {#if poller} +
+
+ {translate('workers.poller')} + + {poller.isAutoscaling ? 'Autoscaling' : 'Manual'} + +
+
+

+ {poller.currentPollers ?? 0} +

+

+ {#if poller.lastSuccessfulPollTime} + {translate('workers.last-poll')} + + {:else} + {translate('workers.no-activity')} + {/if} +

+
+
+ {/if} +
+
+{/snippet} + +{#snippet meterBar(labelledby: string, value: number, maxValue: number = 100)} +
+
+
+{/snippet} + +{#snippet goDependencyWarning()} + +

{translate('workers.go-dependency-warning-description')}

+ + +
+{/snippet} + +{#snippet hostUsage()} + +
+
+ + + {translate('workers.cpu-usage')} + + {heartbeat?.hostInfo?.currentHostCpuUsage?.toFixed(0) ?? '0'}% +
+ {@render meterBar( + 'cpu-label', + heartbeat?.hostInfo?.currentHostCpuUsage ?? 0, + )} +
+
+
+ + + {translate('workers.memory-usage')} + + {heartbeat?.hostInfo?.currentHostMemUsage?.toFixed(0) ?? '0'}% +
+ {@render meterBar( + 'memory-label', + heartbeat?.hostInfo?.currentHostMemUsage ?? 0, + )} +
+ {#if goDependencyPotentiallyMissing} + {@render goDependencyWarning()} + {/if} +
+{/snippet} + +{#snippet hostInfo()} +
+ +

+ {translate('workers.host-info')} +

+
+
{translate('workers.host-name')}
+
{heartbeat?.hostInfo?.hostName ?? '-'}
+ +
{translate('workers.process-id')}
+
{heartbeat?.hostInfo?.processId ?? '-'}
+ +
+ {translate('workers.worker-grouping')} +
+
+ {heartbeat?.hostInfo?.workerGroupingKey ?? '-'} +
+
+
+ {@render hostUsage()} +
+{/snippet} + +{#snippet workflowCache()} + +

+ {translate('workers.workflow-cache')} +

+
+
+
+ {currentStickyCacheSize.toLocaleString()} +
+
+ {translate('workers.cache-size')} +
+
+
+
+ {cacheHitRate}% +
+
+ {translate('workers.cache-hits')} +
+
+
+
+{/snippet} + +{#snippet diagnostics()} + +

+ {translate('workers.diagnostics')} +

+
+
{pollSuccessRate}%
+
+ {translate('workers.poll-success-rate')} +
+
+
+{/snippet} diff --git a/src/lib/components/workers/worker-heartbeats-disabled.svelte b/src/lib/components/workers/worker-heartbeats-disabled.svelte new file mode 100644 index 0000000000..61dce95d99 --- /dev/null +++ b/src/lib/components/workers/worker-heartbeats-disabled.svelte @@ -0,0 +1,18 @@ + + + +
+

{translate('workers.worker-heartbeats-enablement')}

+ +
diff --git a/src/lib/components/workers/worker-status.svelte b/src/lib/components/workers/worker-status.svelte new file mode 100644 index 0000000000..d35e9d1490 --- /dev/null +++ b/src/lib/components/workers/worker-status.svelte @@ -0,0 +1,46 @@ + + +
+ + {label[status]} + {#if isRunning} + + {/if} + +
diff --git a/src/lib/components/workers/workers-table/task-queue-workers-table.svelte b/src/lib/components/workers/workers-table/task-queue-workers-table.svelte new file mode 100644 index 0000000000..94c8fcb234 --- /dev/null +++ b/src/lib/components/workers/workers-table/task-queue-workers-table.svelte @@ -0,0 +1,50 @@ + + +{#snippet fallback()} + {#await getPollers({ queue: taskQueue, namespace })} + + + {:then workers} + + {:catch error} + + {/await} +{/snippet} + +{#if useFallback} + {@render fallback()} +{:else} + +{/if} diff --git a/src/lib/components/workers/workers-table/worker-heartbeats-sdk-alert.svelte b/src/lib/components/workers/workers-table/worker-heartbeats-sdk-alert.svelte new file mode 100644 index 0000000000..40305289ce --- /dev/null +++ b/src/lib/components/workers/workers-table/worker-heartbeats-sdk-alert.svelte @@ -0,0 +1,64 @@ + + + +
+ {#if currentSdk} + {@const { href, sdk, version } = currentSdk} +

+ {translate('workers.worker-heartbeats-sdk-link-preface')} + + + + {translate('workers.worker-heartbeats-sdk-link-postface')} +

+ {:else} +

{translate('workers.worker-heartbeats-sdk-list-preface')}

+ {#each supportedVersions as { href, sdk, version } (`${sdk}:${version}`)} + + + + {/each} + {/if} +
+
diff --git a/src/lib/components/workers/workers-table/workers-table-cell.svelte b/src/lib/components/workers/workers-table/workers-table-cell.svelte new file mode 100644 index 0000000000..956da88701 --- /dev/null +++ b/src/lib/components/workers/workers-table/workers-table-cell.svelte @@ -0,0 +1,115 @@ + + + + {#if attribute === 'BuildId' || attribute === 'WorkerInstanceKey'} + {#if href} + + {truncate(value)} + + {:else} + + {truncate(value)} + + {/if} + {:else if href} + {value} + {:else if children} + {@render children?.()} + {:else} + {value} + {/if} + {#if value} + + {/if} + diff --git a/src/lib/components/workers/workers-table/workers-table-row.svelte b/src/lib/components/workers/workers-table/workers-table-row.svelte new file mode 100644 index 0000000000..81156eedfb --- /dev/null +++ b/src/lib/components/workers/workers-table/workers-table-row.svelte @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + diff --git a/src/lib/components/workers/workers-table/workers-table.svelte b/src/lib/components/workers/workers-table/workers-table.svelte new file mode 100644 index 0000000000..2cb318a1c5 --- /dev/null +++ b/src/lib/components/workers/workers-table/workers-table.svelte @@ -0,0 +1,74 @@ + + + + + {translate('workers.workers')} + + + + {#each columns as { label } (label)} + {label} + {/each} + + {#each visibleItems as worker, i (worker.workerHeartbeat?.workerInstanceKey ?? i)} + + {/each} + + + {#if hasQuery || runningWithNoWorkers} + + {:else} +
+ +
+ {/if} +
+
diff --git a/src/lib/components/workflow/filter-bar/dropdown-filter-chip.svelte b/src/lib/components/workflow/filter-bar/dropdown-filter-chip.svelte index 1f1a7b2e24..8ef5b5ab4f 100644 --- a/src/lib/components/workflow/filter-bar/dropdown-filter-chip.svelte +++ b/src/lib/components/workflow/filter-bar/dropdown-filter-chip.svelte @@ -55,7 +55,7 @@ onUpdate: (updatedFilter: SearchAttributeFilter) => void; onRemove: () => void; index?: number; - openIndex?: number; + openIndex?: number | null; }; let { @@ -179,7 +179,7 @@ } if (isDateTimeFilter(filter)) { - if (filter.customDate) return value.split('BETWEEN')[1]; + if (filter.customDate) return value?.split('BETWEEN')[1]; return $timestamp(value, { format: 'short' }); } @@ -190,7 +190,7 @@ return value; } - function applyChanges(e) { + function applyChanges(e: SubmitEvent) { e.preventDefault(); if (isInConditional(localFilter.conditional)) { diff --git a/src/lib/components/workflow/workflow-call-stack-error.svelte b/src/lib/components/workflow/workflow-call-stack-error.svelte deleted file mode 100644 index 9cb6992968..0000000000 --- a/src/lib/components/workflow/workflow-call-stack-error.svelte +++ /dev/null @@ -1,27 +0,0 @@ - - -{#if runningWithNoWorkers} -
- - {translate('workflows.workflow-error-no-workers-description', { - taskQueue: workflow?.taskQueue ?? '', - })} - -
-{/if} diff --git a/src/lib/components/workflow/workflow-summary.svelte b/src/lib/components/workflow/workflow-summary.svelte index 6c69b7135e..5f04a912d7 100644 --- a/src/lib/components/workflow/workflow-summary.svelte +++ b/src/lib/components/workflow/workflow-summary.svelte @@ -10,7 +10,7 @@ workflowSummaryViewOpen, } from '$lib/stores/workflow-run'; import { formatDistanceAbbreviated } from '$lib/utilities/format-time'; - import { routeForWorkers } from '$lib/utilities/route-for'; + import { routeForWorkflowWorkers } from '$lib/utilities/route-for'; $: ({ workflow } = $workflowRun); $: elapsedTime = formatDistanceAbbreviated({ @@ -40,19 +40,19 @@
@@ -60,19 +60,21 @@

{translate('common.task-queue')}

- + {#if workflow?.taskQueue} + + {/if}
diff --git a/src/lib/holocene/badge.svelte b/src/lib/holocene/badge.svelte index 949160f488..11f8744a52 100644 --- a/src/lib/holocene/badge.svelte +++ b/src/lib/holocene/badge.svelte @@ -12,6 +12,7 @@ danger: 'bg-red-200', count: 'h-6 w-6 min-w-max rounded-full bg-blue-300', subtle: 'surface-subtle dark:text-white font-normal select-all', + ghost: 'surface-primary text-primary border border-subtle', }; const types = cva( diff --git a/src/lib/holocene/filter-or-copy-buttons.svelte b/src/lib/holocene/filter-or-copy-buttons.svelte index c5c7d5b774..f43fcc977c 100644 --- a/src/lib/holocene/filter-or-copy-buttons.svelte +++ b/src/lib/holocene/filter-or-copy-buttons.svelte @@ -52,11 +52,11 @@