feat(health): expose pg/es/s3 used size on /api/health (#7356) - #7357
feat(health): expose pg/es/s3 used size on /api/health (#7356)#7357Sébastien Bocahu (sbocahu) wants to merge 4 commits into
Conversation
|
📖 Documentation check — ✅ Passed 9 functional file(s), 1 doc file(s) changed. Documentation-worthy changes detected and documentation was updated. 👏 Detected changes (covered by doc updates)
|
|
✅ Container vulnerability scan — Passed Previously reported findings are no longer present.
View workflow run · Standard JSON report · UBI9 JSON report Updated from CI run attempt 1. |
9bb3d1a to
aff1b0f
Compare
aff1b0f to
d9c8dba
Compare
|
Two fixes pushed after testing on a deployed environment, where Root cause
client.statObject(... .object(getTenantPath("")) ...); // key = "<tenant-uuid>/"A tenant path is a key prefix, not an object. The probe failed permanently and the load balancer pulled the instance out of rotation. This only stayed hidden because MinIO tolerates the call as soon as any file exists under the prefix — which is true in dev and CI, but not in a new environment. Fix 1 — probe with a listing (
|
Closes #7356
What
Adds opt-in storage metrics to
GET /api/health, behind a newdetails=truerequest parameter:{ "status": "success", "pg_used_size": 104857600, "es_used_size": 524288000, "s3_used_size": 20971520 }Without
details(or withdetails=false) the response is byte-for-byte unchanged (plainsuccess), so existing load-balancer probes keep working and pay no extra cost.Sizes are in bytes. A
nullvalue means the metric could not be retrieved from that dependency.How each size is obtained
pg_used_sizepg_database_size(current_database())es_used_size_statsrestricted to thestoremetric on the{prefix}_*index patterns3_used_sizeWhy the values are cached
The health endpoint is polled very frequently (LB probes), while computing these metrics walks the entire object storage listing and queries the engine cluster. So
HealthCheckService#getStorageUsage()caches the three values foropenaev.healthcheck.storage-usage-cache-duration(defaultPT4H, configurable, documented indocs/deployment/configuration.md).The refresh is single-flight: only one caller recomputes, concurrent callers keep being served the previous (stale) value instead of piling up on the engine and the bucket. Only the very first call — when there is nothing cached yet — blocks.
A metric that fails to compute is logged and reported as
null; it never turns a healthy platform into a 503, since the health status keeps reflecting connectivity only./api/healthactually checksWorth stating explicitly, as it is commonly misunderstood (a javadoc note was added on
runHealthCheck()to that effect):select 1statObjectwith 2s timeoutsnullrather than a 503. So an engine outage is still invisible to this probe.Adding a real engine connectivity check is a deliberate follow-up decision, not part of this PR: it would change the failure semantics of the probe (an engine outage would start taking instances out of the LB pool), which deserves its own discussion.
The endpoint also remains
@Transactional(propagation = NOT_SUPPORTED)— see #6837, it must not pin a Hikari connection while doing external network I/O.Tests
HealthCheckApiTest:details=falsedoes not compute the usage at all;details=truereturns the three sizes.HealthCheckServiceTest: per-metric values, a degraded dependency reported asnullwithout failing, and cache hit on a second call.Checklist
mvn spotless:applymvn compile(openaev-model+openaev-api)mvn test-compiledocs/deployment/configuration.md)