Repository navigation
Commit 3a412e4
authored
fix(app): run the row side panel query once per opened row (#3568)
## Summary
Opening a row in the side panel runs the same `SELECT *` row query twice. `DBRowSidePanel` shows "Loading..." until its `useRowData` lookup settles, then mounts the Overview or Column Values tab, which calls `useRowData` again with the same query key. The app's `QueryClient` keeps React Query's default `staleTime` of 0, so the tab's new observer refetches the row that has just loaded. Both lookups share one cache entry, so the second request is a refetch of a stale query, not two different keys.
- `useRowData` gives its bounded and fallback lookups a `staleTime`: `Infinity` when the row was found, `0` when it was not. The tab reads the row from the cache, so opening a row runs one `SELECT *`. Switching between Overview and Column Values does not run it again either.
- A different row, source or query settings (for example the "Show materialized and alias columns" option from #3231) is a different query key, so it still runs. A row that was not found stays stale, so the next lookup tries again: the row may not have been ingested yet. `useMergeTreeSettings` keeps failures stale the same way.
- The same lookups back the expanded row in the search table and the span details in the trace waterfall. Those mount their tab together with the lookup, so React Query already shared one request there. With this change, switching their tabs reuses the row too.
Things to be aware of:
- A found row now stays fresh while it is cached. Closing the panel and opening the same row again within 5 minutes (React Query's default `gcTime`) shows it from the cache with no request. On `main`, the cached row shows at once and is fetched again in the background. So a row that a ClickHouse `UPDATE` changes, or that `DELETE` or a TTL removes, within those 5 minutes shows its cached values until the cache entry expires.
- When the time-bounded lookup of a "View Trace" frame misses and the unbounded fallback finds the row, the tab still runs the bounded lookup once more, because its empty result is stale: 3 requests instead of 4 on `main` (from reading the code; no test covers this path). I kept one rule for both lookups instead of treating a bounded miss as fresh. Happy to change that.
- I fixed this in `useRowData` instead of passing the row from `DBRowSidePanel` into the tabs, so the other callers above get it too and the tab components keep their props. Happy to switch if you prefer that.
### Tests
New `packages/app/src/components/__tests__/DBRowDataPanel.rowQuery.test.tsx` uses the real `useRowData` and `useQueriedChartConfig`, a `QueryClient` with default options (as in `pages/_app.tsx`) and a mocked ClickHouse client that counts `queryChartConfig` calls. A small panel mirrors `DBRowSidePanel`: it shows "Loading..." until its own lookup settles, then mounts the real `RowDataPanel`.
- The panel and its tab run the lookup once, without and with a `dateRange`, and the tab renders the row.
- Closing the panel and opening the same row again reuses the found row.
- Another row and another source each run the lookup again, once.
- A row that was not found is looked up again when the tab mounts.
With `DBRowDataPanel.tsx` from `main`, 5 of the 6 tests fail: the panel and its tab run the lookup twice (`Expected number of calls: 1`, `Received number of calls: 2`), the reopened row is fetched again, and the row and source tests see two requests per row. The not-found test passes on both. Removing the `staleTime` from the bounded lookup fails only the bounded test, and using `Infinity` for misses fails only the not-found test. The existing `DBRowDataPanel.test.ts` passes, and so do the test files that render the row panels without mocking `DBRowDataPanel` (`ContextSidePanel`, `DirectTraceSidePanel`, `ErrorsTab`, `DBSearchPage.directTrace`). ESLint (no warnings), Prettier, `tsc --noEmit` for `packages/app`, `knip` and `yarn ratchet` pass.
In the browser, with `yarn app:dev:local` connected to the demo server, I counted the POST requests whose SQL starts with `SELECT *,` (the row lookup) in headless Chromium:
| | `main` | This branch |
| :-- | :-- | :-- |
| Open a log row (10 rows) | 2 per row | 1 per row |
| Then Overview → Column Values → Overview (2 rows) | 2 more per row | 0 |
play.hyperdx.io shows the same 2 requests per row (3 rows). The UI does not change. I did not test trace rows, "View Trace" or session replay in the browser. The unit tests cover both the bounded and the unbounded lookup.
### How to reproduce
**Starting point:** play.hyperdx.io, or `yarn app:dev:local` connected to the demo server (onboarding → "Connect to Demo Server").
**On `main`:**
1. Open Search on the Logs source.
2. Open DevTools → Network and filter by Fetch/XHR.
3. Click a log row to open the side panel.
4. Two POST requests to ClickHouse have the same payload, starting with `SELECT *,Timestamp AS "__hdx_timestamp"`, about 300–700 ms apart.
5. Click "Column Values", then "Overview". Each click sends that request again.
**On this branch:**
1. Do the same steps. Step 4 shows one request for the row, and step 5 sends none.
2. Click another row. It sends one request for that row.
### How to test on Vercel preview
**Preview routes:** /search
**Steps:**
1. Click "Connect to Demo Server" on the onboarding modal.
2. Open /search on the Logs source, and open DevTools → Network.
3. Click a log row in the results table to open the side panel.
4. Verify that exactly one POST request with a payload that starts with `SELECT *,Timestamp AS "__hdx_timestamp"` is sent for that row.
5. Click "Column Values", then "Overview", and verify that no new request with that payload is sent.
6. Click another row and verify that it sends one such request.
### References
- Closes #1400
- Related: #32311 parent a044642 commit 3a412e4
3 files changed
Lines changed: 189 additions & 0 deletions
File tree
- .changeset
- packages/app/src/components
- __tests__
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
12 | 13 | | |
13 | 14 | | |
14 | 15 | | |
| |||
23 | 24 | | |
24 | 25 | | |
25 | 26 | | |
| 27 | + | |
26 | 28 | | |
27 | 29 | | |
28 | 30 | | |
| |||
48 | 50 | | |
49 | 51 | | |
50 | 52 | | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
51 | 61 | | |
52 | 62 | | |
53 | 63 | | |
| |||
289 | 299 | | |
290 | 300 | | |
291 | 301 | | |
| 302 | + | |
292 | 303 | | |
293 | 304 | | |
294 | 305 | | |
| |||
310 | 321 | | |
311 | 322 | | |
312 | 323 | | |
| 324 | + | |
313 | 325 | | |
314 | 326 | | |
315 | 327 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
0 commit comments