Skip to content

Service status page - #403

Merged
brucetony merged 21 commits into
developfrom
396-service-status-page
Aug 4, 2026
Merged

Service status page#403
brucetony merged 21 commits into
developfrom
396-service-status-page

Conversation

@brucetony

@brucetony brucetony commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

This PR was also used to clean up the repo including removing old/dead code and fetch methods. This includes refactoring some of the kept fetch calls to no longer be composables when called outside of the setup.

Summary by CodeRabbit

New Features

  • Added an Uptime page with selectable time ranges, auto-refresh, service summaries, heatmap status tracks, and detailed health-check drilldowns.
  • Added Uptime navigation and health-history filtering.
  • Added clear monitoring, loading, empty, latency, and failure-state indicators.

Bug Fixes

  • Improved refresh and data-store deletion error handling.
  • Increased API request timeout and improved build reliability.

Tests

  • Expanded coverage for uptime views, interactions, navigation, status handling, and data utilities.

@brucetony brucetony linked an issue Aug 3, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds service-health history contracts, uptime range utilities, a heatmap-based uptime page, toolbar controls, service cards, drilldown dialogs, navigation, and tests. It also updates typing, datastore handling, container builds, dependencies, and CI workflows.

Changes

Uptime monitoring

Layer / File(s) Summary
Health-history API contract
app/services/Api.ts, app/services/hub_adapter_swagger.json, app/composables/useAPIFetch.ts, app/plugins/api.ts
Adds service-health models, enums, settings, history schemas, the /health/services/history operation, fetch support, and a 60-second timeout.
Uptime data and chart setup
app/composables/useServiceHealth.ts, app/utils/uptime-state.ts, nuxt.config.ts, package.json, pnpm-workspace.yaml
Adds range presets, slot generation, bucket alignment, uptime classification, tooltip helpers, ECharts configuration, and dependencies.
Uptime page and interactive components
app/components/uptime/*, app/pages/uptime.vue, app/components/header/MenuHeader.vue
Adds range controls, service cards, heatmap tracks, bucket drilldowns, page orchestration, and the /uptime navigation entry.
Uptime behavior validation
test/components/uptime/*, test/composables/useServiceHealth.test.ts, test/utils/uptime-state.test.ts, test/pages/uptime.spec.ts, test/mockapi/handlers.ts
Adds fixtures, API mocks, and coverage for range handling, rendering, polling, accessibility, drilldowns, and stale responses.

Repository maintenance

Layer / File(s) Summary
Application typing and behavior
app/components/analysis/AnalysesTable.vue, app/components/table/SearchBar.vue, app/components/data-stores/*, server/routes/flame/api/auth/[...].ts, test/components/data-stores/*, test/composables/useDataStoreList.test.ts
Updates reactive status access, typed props, synchronous datastore loading, deletion error handling, authentication types, and related tests.
Build and CI workflow updates
Dockerfile, prod.Dockerfile, .github/actions/*, .github/workflows/*, tsconfig.json
Removes the Corepack override, clears .nuxt before builds, updates Node and pnpm setup, changes image workflows, and removes TypeScript path aliases.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant UptimeToolbar
  participant UptimePage
  participant useAPIFetch
  participant HealthHistoryAPI
  participant ServiceUptimeCard
  participant UptimeTrack
  participant BucketDrilldownDialog

  User->>UptimeToolbar: select range or refresh
  UptimeToolbar->>UptimePage: emit rangeChange or refresh
  UptimePage->>useAPIFetch: request service-health history
  useAPIFetch->>HealthHistoryAPI: GET /health/services/history
  HealthHistoryAPI-->>useAPIFetch: return ServiceHealthHistory
  useAPIFetch-->>UptimePage: provide history data
  UptimePage->>ServiceUptimeCard: pass service summary and slots
  ServiceUptimeCard->>UptimeTrack: render aligned buckets
  User->>UptimeTrack: click uptime cell
  UptimeTrack->>BucketDrilldownDialog: emit selected slot and bucket
  BucketDrilldownDialog->>HealthHistoryAPI: fetch raw checks for selected slice
  HealthHistoryAPI-->>BucketDrilldownDialog: return probe checks
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the primary change: adding a service status page.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 396-service-status-page

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

# Conflicts:
#	test/components/data-stores/create/DataStoreProjectInitializer.spec.ts
#	test/utils/data-store-name.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (5)
app/composables/useAPIFetch.ts (1)

56-73: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Type the opts parameter.

opts? is still inferred as any. Type it with the option type that useAPIFetch accepts so the wrapper is self-documenting and future refactorings are safer.

🛠️ Proposed typing
 export function getServiceHealthHistory(
   query: {
     start_date?: string;
     end_date?: string;
     service?: string[];
     include_checks?: boolean;
     limit?: number;
     resolution?: number;
   } = {},
-  opts?,
+  opts?: UseFetchOptions<ServiceHealthHistory>,
 ) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/composables/useAPIFetch.ts` around lines 56 - 73, Type the opts parameter
in getServiceHealthHistory using the options type accepted by useAPIFetch,
preserving its optional nature and ensuring the wrapper’s spread options remain
type-safe.
app/components/uptime/ServiceUptimeCard.vue (1)

71-71: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider dropping service from the card payload.

The card sets service to name, which is the display title (mapServiceName(name) from app/pages/uptime.vue line 130). The page then overwrites it with the raw service key at app/pages/uptime.vue line 133. The value the card emits is therefore never used, and any other consumer would receive a display title where a key is expected. Either emit the track payload unchanged, or pass the service key to the card as a separate prop.

♻️ Proposed change
-        `@cell-click`="emit('cellClick', { ...$event, service: name })"
+        `@cell-click`="emit('cellClick', $event)"

Then declare the emit payload without service and keep the page's mapping as the single source:

-const emit = defineEmits<{
-  cellClick: [
-    payload: { service: string; slot: UptimeSlot; bucket: UptimeBucket | null },
-  ];
-}>();
+const emit = defineEmits<{
+  cellClick: [payload: { slot: UptimeSlot; bucket: UptimeBucket | null }];
+}>();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/components/uptime/ServiceUptimeCard.vue` at line 71, Update the
cell-click handler in ServiceUptimeCard so it emits the track payload unchanged,
removing the locally added service field. Keep the page-level mapping in
uptime.vue as the single source for the raw service key, and adjust the event
payload declaration if needed to no longer require service.
test/components/uptime/UptimeTrack.spec.ts (1)

147-180: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reset the theme in a hook instead of at the end of each test.

setDark(false) runs as the last statement of the dark-mode tests. If an earlier assertion in the same test fails, the call never runs and the shared theme.isDark ref stays true for the following tests. A beforeEach reset makes isolation independent of assertion order.

♻️ Proposed change
 describe("UptimeTrack.vue", () => {
+  beforeEach(() => {
+    theme.isDark.value = false;
+  });
+
   it("renders one data point per slot", () => {

Then remove the trailing await setDark(false); calls, and add beforeEach to the vitest import.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/components/uptime/UptimeTrack.spec.ts` around lines 147 - 180, Update
the UptimeTrack test setup to import beforeEach from vitest and add a beforeEach
hook that resets the shared theme to light with setDark(false). Remove the
trailing await setDark(false) calls from the dark-mode tests, including “swaps
to the dark palette when the theme changes” and “separates the cells with the
surface colour of the current theme,” so cleanup runs even when assertions fail.
test/pages/uptime.spec.ts (2)

361-372: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add coverage for overlapping range requests.

No test holds two page requests open at the same time. The page assigns history from whichever response settles last, so an out-of-order response is currently undetectable by this suite. See the related comment on app/pages/uptime.vue lines 67-84.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/pages/uptime.spec.ts` around lines 361 - 372, Add a test in the uptime
page suite that starts two overlapping fetches, resolves them out of order, and
verifies the page retains the latest requested range rather than replacing
history with the stale response. Reuse the existing mockFetch, mountPage, and
page state assertions, and cover the request-ordering behavior described in the
uptime page implementation.

80-82: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Align the comment with the assertion.

The comment describes a comparison of the floored start, but this test asserts only end_date. Line 126 covers the flooring. Either assert the floored start_date here or trim the comment to the end_date claim.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/pages/uptime.spec.ts` around lines 80 - 82, Update the comment
immediately above the assertion in the uptime test so it describes only the
untouched end-date comparison, since the floored start-date behavior is already
asserted elsewhere; keep the existing end_date assertion unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/components/uptime/UptimeTrack.vue`:
- Around line 146-164: Add a keyboard-accessible control path in UptimeTrack’s
template by rendering a visually hidden, focusable button for each slot, with
keyboard activation emitting cellClick using that slot and its corresponding
bucketAt index. Keep the existing VChart pointer handler and role="img" behavior
unchanged, and ensure each button has an accessible label identifying its slot.

In `@app/pages/uptime.vue`:
- Around line 67-84: The uptime page’s load function applies stale results from
overlapping requests. In app/pages/uptime.vue lines 67-84, add a latestRequest
sequence guard, apply slots and history only for the newest request, and add
catch handling that surfaces failures; in test/pages/uptime.spec.ts lines
361-372, add coverage that keeps two requests pending, resolves them out of
order, and verifies the newest range remains displayed.

---

Nitpick comments:
In `@app/components/uptime/ServiceUptimeCard.vue`:
- Line 71: Update the cell-click handler in ServiceUptimeCard so it emits the
track payload unchanged, removing the locally added service field. Keep the
page-level mapping in uptime.vue as the single source for the raw service key,
and adjust the event payload declaration if needed to no longer require service.

In `@app/composables/useAPIFetch.ts`:
- Around line 56-73: Type the opts parameter in getServiceHealthHistory using
the options type accepted by useAPIFetch, preserving its optional nature and
ensuring the wrapper’s spread options remain type-safe.

In `@test/components/uptime/UptimeTrack.spec.ts`:
- Around line 147-180: Update the UptimeTrack test setup to import beforeEach
from vitest and add a beforeEach hook that resets the shared theme to light with
setDark(false). Remove the trailing await setDark(false) calls from the
dark-mode tests, including “swaps to the dark palette when the theme changes”
and “separates the cells with the surface colour of the current theme,” so
cleanup runs even when assertions fail.

In `@test/pages/uptime.spec.ts`:
- Around line 361-372: Add a test in the uptime page suite that starts two
overlapping fetches, resolves them out of order, and verifies the page retains
the latest requested range rather than replacing history with the stale
response. Reuse the existing mockFetch, mountPage, and page state assertions,
and cover the request-ordering behavior described in the uptime page
implementation.
- Around line 80-82: Update the comment immediately above the assertion in the
uptime test so it describes only the untouched end-date comparison, since the
floored start-date behavior is already asserted elsewhere; keep the existing
end_date assertion unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 9e3ab9f0-1eb3-43f5-81d4-76f9a9c0667d

📥 Commits

Reviewing files that changed from the base of the PR and between 0948503 and 772d82a.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (34)
  • Dockerfile
  • app/components/analysis/AnalysesTable.vue
  • app/components/header/MenuHeader.vue
  • app/components/table/SearchBar.vue
  • app/components/uptime/BucketDrilldownDialog.vue
  • app/components/uptime/ServiceUptimeCard.vue
  • app/components/uptime/UptimeToolbar.vue
  • app/components/uptime/UptimeTrack.vue
  • app/composables/useAPIFetch.ts
  • app/composables/useServiceHealth.ts
  • app/pages/uptime.vue
  • app/plugins/api.ts
  • app/services/Api.ts
  • app/services/hub_adapter_swagger.json
  • app/utils/prettify-key.ts
  • app/utils/uptime-state.ts
  • nuxt.config.ts
  • package.json
  • pnpm-workspace.yaml
  • prod.Dockerfile
  • server/routes/flame/api/auth/[...].ts
  • test/components/data-stores/create/DataStoreProjectInitializer.spec.ts
  • test/components/header/MenuHeader.spec.ts
  • test/components/uptime/BucketDrilldownDialog.spec.ts
  • test/components/uptime/ServiceUptimeCard.spec.ts
  • test/components/uptime/UptimeToolbar.spec.ts
  • test/components/uptime/UptimeTrack.spec.ts
  • test/components/uptime/constants.ts
  • test/composables/useServiceHealth.test.ts
  • test/mockapi/handlers.ts
  • test/pages/uptime.spec.ts
  • test/utils/data-store-name.test.ts
  • test/utils/uptime-state.test.ts
  • tsconfig.json

Comment on lines +146 to +164
function onChartClick(params: unknown) {
const index = slotIndexOf(params);
const slot = index === null ? undefined : props.slots[index];
if (index === null || !slot) return;

emit("cellClick", { slot, bucket: bucketAt(index) });
}
</script>

<template>
<VChart
class="uptime-track"
role="img"
:aria-label="ariaLabel"
:option="option"
autoresize
@click="onChartClick"
/>
</template>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

The bucket drilldown is reachable only with a pointer.

The track emits cellClick from the chart @click handler only. The root element uses role="img", which hides the chart contents from assistive technology, and nothing in the component is focusable or handles keyboard events. A keyboard user can read the ariaLabel summary, but cannot open the drilldown dialog for any slice.

Add a keyboard path to the same emit. One option: keep the visual chart as role="img", and render a visually hidden but focusable list of buttons, one per slot, that emit cellClick with the same payload.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/components/uptime/UptimeTrack.vue` around lines 146 - 164, Add a
keyboard-accessible control path in UptimeTrack’s template by rendering a
visually hidden, focusable button for each slot, with keyboard activation
emitting cellClick using that slot and its corresponding bucketAt index. Keep
the existing VChart pointer handler and role="img" behavior unchanged, and
ensure each button has an accessible label identifying its slot.

Comment thread app/pages/uptime.vue

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/components/uptime/BucketDrilldownDialog.vue (1)

37-39: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Invalidate pending requests before clearing the dialog state.

When visible becomes false during a pending request, this branch clears checks but does not change latestRequest. The pending request can then pass the check on Line 53 and restore old checks on Line 55. Increment the request generation and clear loading before returning.

Proposed fix
   if (!props.visible || !service || !range) {
+    latestRequest += 1;
     checks.value = [];
+    loading.value = false;
     return;
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/components/uptime/BucketDrilldownDialog.vue` around lines 37 - 39, Update
the early-return guard in the dialog’s request/state reset logic to increment
the request generation represented by latestRequest and set loading to false
before clearing checks and returning. Preserve the existing reset behavior while
ensuring pending requests cannot pass the response-generation check and restore
stale checks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@app/components/uptime/BucketDrilldownDialog.vue`:
- Around line 37-39: Update the early-return guard in the dialog’s request/state
reset logic to increment the request generation represented by latestRequest and
set loading to false before clearing checks and returning. Preserve the existing
reset behavior while ensuring pending requests cannot pass the
response-generation check and restore stale checks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c2d070d6-fb68-4889-9fa7-d590ef360f73

📥 Commits

Reviewing files that changed from the base of the PR and between 772d82a and b0991c4.

📒 Files selected for processing (23)
  • .github/actions/build-docker-image/action.yaml
  • .github/actions/setup-and-cache/action.yaml
  • .github/workflows/ci.yaml
  • .github/workflows/docker-preview.yaml
  • .github/workflows/release.yaml
  • app/components/TableRowMetadata.vue
  • app/components/analysis/ObjectDownloadButtons.vue
  • app/components/data-stores/DataStoreList.vue
  • app/components/data-stores/DetailedDataStoreTable.vue
  • app/components/table/ExpandRowButtons.vue
  • app/components/uptime/BucketDrilldownDialog.vue
  • app/composables/useAPIFetch.ts
  • app/composables/useDataStoreList.ts
  • app/pages/uptime.vue
  • app/utils/prettify-key.ts
  • nuxt.config.ts
  • test/components/data-stores/DataStoreList.spec.ts
  • test/components/data-stores/DetailedDataStoreTable.spec.ts
  • test/components/uptime/BucketDrilldownDialog.spec.ts
  • test/composables/useAPIFetch.test.ts
  • test/composables/useDataStoreList.test.ts
  • test/pages/uptime.spec.ts
  • test/utils/prettify-key.test.ts
💤 Files with no reviewable changes (6)
  • .github/workflows/docker-preview.yaml
  • test/utils/prettify-key.test.ts
  • app/utils/prettify-key.ts
  • app/components/TableRowMetadata.vue
  • app/components/table/ExpandRowButtons.vue
  • app/components/analysis/ObjectDownloadButtons.vue
🚧 Files skipped from review as they are similar to previous changes (3)
  • nuxt.config.ts
  • test/components/uptime/BucketDrilldownDialog.spec.ts
  • app/pages/uptime.vue

@brucetony
brucetony merged commit 2c2df0e into develop Aug 4, 2026
3 checks passed
@brucetony
brucetony deleted the 396-service-status-page branch August 4, 2026 05:53
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.

Service status page

1 participant