- {#if !$enterpriseLicense}
-
-
- EE only
Enterprise Edition only feature
-
- {/if}
+
+
+ Jobs that have not been specifically assigned custom tags will use a
default tags based on the language they are in or their kind.
+
+
+ {#snippet action()}
+ {#if !$enterpriseLicense}
+ Read only
+ {:else}
+
+ {/if}
+ {/snippet}
+
{#if defaultTagPerWorkspace == undefined || defaultTags == undefined}
- {:else}
-
- {#each defaultTags.sort() as tag (tag)}
-
+ {:else if !$enterpriseLicense}
+
+
+ {#each $state.snapshot(defaultTags).sort() as tag (tag)}
+ {defaultTagPerWorkspace ? `${tag}-$workspace` : tag}
{/each}
+ {:else}
+
-
+
+
+
{#if defaultTagPerWorkspace}
-
+
{#if limitToWorkspaces}
{/if}
{/if}
-
-
When tags use $workspace
, the final tag has
- $workspace
replaced with the workspace id, allowing multi-vpc setup with
- more ease, without having to assign a specific tag each time.
+
+
Job language or kind
+
+
Default tag
+
+
+
+
+ {#each $state.snapshot(defaultTags).sort() as tag (tag)}
+
+
+ {tag}
+
+
+
→
+
+ {defaultTagPerWorkspace ? `${tag}-$workspace` : tag}
+
+
+ {/each}
+
{/if}
-
+
diff --git a/frontend/src/lib/components/DropdownV2Inner.svelte b/frontend/src/lib/components/DropdownV2Inner.svelte
index bbf97a35ec..ebb12077d1 100644
--- a/frontend/src/lib/components/DropdownV2Inner.svelte
+++ b/frontend/src/lib/components/DropdownV2Inner.svelte
@@ -4,6 +4,7 @@
import { twMerge } from 'tailwind-merge'
import type { MenubarMenuElements } from '@melt-ui/svelte'
import type { Item } from '$lib/utils'
+ import { Tooltip } from './meltComponents'
interface Props {
aiId?: string
@@ -53,6 +54,13 @@
{item.displayName}
{@render item.extra?.()}
+ {#if item.tooltip}
+
+ {#snippet text()}
+ {item.tooltip}
+ {/snippet}
+
+ {/if}
{/each}
diff --git a/frontend/src/lib/components/EEOnly.svelte b/frontend/src/lib/components/EEOnly.svelte
new file mode 100644
index 0000000000..0bf54b7b68
--- /dev/null
+++ b/frontend/src/lib/components/EEOnly.svelte
@@ -0,0 +1,33 @@
+
+
+
-
- EE only {#if setting.ee_only != ''}
{setting.ee_only}{/if}
-
+
@@ -571,13 +561,17 @@
{@const currentTeam = $values['critical_error_channels'][i]?.teams_channel
? {
team_id: $values['critical_error_channels'][i]?.teams_channel?.team_id,
- team_name: $values['critical_error_channels'][i]?.teams_channel?.team_name
+ team_name:
+ $values['critical_error_channels'][i]?.teams_channel?.team_name
}
: undefined}
- {@const currentChannel = $values['critical_error_channels'][i]?.teams_channel?.channel_id
+ {@const currentChannel = $values['critical_error_channels'][i]?.teams_channel
+ ?.channel_id
? {
- channel_id: $values['critical_error_channels'][i]?.teams_channel?.channel_id,
- channel_name: $values['critical_error_channels'][i]?.teams_channel?.channel_name
+ channel_id:
+ $values['critical_error_channels'][i]?.teams_channel?.channel_id,
+ channel_name:
+ $values['critical_error_channels'][i]?.teams_channel?.channel_name
}
: undefined}
diff --git a/frontend/src/lib/components/Label.svelte b/frontend/src/lib/components/Label.svelte
index 42474e5b77..e00ee53cdc 100644
--- a/frontend/src/lib/components/Label.svelte
+++ b/frontend/src/lib/components/Label.svelte
@@ -2,6 +2,8 @@
import { twMerge } from 'tailwind-merge'
import Required from './Required.svelte'
import Tooltip from './Tooltip.svelte'
+ import { enterpriseLicense } from '$lib/stores'
+ import EEOnly from './EEOnly.svelte'
interface Props {
label?: string | undefined
@@ -12,6 +14,7 @@
class?: string | undefined
for?: string | undefined
tooltip?: string | undefined
+ eeOnly?: boolean
header?: import('svelte').Snippet
error?: import('svelte').Snippet
action?: import('svelte').Snippet
@@ -27,6 +30,7 @@
class: clazz = undefined,
for: forAttr = undefined,
tooltip = undefined,
+ eeOnly = false,
header,
error,
action,
@@ -49,6 +53,11 @@
{tooltip}
{/if}
+ {#if eeOnly}
+ {#if !$enterpriseLicense}
+
+ {/if}
+ {/if}
{@render header?.()}
{/if}
diff --git a/frontend/src/lib/components/ManageTagsDrawer.svelte b/frontend/src/lib/components/ManageTagsDrawer.svelte
new file mode 100644
index 0000000000..f6fee2fe38
--- /dev/null
+++ b/frontend/src/lib/components/ManageTagsDrawer.svelte
@@ -0,0 +1,71 @@
+
+
+
+ drawer?.closeDrawer?.()}>
+
+
+
+ Tags determine which worker group will execute a given job. Workers process only those jobs
+ whose tags match those defined in their
worker group
+ configuration.
+
+
+
+
+
+
+ {
+ if (onRefresh) {
+ onRefresh()
+ }
+ }}
+ />
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/lib/components/OccupancyBars.svelte b/frontend/src/lib/components/OccupancyBars.svelte
new file mode 100644
index 0000000000..7efbf8433e
--- /dev/null
+++ b/frontend/src/lib/components/OccupancyBars.svelte
@@ -0,0 +1,46 @@
+
+
+
+ {#each rates as rate}
+
+
+ {#if rate.value !== undefined && rate.value > 0}
+ {@const heightPercent = Math.min(rate.value * 100, 100)}
+ {@const minHeight = heightPercent > 0 && heightPercent < 3 ? 1 : heightPercent}
+
+ {/if}
+
+ {#snippet text()}
+ {rate.label}: {rate.value ? displayOccupancyRate(rate.value) : '--'}
+ {/snippet}
+
+ {/each}
+
diff --git a/frontend/src/lib/components/QueueAlerts.svelte b/frontend/src/lib/components/QueueAlerts.svelte
new file mode 100644
index 0000000000..1f147f52dd
--- /dev/null
+++ b/frontend/src/lib/components/QueueAlerts.svelte
@@ -0,0 +1,572 @@
+
+
+
+ {#snippet action()}
+ {#if $enterpriseLicense}
+
+ {#snippet trigger()}
+
+ {/snippet}
+ {#snippet content()}
+
+ {/snippet}
+
+ {/if}
+ {/snippet}
+
+ {#if !$enterpriseLicense}
+
+ Queue Metric Alerts is an enterprise feature allowing you to monitor queues for waiting jobs.
+ Please upgrade to access this functionality.
Learn more about our plans
+
+ {:else if queueAlertConfig.length === 0}
+
+
No queue alerts configured
+
Add your first alert to monitor queue conditions
+
+ {:else}
+
+
+
+
+ |
+
+ Worker Tags
+ Tags that identify which workers to monitor for this alert
+
+ |
+
+
+ Jobs Threshold
+ Trigger alert when queue exceeds this many jobs
+
+ |
+
+
+ Cooldown (s)
+ Wait time between alerts for the same condition
+
+ |
+
+
+ Time Threshold (s)
+ How long the condition must persist before alerting
+
+ |
+ Actions |
+
+
+
+ {#each queueAlertConfig as config, index}
+
+ |
+ {#if editingRowIndex === index}
+
+ {
+ if (!editForm.tags_to_monitor.includes(tag)) {
+ editForm.tags_to_monitor = [...editForm.tags_to_monitor, tag]
+ }
+ }}
+ createText="Press Enter to add custom tag"
+ placeholder="Select or create tags..."
+ class="flex-1"
+ />
+ {#if editForm.tags_to_monitor.length === 0}
+
+ {/if}
+
+ {:else}
+ {@const isExpanded = expandedTagRows.includes(index)}
+ {@const tagsToShow =
+ isExpanded || config.tags_to_monitor.length <= MAX_NUMBER_OF_TAGS_DISPLAYED
+ ? config.tags_to_monitor
+ : config.tags_to_monitor.slice(0, MAX_NUMBER_OF_TAGS_DISPLAYED)}
+
+
+ {#each tagsToShow as tag}
+
+ {tag}
+
+ {/each}
+
+ {#if config.tags_to_monitor.length > MAX_NUMBER_OF_TAGS_DISPLAYED && !isExpanded}
+ {
+ expandedTagRows = [...expandedTagRows, index]
+ }}
+ >
+ + {config.tags_to_monitor.length}
+
+ {/if}
+
+ {/if}
+ |
+
+ {#if editingRowIndex === index}
+
+ {:else}
+ {config.jobs_num_threshold}
+ {/if}
+ |
+
+ {#if editingRowIndex === index}
+
+ {:else}
+ {config.alert_cooldown_seconds}
+ {/if}
+ |
+
+ {#if editingRowIndex === index}
+
+ {:else}
+ {config.alert_time_threshold_seconds}
+ {/if}
+ |
+
+ {#if editingRowIndex === index}
+
+
+
+
+ {:else}
+
+
+
+
+ {/if}
+ |
+
+ {/each}
+
+
+
+ {/if}
+
diff --git a/frontend/src/lib/components/QueueMetricsDrawer.svelte b/frontend/src/lib/components/QueueMetricsDrawer.svelte
index dd4ad426fa..4b05c41899 100644
--- a/frontend/src/lib/components/QueueMetricsDrawer.svelte
+++ b/frontend/src/lib/components/QueueMetricsDrawer.svelte
@@ -1,423 +1,26 @@
-
+
-
- {#if $enterpriseLicense}
- {#if changesMade}
- Non applied changes
- {/if}
-
-
-
-
+
- {#if alerts.length > 0}
-
- {/if}
+
-
-
- {:else}
-
- Queue Metric Alerts are an enterprise feature allowing you to monitor queues for waiting
- jobs. Please upgrade to access this functionality.
- Learn more about our plans.
-
- {/if}
-
- Queue Metrics
-
-
-
+
+
+
diff --git a/frontend/src/lib/components/QueueMetricsDrawerInner.svelte b/frontend/src/lib/components/QueueMetricsDrawerInner.svelte
index 76e0b0c72b..f6cc720b88 100644
--- a/frontend/src/lib/components/QueueMetricsDrawerInner.svelte
+++ b/frontend/src/lib/components/QueueMetricsDrawerInner.svelte
@@ -20,6 +20,7 @@
import Skeleton from './common/skeleton/Skeleton.svelte'
import DarkModeObserver from './DarkModeObserver.svelte'
import Alert from './common/alert/Alert.svelte'
+ import { Section } from './common'
let loading: boolean = true
@@ -186,87 +187,89 @@
-{#if loading}
-
-{:else if noMetrics}
- No jobs delayed by more than 3 seconds in the last 14 days
-{:else}
-
- {#if countData}
-
3s)'
- }
- },
- scales: {
- x: {
- type: 'time',
- min: minDate.toISOString(),
- max: new Date().toISOString()
- },
- y: {
+
+ {#if loading}
+
+ {:else if noMetrics}
+ No jobs delayed by more than 3 seconds in the last 14 days
+ {:else}
+
+ {#if countData}
+
3s)'
}
- }
- }
- }}
- />
- {/if}
- {#if delayData}
- 3s)'
},
- tooltip: {
- callbacks: {
- label: function (context) {
- // @ts-ignore
- if (context.raw.y === 1) {
- return context.dataset.label + ': 0'
- } else {
- // @ts-ignore
- return context.dataset.label + ': ' + context.raw.y
- }
+ scales: {
+ x: {
+ type: 'time',
+ min: minDate.toISOString(),
+ max: new Date().toISOString()
+ },
+ y: {
+ title: {
+ display: true,
+ text: 'count'
}
}
}
- },
- scales: {
- x: {
- type: 'time',
- min: minDate.toISOString(),
- max: new Date().toISOString()
- },
-
- y: {
- type: 'logarithmic',
+ }}
+ />
+ {/if}
+ {#if delayData}
+ 3s)'
},
- ticks: {
- callback: (value, _) => (value === 1 ? '0' : value)
+ tooltip: {
+ callbacks: {
+ label: function (context) {
+ // @ts-ignore
+ if (context.raw.y === 1) {
+ return context.dataset.label + ': 0'
+ } else {
+ // @ts-ignore
+ return context.dataset.label + ': ' + context.raw.y
+ }
+ }
+ }
+ }
+ },
+ scales: {
+ x: {
+ type: 'time',
+ min: minDate.toISOString(),
+ max: new Date().toISOString()
+ },
+
+ y: {
+ type: 'logarithmic',
+ title: {
+ display: true,
+ text: 'delay (s)'
+ },
+ ticks: {
+ callback: (value, _) => (value === 1 ? '0' : value)
+ }
}
}
- }
- }}
- />
- {/if}
-
- Only tags for jobs that have been delayed by more than 3 seconds in the last 14 days are
- included in the graph.
-
-
-{/if}
+ }}
+ />
+ {/if}
+
+ Only tags for jobs that have been delayed by more than 3 seconds in the last 14 days are
+ included in the graph.
+
+
+ {/if}
+
diff --git a/frontend/src/lib/components/ScriptBuilder.svelte b/frontend/src/lib/components/ScriptBuilder.svelte
index fd2326cb23..8d2b022e3b 100644
--- a/frontend/src/lib/components/ScriptBuilder.svelte
+++ b/frontend/src/lib/components/ScriptBuilder.svelte
@@ -12,7 +12,7 @@
PostgresTriggerService,
CaptureService,
type ScriptLang,
- WorkerService,
+ WorkerService
} from '$lib/gen'
import { inferArgs } from '$lib/infer'
import {
@@ -189,7 +189,7 @@
: undefined
)
const simplifiedPoll = writable(false)
-
+
export function setPrimarySchedule(schedule: ScheduleTrigger | undefined | false) {
primaryScheduleStore.set(schedule)
loadTriggers()
@@ -1046,7 +1046,7 @@
{#snippet content()}
-
+
{#snippet action()}
{#if customUi?.settingsPanel?.metadata?.disableMute !== true}
@@ -1214,7 +1214,7 @@
-
{#if $enterpriseLicense && initialPath != ''}
diff --git a/frontend/src/lib/components/ScriptEditor.svelte b/frontend/src/lib/components/ScriptEditor.svelte
index e77d91ca63..d042f3ec03 100644
--- a/frontend/src/lib/components/ScriptEditor.svelte
+++ b/frontend/src/lib/components/ScriptEditor.svelte
@@ -23,7 +23,7 @@
import Modal from './common/modal/Modal.svelte'
import DiffEditor from './DiffEditor.svelte'
import {
- Clipboard,
+ Copy,
CornerDownLeft,
ExternalLink,
Github,
@@ -556,7 +556,7 @@