Commit 4cf9014
perf/fix: close the remaining Performance-tab gaps from the readiness review
The seven non-blocking findings left over after #86. Each was re-verified against
current main before being fixed, and each fix verified after — two of them turned
out to be wrong on the first attempt, both caught by testing rather than reading.
Sample recovery was an unindexable full scan on a table nothing pruned
recoverFullText runs one lookup per sample, up to 20 per "view full query" click,
and the query wrapped query_text in three nested regexp_replace/REPLACE calls plus
LOWER — so no index could satisfy it and Postgres materialized a rewritten copy of
the whole per-connection slice. EXPLAIN (ANALYZE) on a real install: 36 ms at 1,093
rows, 1,112 ms at 34,976. Linear, and query_lineage was absent from
SlowQueryRetentionService, so it degraded with the install's *age* rather than its
load — which is why it passed every pre-launch test.
Precomputed into a STORED generated column (normalized_match) with a
text_pattern_ops index, applied by QueryLineageMatchIndexInitializer since this repo
has no Flyway runtime. Verified on the real table: Index Scan, 0.119 ms, and the DDL
is idempotent on re-run. query_lineage is now purged with the other three fact
tables.
Deliberately no COALESCE fallback to the inline expression. That is the obvious way
to stay safe on a database without the column and it silently undoes the entire fix:
measured on the same 37,504-row table, COALESCE(normalized_match, …) plans a Seq Scan
at 48.7 ms versus 0.39 ms for the bare column. A missing column instead surfaces as a
WARN from the initializer, and recoverFullText already catches a failed lookup and
returns the sample unchanged.
Denials were retried three times
queryClient set retry: 3 with no status predicate, so a 403 became four requests and
~7 s of backoff before the UI could render anything — and an unauthorized
/tenant-column-suggestions opens a fresh JDBC connection to the target database on
every attempt.
The first version of this fix read error.response.status and did nothing at all: the
axios response interceptor rethrows a plain Error with the status copied onto
error.status, so the axios-shaped field never matched. Measured in the browser before
and after: 4 attempts / 7197 ms -> 1 attempt / 34 ms. Confirmed 500, 503, 401 and
network failures still retry, and the 3-attempt cap still holds.
A customer id containing a slash was unreachable by any encoding
customerId is a literal value from the tenant column — application data, so it can
contain /, ? or #. Raw, the slash split the path; percent-encoded, Jetty answers 400
"Ambiguous URI path separator". Both reproduced with the real value `acct/77?x=1`,
whose rows rendered as "no queries rolled up yet" while the header said the customer
had 12 executions. encodeURIComponent alone does not fix this, which is why the id
moved off the path: /{connectionId}/customer-queries?customerId=… and
/customer-query-samples. The old path routes are kept and @deprecated for wire
compatibility. Verified: the slash-bearing id now returns 200, and 403 on a
connection the caller cannot read.
Failed fetches rendered as "no data yet"
Every panel branched on `!isLoading && rows.length === 0`, and `data ?? []` turns any
error into an empty array — so a 404 and an empty result were indistinguishable. That
matters more now that connection authorization is enforced: a 403 would read as
"nothing captured yet" and send the user to re-run an ingestion they cannot fix. Added
a shared QueryError component wired into CustomerExplorer (3 branches), QueryTrendsTab
(2) and WorkloadAnalysisPanel (1), with per-status wording verified against the real
interceptor error shapes.
Tab bar and ARIA
At 390 px the four tabs measured 427 px with overflow-x: visible, so three of them sat
off-screen unreachable. The bar now scrolls (verified: scrolls 373 px, all four
reachable). Completed the ARIA tabs pattern — role="tabpanel", aria-controls, roving
tabindex and arrow/Home/End navigation. The first version had a stale-closure bug that
moved selection exactly once and then froze; fixed with the functional state updater,
verified across the full key sequence including wraparound.
Workload reads were gated on the write tier
status/latest/getReport/history all used assertCanManageConnectionContent.
EffectiveConnectionAccess's own comment lists slow-query analytics under read. Latent
today because every grant resolves to FULL_CONTENT, but it would deny the whole
Workload tab to a read-only grant the moment one is reintroduced. `run` keeps manage.
Known issue, documented rather than fixed
The slow-log ingestion cursor has two real defects, both left in place with a comment
at updateLastProcessed explaining them: it records the time ingestion *finished*
rather than the last event's timestamp (so events arriving mid-run are skipped
permanently), and it writes LocalDateTime.now() while every read does
.atZone(ZoneOffset.UTC) (agreeing only because the container runs Etc/UTC; a
bare-metal install at UTC+5:30 would skip 5.5 h of history every run). Not fixed here
because all six providers need live cloud credentials to exercise, and an unverified
change to a cursor silently skips or duplicates data.
Verification
Backend and frontend both build clean. Live against the rebuilt image: new customer
routes 200 with a slash-bearing id and 403 on an ungranted connection; workload reads
non-403 for a granted user; the lineage index confirmed as an Index Scan on the real
table.
Not covered: mvn test was not run locally (no JDK/Maven on this host) — CI runs it.
Note that the "backend tests (advisory)" job is continue-on-error, so its green tick
means the job finished, not that tests passed; main currently has 5 failing test
classes independent of this branch.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 64a0085 commit 4cf9014
16 files changed
Lines changed: 461 additions & 43 deletions
File tree
- backend/src/main
- java/com/dbaagent
- config
- controller
- repository
- service
- resources/db/migration
- src
- components
- sections
- tabs/Performance
- components
- lib
- api
Lines changed: 116 additions & 0 deletions
| 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 | + | |
Lines changed: 39 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
78 | 78 | | |
79 | 79 | | |
80 | 80 | | |
81 | | - | |
| 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 | + | |
82 | 116 | | |
83 | 117 | | |
84 | 118 | | |
| |||
87 | 121 | | |
88 | 122 | | |
89 | 123 | | |
90 | | - | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
91 | 128 | | |
92 | 129 | | |
93 | 130 | | |
| |||
Lines changed: 10 additions & 4 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
30 | 36 | | |
31 | 37 | | |
32 | 38 | | |
| |||
64 | 70 | | |
65 | 71 | | |
66 | 72 | | |
67 | | - | |
| 73 | + | |
68 | 74 | | |
69 | 75 | | |
70 | 76 | | |
| |||
81 | 87 | | |
82 | 88 | | |
83 | 89 | | |
84 | | - | |
| 90 | + | |
85 | 91 | | |
86 | 92 | | |
87 | 93 | | |
| |||
92 | 98 | | |
93 | 99 | | |
94 | 100 | | |
95 | | - | |
| 101 | + | |
96 | 102 | | |
97 | 103 | | |
98 | 104 | | |
| |||
101 | 107 | | |
102 | 108 | | |
103 | 109 | | |
104 | | - | |
| 110 | + | |
105 | 111 | | |
106 | 112 | | |
107 | 113 | | |
Lines changed: 43 additions & 12 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
| 6 | + | |
6 | 7 | | |
7 | 8 | | |
| 9 | + | |
8 | 10 | | |
9 | 11 | | |
10 | 12 | | |
| |||
147 | 149 | | |
148 | 150 | | |
149 | 151 | | |
150 | | - | |
151 | | - | |
152 | | - | |
153 | | - | |
154 | | - | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
155 | 172 | | |
156 | 173 | | |
157 | 174 | | |
158 | 175 | | |
159 | 176 | | |
160 | | - | |
161 | | - | |
162 | | - | |
163 | | - | |
164 | | - | |
165 | | - | |
166 | | - | |
| 177 | + | |
167 | 178 | | |
168 | 179 | | |
169 | 180 | | |
| |||
172 | 183 | | |
173 | 184 | | |
174 | 185 | | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
175 | 206 | | |
Lines changed: 24 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
418 | 418 | | |
419 | 419 | | |
420 | 420 | | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
421 | 445 | | |
422 | 446 | | |
423 | 447 | | |
| |||
0 commit comments