Repository navigation
Conversation
fc7f8c9 to
d866e0e
Compare
QA LLM Review1. MEDIUM -- Hydration history query is gated at 26.41 but needs a column added in 26.43
DetailsAt The 26.44 gate for the memory breakdown columns is correct: Fix: raise the constant to |
d866e0e to
423440e
Compare
423440e to
0e48230
Compare
|
Thanks, confirmed: |
|
|
||
| if ( | ||
| isHydratingNow && | ||
| currentRun?.state === "running" && | ||
| currentRun.endMs === windowEndMs && | ||
| currentRun.startMs > windowStartMs && | ||
| !hydrationEpisodes.some( | ||
| (episode) => episode.startedAt.getTime() >= currentRun.startMs, | ||
| ) | ||
| ) { | ||
| segments = paintHydrating(segments, currentRun.startMs, windowEndMs); |
There was a problem hiding this comment.
On the open question: I think the inference can go wrong in two ways. The collector visits one replica per hydration_history_collection_interval. In an environment with N replicas, a finished episode can take about N minutes to be recorded.
- The stretch can be too long. Suppose a replica restarts and finishes hydrating, but the collector hasn't recorded that episode yet. Then someone creates a new index. The model sees an unhydrated object and no recorded episode since the restart. So it paints the whole time since the restart as hydrating. This lasts until the collector visits the replica.
- The stretch can be missing. Suppose the collector has already recorded the restart episode. Then someone creates a new index. The model finds an episode that started after the restart. So it doesn't paint a hydrating stretch at all. The new index's hydration doesn't appear until its own episode is recorded.
Nothing on mz_catalog_server says when an in-progress hydration started. So any stretch drawn for it is a guess. Two options:
- Don't draw a stretch for in-progress hydration. Instead, show the current state at the "now" edge, for example "Hydrating · 3 objects". This is accurate, but less visual.
- Start the inferred stretch at the later of two times: the restart, or the earliest creation time among the replica's unhydrated objects. Then drop the episode check. This fixes both cases, but it's still an approximation.
useHydratingReplicaIdswould need to keep the object ids. They might also need mapping throughmz_object_global_idsto matchmz_object_lifetimes.
There was a problem hiding this comment.
Thanks, this is a clear write-up. I went with option 1: the model no longer infers an in-progress stretch, and the status row shows a "Hydrating · N objects" badge at the now edge, counted per current replica from mz_compute_hydration_times (#39508). Finished episodes still draw from history.
|
|
||
| // TODO: remove these gates once all environments are past them. | ||
| const REPLICA_MEMORY_BREAKDOWN_MIN_VERSION = "26.44.0"; | ||
| const REPLICA_HYDRATION_HISTORY_MIN_VERSION = "26.43.0"; |
There was a problem hiding this comment.
nit: the commit message says hydration episodes need 26.41 and later, but the gate is 26.43 (for process_id), as the description says.
There was a problem hiding this comment.
Fixed the commit message.
6c2b1c5 to
aed7858
Compare
QA LLM Review1. MEDIUM -- Status timeline is blank before the first transition once a replica's older history has aged out
Details
The fix is to fill the stretch before the earliest transition from 2. LOW -- Heap-limit polling stops on a metrics row whose
|
aed7858 to
3df23ed
Compare
QA LLM Review1. MEDIUM -- Creation-times query matches clusters, replicas, roles and schemas that share an index's id
Details
The console's other |
24706e0 to
3763cce
Compare
26ce110 to
6d357be
Compare
|
Thanks. 1 is fixed in 6d357be: without a transition before the window, the stretch up to the first transition is drawn as running from the replica's readings (empty readings don't count). 2 was already fixed in the earlier push: the heap limits query keeps polling while a replica's latest limit is null. |
|
Thanks, fixed in 6d357be: the creation-times query now filters |
6d357be to
c78a132
Compare
c78a132 to
e3bf75d
Compare
| // subscribe holds one window of them instead of every sample since it | ||
| // started. | ||
| .where( | ||
| sql<boolean>`mz_now() <= m.occurred_at + ${sql.lit(`${retentionMinutes} minutes`)}::interval`, |
There was a problem hiding this comment.
This adds a per-viewer subscribe dataflow on mz_catalog_server for every multi-process cluster someone has open. The temporal filter bounds it, but it has to hold every row in the window to retract it later. In the 24h tier that's about 1,440 samples per process per open tab, for example around 23,000 rows for 2 replicas of 8 processes.
The EXPLAIN shows the lookup, but not the memory. Was the 24h tier's footprint on mz_catalog_server measured? If it's significant, limiting per-process series to the 3h tier until CNS-203 lands would bound it to an eighth.
There was a problem hiding this comment.
Thanks, it wasn't measured. On a local emulator with 2 replicas of 16 processes, the 24h temporal filter held ~12 MiB per open tab against ~2 MiB with a literal bound. The card no longer subscribes per process, and the builder kept for the workers drawer now starts at a literal time that moves forward once per window, in 9f3a5c2.
e3bf75d to
05a6c95
Compare
77b21bd to
9f3a5c2
Compare
9f3a5c2 to
c504ca6
Compare
Second in the cluster details redesign stack. Adds the queries, hooks and chart model that the resource usage card in the next PR draws from. Nothing renders them yet. Queries, all scoped to literal replica or object ids so they plan as index lookups on mz_catalog_server, except where noted: - RAM and swap as shares of the heap limit, selected from the console utilization views on 26.44 and later only. Callers that don't ask for them keep their query keys. - Replica status history, for running and offline stretches and out-of-memory kills. - Hydration episodes from mz_replica_hydration_history (26.43 and later, where it gained process_id). This has no index, so it only runs for replicas that came back online inside the window. - How many compute objects each replica has yet to hydrate. - Heap limits per replica, fetched once and refetched only while a replica hasn't reported one. - Creation times of the cluster's indexes and materialized views, fetched once per id set. Per-process reads, for the workers drawer later in the stack: a subscribe builder for a replica's samples in mz_cluster_replica_metrics_history (a lookup on its replica_id index) and each size's process count and allocations from mz_cluster_replica_sizes. The subscribe starts at a literal time, which useRollingWindowStartMs moves forward once per window, since a mz_now() filter would hold every sample's pending retraction on mz_catalog_server. useUtilizationTier holds the tier choice that the replica-level paths share. useReplicaUtilizationHistory gains an includeOfflineEvents option. The new page reads offline stretches from status history, so it skips the 20s offline-events poll on windows of 3h or less. The chart model holds the pure logic: status timelines, replica colors, memory bar segments, and merging buckets so bars stay readable on wide windows.
c504ca6 to
db7eda6
Compare
Motivation
Second PR in the cluster details redesign stack, on top of #39446. It adds the data behind the resource usage card: memory split into RAM and swap, replica status over time, hydration, heap limits and object creation times. The card itself is the next PR (#39508), so this one can be reviewed without the chart code. Nothing renders these queries yet.
Part of CNS-174.
Description
New queries. Each filters on literal replica or object ids, so it plans as an index lookup on
mz_catalog_server, except where noted.swap_of_ram_percentandheap_limit_percenton the console utilization views, 26.44 and latermz_cluster_replica_status_historymz_replica_hydration_history, 26.43 and later, where it gainedprocess_id. No index, so it only runs for replicas that came back online inside the window.mz_compute_hydration_timesmz_cluster_replica_metricsmz_object_lifetimes, filtered to those object types since other kinds share theu<N>id formmz_cluster_replica_metrics_history, a lookup on itsreplica_idindexmz_cluster_replica_sizes, fast path on its indexPer-process reads. The resource usage card charts replicas, not processes. This PR adds the per-process subscribe builder and the sizes query that the Processes drawer in #39508 and the workers drawer in #39889 read. The subscribe starts at a literal time one window back, and
useRollingWindowStartMsmoves that start forward once per window, so an open subscribe holds at most two windows of samples. Amz_now()temporal filter would instead hold each sample's pending retraction in the subscribe onmz_catalog_server: on a local emulator with 2 replicas of 16 processes over 24h, that measured ~12 MiB per open subscribe, against ~2 MiB with the literal bound. EXPLAIN onmz_catalog_server: a lookup onmz_cluster_replica_metrics_history_ind, with the bound as a plain filter. Per-process catalog views are tracked in CNS-203.useUtilizationTierholds the tier choice (3h subscribe, 24h subscribe, or poll) that the replica-level paths share.useReplicaUtilizationHistorygets two options:includeMemoryBreakdownadds the RAM and swap columns. Callers that don't pass it keep their query keys, so the classic page sends the same queries as before.includeOfflineEvents: falseskips the 20s offline-events poll on windows of 3h or less. The new page reads offline stretches from status history instead.useClusterObjectsLive(inallObjectsCollection.ts) returns a cluster's objects of the given types as a TanStack DB live query over the existingallObjectsCollection. FilteringuseAllObjectsgives a new array on every DDL anywhere in the environment; the live query keeps its result until one of this cluster's matching objects changes. It reuses the app-wide objects subscribe, so it adds no catalog_server load.resourceUsageModel.tsholds the chart logic as pure functions: status timelines, replica colors, memory bar segments, and merging buckets so bars stay readable on wide windows.The k6 cluster detail replay lists these queries' refresh intervals, since it replays unlisted queries every 5s. The testing guide's scalability commands now use
yarn test:e2e:scalability, because thechromiumproject skipsscalability/.types/materialize.d.tsis edited by hand, with TODOs on the new columns, becauseyarn gen:typesfails against current builds (pg_get_serial_sequencedoesn't exist).A hydration in progress has no recorded start, so the timeline model doesn't draw one. The next PR shows it as a count of objects still hydrating at the now edge instead.
Verification
replicaUtilizationBinning.test.ts: RAM and swap shares survive binning and come from the bucket's highest-heap sample.allObjectsCollection.test.ts:useClusterObjectsLivereturns the cluster's objects of the given types, keeps its result through changes on other clusters, and updates when one of its objects changes.resourceUsageModel.test.ts: status timelines (state before the window, readings before the first transition once older history is gone, clipping, out-of-memory markers, hydration stretches), replica colors, memory bar segments, the RAM limit, and bucket merging.replicaProcessMetrics.test.ts: the per-process subscribe bounds its samples with a literal start and no temporal filter.queries.test.ts:useRollingWindowStartMsstarts one window back, moves once per window, and never returns a start for another window.mz_catalog_serverin a local v26.45 build, and the two per-process queries on a cloud environment.🤖 Generated with Claude Code