Skip to content

[web-console] Add connector health UI to Performance tab#5801

Merged
Karakatiza666 merged 4 commits intomainfrom
connector-health-ui
Mar 16, 2026
Merged

[web-console] Add connector health UI to Performance tab#5801
Karakatiza666 merged 4 commits intomainfrom
connector-health-ui

Conversation

@Karakatiza666
Copy link
Copy Markdown
Contributor

Tested: manually
image
image
image

Copy link
Copy Markdown

@mythical-fred mythical-fred left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New connector health filter and unhealthy chip are useful additions, but this introduces untested behavior. See inline.

if (unhealthyConnectors.length > 0) {
filtered.set(relation, { ...data, connectors: unhealthyConnectors })
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces stateful filtering logic (healthFilter, filteredTables, filteredViews, unhealthyCount) with no tests. The hard rule for web-console: any behavior change needs tests.

numConnectorsWithProblems (systemErrors.ts) and the filtering logic here are pure functions -- easy to cover with Vitest + @testing-library/svelte. At minimum:

  • isUnhealthy: does it correctly identify Unhealthy vs other statuses?
  • filteredTables/filteredViews: does filtering by 'unhealthy' correctly exclude healthy connectors?
  • numConnectorsWithProblems: does it count unhealthy connectors in addition to error counts?

feldera_types::query::AdHocResultFormat,
feldera_types::format::json::JsonUpdateFormat,
feldera_types::format::json::JsonLines,
feldera_types::preprocess::PreprocessorConfig,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems unrelated to this PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change is required for a successful generation of OpenAPI bindings - the OpenAPI spec was referencing this new struct, but the struct itself was missing.

export type AggregatedOutputEndpointMetrics = AggregatedMetrics<
OutputEndpointMetrics,
{ io_active: boolean }
{ io_active: boolean; health?: ConnectorHealth | null }
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is the health optional because of backwards-compatibility?
In this case you could have a TODO to remove the null eventually.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is optional in the API, so reflected as such in TypeScript

) => void
} = $props()

type HealthFilter = 'all' | 'unhealthy'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the images given as part of the PR I didn't guess that there is actually a selector between "all" and "unhealthy". I don't know if there's a better way to show this visually. A combo box would work, but wouldn't make it clear that there are only two choices. Maybe a slider with two positions and one label only (all/unhealthy)?

Copy link
Copy Markdown
Contributor Author

@Karakatiza666 Karakatiza666 Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect we may have multiple different criteria we may want to filter connectors on; we have other instances of this selector UI component in the web-console: dark theme switch, selector on the Demos page, in the new Connector Errors list, and a few in mobile mode.

return count
})

const filteredTables = $derived.by(() => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would call this tablesFilteredByHealth

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, health status may be one of multiple things we may want to filter on in the future

data.connectors
.filter(isUnhealthy)
.map((c) => c.health?.description)
.filter(Boolean)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is .filter(Boolean)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It passes Boolean built-in function as a filter condition - it converts the argument value to bool based on JS's nullish-ness. In effect, this filters out empty descriptions.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know that Boolean is a built-in function, I think writing it as a lambda would be clearer

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well there are three candidates:

  1. .filter(Boolean) - we covered that; and Boolean passed as a .filter() argument implies it has to be a function
  2. .filter(v => v) - explicit lambda, concise, and still has an implicit "nullish"-check - this is the built-in JS behavior of casting values to bool
  3. .filter(v => nonNull(v) && v !== "") - fully explicit, uses nonNull helper; I can change the condition to this, but this just re-impements the nullish check.

I assume you prefer the option 3, but I would argue the intent should be expressed with the balance of conciseness and simplicity of used primitives.
So I will refactor to variant 3 here, and hope you'll find the pattern 1 reasonable in the future.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about a comment about what Boolean is?

Copy link
Copy Markdown
Contributor Author

@Karakatiza666 Karakatiza666 Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather, I'll document what Boolean filters out here:

// Filter out missing and empty descriptions to avoid large gaps in the combined text

I don't think it's meaningful to just document rather simple JS features

@Karakatiza666 Karakatiza666 force-pushed the connector-health-ui branch 4 times, most recently from 8b4086c to 8c108e5 Compare March 14, 2026 10:35
@Karakatiza666
Copy link
Copy Markdown
Contributor Author

Added unit tests for connector tables using vitest, @vitest/browser-playwright and vitest-browser-svelte

Copy link
Copy Markdown

@mythical-fred mythical-fred left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests landed. 659-line vitest-browser-svelte spec covers basic rendering, metric display, io_active indicator, all connector status icon states, multi-connector expand/collapse, error button callbacks, health chips, and the filter logic I flagged. CI runs it in a real Playwright container. LGTM.

@Karakatiza666 Karakatiza666 added this pull request to the merge queue Mar 14, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Mar 14, 2026
@Karakatiza666 Karakatiza666 force-pushed the connector-health-ui branch 2 times, most recently from 34cd71c to 9bb7e2f Compare March 16, 2026 13:18
@Karakatiza666 Karakatiza666 enabled auto-merge March 16, 2026 13:18
@Karakatiza666 Karakatiza666 added this pull request to the merge queue Mar 16, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Mar 16, 2026
@Karakatiza666 Karakatiza666 enabled auto-merge March 16, 2026 15:27
@Karakatiza666 Karakatiza666 added this pull request to the merge queue Mar 16, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Mar 16, 2026
@Karakatiza666 Karakatiza666 force-pushed the connector-health-ui branch 2 times, most recently from dad3a6f to 05b2b62 Compare March 16, 2026 17:03
@Karakatiza666 Karakatiza666 self-assigned this Mar 16, 2026
@Karakatiza666 Karakatiza666 enabled auto-merge March 16, 2026 17:06
@Karakatiza666 Karakatiza666 added this pull request to the merge queue Mar 16, 2026
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Mar 16, 2026
Signed-off-by: Karakatiza666 <bulakh.96@gmail.com>
Signed-off-by: Karakatiza666 <bulakh.96@gmail.com>
Signed-off-by: Karakatiza666 <bulakh.96@gmail.com>
Signed-off-by: Karakatiza666 <bulakh.96@gmail.com>
@Karakatiza666 Karakatiza666 enabled auto-merge March 16, 2026 19:00
@Karakatiza666 Karakatiza666 added this pull request to the merge queue Mar 16, 2026
Merged via the queue into main with commit fa52e38 Mar 16, 2026
1 check passed
@Karakatiza666 Karakatiza666 deleted the connector-health-ui branch March 16, 2026 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants