Skip to content

fix: use healthcheck self_check_result for database status color#3837

Merged
astandrik merged 8 commits intomainfrom
copilot/use-healthcheck-response-for-status
Apr 27, 2026
Merged

fix: use healthcheck self_check_result for database status color#3837
astandrik merged 8 commits intomainfrom
copilot/use-healthcheck-response-for-status

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 24, 2026

On the database page the status indicator next to the database name was driven by tenantinfo.Overall. Switch it to the healthcheck response so the color reflects the same signal surfaced by the healthcheck drawer/preview, while preserving the existing StatusFlagEFlag color mapper already present in the project.

Changes

  • TenantOverview — subscribes to healthcheckApi.useGetHealthcheckInfoQuery and reads healthcheckData.self_check_result. Before passing the value to EntityStatus, it now converts SelfCheckResult to StatusFlag, then reuses the existing hcStatusToColorFlag mapper. Falls back to tenant.Overall when healthcheck data is absent (Serverless, loading, or error), so behavior is unchanged in those cases.
  • selfCheckResultToHcStatus — added in store/reducers/healthcheckInfo/utils.ts to normalize SelfCheckResult to StatusFlag using backend-compatible semantics:
    • GOOD → GREEN
    • DEGRADED → YELLOW
    • MAINTENANCE_REQUIRED → RED
    • EMERGENCY → RED
    • UNSPECIFIED → GREY
  • hcStatusToColorFlag — kept as Record<StatusFlag, EFlag> only; it is no longer extended with SelfCheckResult keys.
  • The query is skipped when the database is Serverless, when V2 navigation is enabled (the badge isn't rendered in that mode), or before tenant info has loaded — avoiding spurious requests. Polling is delegated to the existing HealthcheckPreview subscription, which shares the same RTK Query cache key, so this subscription does not alter polling frequency or load.
  • A nullish check plus ?? Overall ensures that a missing mapping key cleanly falls back to tenant.Overall rather than passing undefined to EntityStatus.
const {currentData: healthcheckData} = healthcheckApi.useGetHealthcheckInfoQuery(
    {database},
    {skip: isServerless || isV2NavigationEnabled || tenant === undefined},
);
const selfCheckResult = healthcheckData?.self_check_result;
const healthcheckStatus =
    selfCheckResult === undefined ? undefined : selfCheckResultToHcStatus[selfCheckResult];
const databaseStatus =
    healthcheckStatus === undefined
        ? Overall
        : (hcStatusToColorFlag[healthcheckStatus] ?? Overall);

<EntityStatus status={databaseStatus} name={Name || TENANT_DEFAULT_TITLE} ... />

Important Files Changed

Filename Overview
src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx Adds a healthcheck query (skipped for Serverless, V2 navigation, or unloaded tenant) and routes self_check_result through SelfCheckResult -> StatusFlag -> EFlag before rendering EntityStatus; falls back to tenant.Overall when data is absent.
src/store/reducers/healthcheckInfo/utils.ts Keeps hcStatusToColorFlag scoped to StatusFlag only and adds selfCheckResultToHcStatus to normalize healthcheck self_check_result values to backend-compatible StatusFlag values.

Greptile Summary

The PR aligns the database status badge color in TenantOverview with the healthcheck drawer by reading healthcheckData?.self_check_result instead of tenant.Overall. It now normalizes SelfCheckResult to StatusFlag first, then reuses the existing hcStatusToColorFlag mapping, preserving the original mapper responsibilities and matching backend cluster-state semantics. Skip conditions (isServerless, isV2NavigationEnabled, tenant === undefined) are correctly applied, and RTK Query deduplicates this subscription against HealthcheckPreview's polling subscription so no extra network requests are introduced.

Confidence Score: 5/5

Safe to merge — logic is correct, fallback is solid, skip conditions are properly guarded, and the final status semantics now match backend behavior.

No P0 or P1 issues found. The RTK Query cache deduplication with HealthcheckPreview works as intended, and the final implementation avoids duplicating SelfCheckResult -> EFlag color mapping logic.

No files require special attention.

Important Files Changed

Filename Overview
src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx Adds healthcheck query subscription with correct skip conditions; derives database status from self_check_result via StatusFlag with safe fallback to Overall
src/store/reducers/healthcheckInfo/utils.ts Restores hcStatusToColorFlag to StatusFlag -> EFlag only and adds selfCheckResultToHcStatus for backend-compatible normalization

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[TenantOverview mounts] --> B{skip conditions}
    B -->|isServerless OR\nisV2NavigationEnabled OR\ntenant === undefined| C[Skip healthcheck query\nfallback: databaseStatus = Overall]
    B -->|none| D[useGetHealthcheckInfoQuery\ndatabase]
    D --> E{RTK Query cache hit?}
    E -->|yes - HealthcheckPreview\nshares same key| F[Return cached data\nno extra network req]
    E -->|no| G[Network request]
    G --> F
    F --> H{self_check_result\ndefined?}
    H -->|undefined| C
    H -->|defined| I[selfCheckResultToHcStatus\nSelfCheckResult to StatusFlag]
    I --> J[hcStatusToColorFlag\nStatusFlag to EFlag]
    J --> K{mapping found?}
    K -->|yes| L[databaseStatus = EFlag]
    K -->|no, fallback via ??| C
    C --> M[EntityStatus with databaseStatus]
    L --> M
Loading

Reviews (5): Last reviewed commit: "fix: convert self check result through status flag" | Re-trigger Greptile

CI Results

Test Status: ⚠️ FLAKY

📊 Full Report

Total Passed Failed Flaky Skipped
634 630 0 1 3

😟 No changes in tests. 😕

Bundle Size: ✅

Current: 63.46 MB | Main: 63.46 MB
Diff: +2.35 KB (0.00%)

✅ Bundle size unchanged.

ℹ️ CI Information
  • Test recordings for failed tests are available in the full report.
  • Bundle size is measured for the entire 'dist' directory.
  • 📊 indicates links to detailed reports.
  • 🔺 indicates increase, 🔽 decrease, and ✅ no change in bundle size.

Copilot AI changed the title [WIP] Update database status color using healthcheck response Use healthcheck self_check_result for database status color Apr 24, 2026
Copilot AI requested a review from adameat April 24, 2026 11:43
@adameat
Copy link
Copy Markdown
Member

adameat commented Apr 24, 2026

@copilot no, you shouldn't add a new mapping from healthcheck status to color. it's already exists in the project, look for it.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 24, 2026

@copilot no, you shouldn't add a new mapping from healthcheck status to color. it's already exists in the project, look for it.

Removed the new selfCheckResultToColorFlag mapping. Now using the existing hcStatusToColorFlag (StatusFlag → EFlag) with healthcheckData.database_status[0].overall from the healthcheck response. Done in 3d6db51.

Copilot AI changed the title Use healthcheck self_check_result for database status color Use healthcheck database_status for database status color Apr 24, 2026
@adameat adameat marked this pull request as ready for review April 24, 2026 11:51
Copilot AI review requested due to automatic review settings April 24, 2026 11:51
Comment thread src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx
Comment thread src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR updates the database status indicator on the Tenant diagnostics overview to derive its color from the healthcheck database_status signal (when available), aligning it with the healthcheck drawer/preview.

Changes:

  • Subscribe to healthcheckApi.useGetHealthcheckInfoQuery in TenantOverview (skipped for Serverless).
  • Map healthcheckData.database_status[0].overall (StatusFlag) to EntityStatus’s expected EFlag using hcStatusToColorFlag.
  • Fall back to tenantinfo.Overall when healthcheck data isn’t available.

Comment thread src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx Outdated
Comment thread src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx Outdated
@adameat
Copy link
Copy Markdown
Member

adameat commented Apr 27, 2026

@copilot review the comments and fix them. also fix the PR title

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 27, 2026

@copilot review the comments and fix them. also fix the PR title

Addressed all reviewer comments in 0348cac:

  • Skip healthcheck when isV2NavigationEnabled (badge not rendered) and tenant === undefined (avoid spurious request before Type is known).
  • Use === undefined check with hcStatusToColorFlag[...] ?? Overall so falsy/missing values fall back cleanly to tenant.Overall.
  • Dropped the local pollingInterval; HealthcheckPreview already polls the deduped cache key, so this subscription no longer alters polling load.

PR title updated to "Use healthcheck database_status for database status color".

Copilot AI requested a review from adameat April 27, 2026 04:33
Comment thread src/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx Outdated
@adameat
Copy link
Copy Markdown
Member

adameat commented Apr 27, 2026

@copilot here is example of /viewer/healthcheck response:

{
"self_check_result": "DEGRADED",
"issue_log": [
{
"id": "YELLOW-a8c7",
"status": "YELLOW",
"message": "Storage degraded",
"reason": [
"YELLOW-f700-1a63e2d6"
],
"type": "STORAGE",
"level": 2
},
{
"id": "YELLOW-f700-1a63e2d6",
"status": "YELLOW",
"message": "Pool degraded",
"location": {
"storage": {
"pool": {
"name": "[/dev02/home/xenoxeno/db1:ssd](http://ydb-vla-dev02-000.search.yandex.net:8765/dev02/home/xenoxeno/db1:ssd)"
}
}
},
"reason": [
"YELLOW-5d3e-2181038080",
"YELLOW-5d3e-2181038081",
"YELLOW-5d3e-2181038082",
"YELLOW-5d3e-2181038083"
],
"type": "STORAGE_POOL",
"level": 3
},
{
"id": "YELLOW-5d3e-2181038083",
"status": "YELLOW",
"message": "Group degraded",
"location": {
"storage": {
"pool": {
"name": "[/dev02/home/xenoxeno/db1:ssd](http://ydb-vla-dev02-000.search.yandex.net:8765/dev02/home/xenoxeno/db1:ssd)",
"group": {
"id": [
"2181038083"
]
}
}
}
},
"reason": [
"RED-9f89-2-2181038083-6-0-1-0"
],
"type": "STORAGE_GROUP",
"level": 4
},
{
"id": "YELLOW-5d3e-2181038080",
"status": "YELLOW",
"message": "Group degraded",
"location": {
"storage": {
"pool": {
"name": "[/dev02/home/xenoxeno/db1:ssd](http://ydb-vla-dev02-000.search.yandex.net:8765/dev02/home/xenoxeno/db1:ssd)",
"group": {
"id": [
"2181038080"
]
}
}
}
},
"reason": [
"RED-9f89-2-2181038080-13-0-1-0"
],
"type": "STORAGE_GROUP",
"level": 4
},
{
"id": "YELLOW-5d3e-2181038081",
"status": "YELLOW",
"message": "Group degraded",
"location": {
"storage": {
"pool": {
"name": "[/dev02/home/xenoxeno/db1:ssd](http://ydb-vla-dev02-000.search.yandex.net:8765/dev02/home/xenoxeno/db1:ssd)",
"group": {
"id": [
"2181038081"
]
}
}
}
},
"reason": [
"RED-9f89-2-2181038081-2-0-1-0"
],
"type": "STORAGE_GROUP",
"level": 4
},
{
"id": "YELLOW-5d3e-2181038082",
"status": "YELLOW",
"message": "Group degraded",
"location": {
"storage": {
"pool": {
"name": "[/dev02/home/xenoxeno/db1:ssd](http://ydb-vla-dev02-000.search.yandex.net:8765/dev02/home/xenoxeno/db1:ssd)",
"group": {
"id": [
"2181038082"
]
}
}
}
},
"reason": [
"RED-9f89-2-2181038082-24-0-1-0"
],
"type": "STORAGE_GROUP",
"level": 4
},
{
"id": "RED-9f89-2-2181038083-6-0-1-0",
"status": "RED",
"message": "VDisk is not available",
"location": {
"storage": {
"node": {
"id": 2,
"host": "ydb-vla-dev02-001.search.yandex.net",
"port": 19001
},
"pool": {
"name": "[/dev02/home/xenoxeno/db1:ssd](http://ydb-vla-dev02-000.search.yandex.net:8765/dev02/home/xenoxeno/db1:ssd)",
"group": {
"vdisk": {
"id": [
"2181038083-6-0-1-0"
]
}
}
}
}
},
"type": "VDISK",
"level": 5
},
{
"id": "RED-9f89-2-2181038080-13-0-1-0",
"status": "RED",
"message": "VDisk is not available",
"location": {
"storage": {
"node": {
"id": 2,
"host": "ydb-vla-dev02-001.search.yandex.net",
"port": 19001
},
"pool": {
"name": "[/dev02/home/xenoxeno/db1:ssd](http://ydb-vla-dev02-000.search.yandex.net:8765/dev02/home/xenoxeno/db1:ssd)",
"group": {
"vdisk": {
"id": [
"2181038080-13-0-1-0"
]
}
}
}
}
},
"type": "VDISK",
"level": 5
},
{
"id": "RED-9f89-2-2181038081-2-0-1-0",
"status": "RED",
"message": "VDisk is not available",
"location": {
"storage": {
"node": {
"id": 2,
"host": "ydb-vla-dev02-001.search.yandex.net",
"port": 19001
},
"pool": {
"name": "[/dev02/home/xenoxeno/db1:ssd](http://ydb-vla-dev02-000.search.yandex.net:8765/dev02/home/xenoxeno/db1:ssd)",
"group": {
"vdisk": {
"id": [
"2181038081-2-0-1-0"
]
}
}
}
}
},
"type": "VDISK",
"level": 5
},
{
"id": "RED-9f89-2-2181038082-24-0-1-0",
"status": "RED",
"message": "VDisk is not available",
"location": {
"storage": {
"node": {
"id": 2,
"host": "ydb-vla-dev02-001.search.yandex.net",
"port": 19001
},
"pool": {
"name": "[/dev02/home/xenoxeno/db1:ssd](http://ydb-vla-dev02-000.search.yandex.net:8765/dev02/home/xenoxeno/db1:ssd)",
"group": {
"vdisk": {
"id": [
"2181038082-24-0-1-0"
]
}
}
}
}
},
"type": "VDISK",
"level": 5
},
{
"id": "YELLOW-5cc9",
"status": "YELLOW",
"message": "Database has storage issues",
"reason": [
"YELLOW-a8c7"
],
"type": "DATABASE",
"level": 1
}
],
"location": {
"id": 50005,
"host": "ui-dev-0.ydb.yandex.net",
"port": 19010
}
}

you should use "self_check_result" field to convert it's values to colors and present it as the database status

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 27, 2026

@copilot here is example of /viewer/healthcheck response:

{

...

Switched to self_check_result in 46a3130. Added a selfCheckResultToColorFlag mapping in store/reducers/healthcheckInfo/utils.ts (alongside the existing hcStatusToColorFlag), aligned with the existing SelfCheckResultToLabelTheme themes:

  • GOODGreen (success)
  • DEGRADEDBlue (info)
  • MAINTENANCE_REQUIREDYellow (warning)
  • EMERGENCYRed (danger)
  • UNSPECIFIEDGrey (normal)

Falls back to tenant.Overall when healthcheck data is absent. Let me know if you'd prefer different EFlag values for any of these (e.g. DEGRADEDYellow instead of Blue).

Copilot AI changed the title fix: use healthcheck database_status for database status color fix: use healthcheck self_check_result for database status color Apr 27, 2026
@adameat
Copy link
Copy Markdown
Member

adameat commented Apr 27, 2026

@copilot here is example of /viewer/healthcheck response:

{

...

Switched to self_check_result in 46a3130. Added a selfCheckResultToColorFlag mapping in store/reducers/healthcheckInfo/utils.ts (alongside the existing hcStatusToColorFlag), aligned with the existing SelfCheckResultToLabelTheme themes:

  • GOODGreen (success)
  • DEGRADEDBlue (info)
  • MAINTENANCE_REQUIREDYellow (warning)
  • EMERGENCYRed (danger)
  • UNSPECIFIEDGrey (normal)

Falls back to tenant.Overall when healthcheck data is absent. Let me know if you'd prefer different EFlag values for any of these (e.g. DEGRADEDYellow instead of Blue).

@copilot omg, why you've added another mapping from hc status to flag AGAIN?! self_check_result IS a hcStatus. health check status = self_check_result. use existing mapper, it should be enough

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 27, 2026

@copilot here is example of /viewer/healthcheck response:

{

...

Done in 1baecbf. Removed the separate selfCheckResultToColorFlag and extended the existing hcStatusToColorFlag to also cover SelfCheckResult keys (GOOD/DEGRADED/MAINTENANCE_REQUIRED/EMERGENCY; UNSPECIFIED is shared with StatusFlag). TenantOverview now uses hcStatusToColorFlag[self_check_result].

@adameat
Copy link
Copy Markdown
Member

adameat commented Apr 27, 2026

@copilot here is example of /viewer/healthcheck response:

{

...

Done in 1baecbf. Removed the separate selfCheckResultToColorFlag and extended the existing hcStatusToColorFlag to also cover SelfCheckResult keys (GOOD/DEGRADED/MAINTENANCE_REQUIRED/EMERGENCY; UNSPECIFIED is shared with StatusFlag). TenantOverview now uses hcStatusToColorFlag[self_check_result].

@copilot here is example of /viewer/healthcheck response:

{

...

Done in 1baecbf. Removed the separate selfCheckResultToColorFlag and extended the existing hcStatusToColorFlag to also cover SelfCheckResult keys (GOOD/DEGRADED/MAINTENANCE_REQUIRED/EMERGENCY; UNSPECIFIED is shared with StatusFlag). TenantOverview now uses hcStatusToColorFlag[self_check_result].

@copilot

okay, this is not what I meant.

there is should be existing convertor from "EMERGENCY" to "RED".

could you please search codebase carefully and find that convertor. and use it instead.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 27, 2026

@copilot here is example of /viewer/healthcheck response:

{

...

I searched the codebase carefully and can't find an existing SelfCheckResult → EFlag (or EMERGENCY → RED) converter. The only existing SelfCheckResult-keyed maps are:

  • SelfCheckResultToLabelTheme (HealthcheckStatus.tsx) → Gravity UI Label theme ('danger'/'warning'/'info'/...), not EFlag
  • checkResultToAlertTheme (HealthcheckPreview.tsx) → Gravity UI Alert theme, same value set
  • HEALTHCHECK_RESULT_TO_TEXT / HEALTHCHECK_RESULT_TO_ICON (Tenant/constants.ts) → text/icons

hcStatusToColorFlag originally only covered StatusFlag (RED/YELLOW/GREEN/…), which is a different enum than SelfCheckResult (EMERGENCY/MAINTENANCE_REQUIRED/DEGRADED/GOOD).

Could you point me at the specific file/symbol you have in mind? Or did you mean: instead of self_check_result, derive the status from the DATABASE-type entry in issue_log (whose status is a StatusFlag like "YELLOW"/"RED") and run that through the original hcStatusToColorFlag?

@astandrik
Copy link
Copy Markdown
Collaborator

@copilot Use the existing hcStatusToColorFlag only for StatusFlag -> EFlag.

Please do not extend it with SelfCheckResult keys. Instead, add a small converter from SelfCheckResult to StatusFlag, then use the existing color mapper:

self_check_result -> StatusFlag -> hcStatusToColorFlag -> EFlag

The mapping should match the backend logic in GetClusterStateFromSelfCheck:

GOOD -> GREEN
DEGRADED -> YELLOW
MAINTENANCE_REQUIRED -> RED
EMERGENCY -> RED
UNSPECIFIED/default -> GREY

So the fix should be:

  • keep hcStatusToColorFlag as Record<StatusFlag, EFlag>
  • add/reuse a SelfCheckResult -> StatusFlag converter
  • in TenantOverview, convert healthcheckData.self_check_result to StatusFlag first, then pass that through hcStatusToColorFlag
  • keep fallback to tenant.Overall when healthcheck data is absent

Do not map SelfCheckResult directly to EFlag; that duplicates the color mapping and currently gives different semantics (DEGRADED -> Blue, MAINTENANCE_REQUIRED -> Yellow) than the backend status logic.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 27, 2026

@copilot Use the existing hcStatusToColorFlag only for StatusFlag -> EFlag.

Please do not extend it with SelfCheckResult keys. Instead, add a small converter from SelfCheckResult to...

Updated in 92c4050.

hcStatusToColorFlag is back to Record<StatusFlag, EFlag> only, and TenantOverview now does self_check_result -> StatusFlag -> hcStatusToColorFlag -> EFlag via selfCheckResultToHcStatus with the backend semantics you listed:

  • GOOD -> GREEN
  • DEGRADED -> YELLOW
  • MAINTENANCE_REQUIRED -> RED
  • EMERGENCY -> RED
  • UNSPECIFIED -> GREY

Screenshot: /tmp/healthcheck-status-mapping.png

Copilot AI requested a review from astandrik April 27, 2026 11:12
@astandrik astandrik added this pull request to the merge queue Apr 27, 2026
Merged via the queue into main with commit a8e3324 Apr 27, 2026
23 checks passed
@astandrik astandrik deleted the copilot/use-healthcheck-response-for-status branch April 27, 2026 11:43
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.

use healthcheck response to display database status color

4 participants