Commit 9dde5a0
authored
[OPIK-7315] scope the sentinel repair to the flag window (#8055)
* [OPIK-7315] scope the sentinel repair to the flag window
The repair matched every epoch end_time and NaN ttft in the table. That is
unsafe: an epoch end_time is not evidence the flag produced it, since clients
send them and rows predating the flag hold them. Those values cannot be
recovered afterwards either, because the parked successor encodes an absent
end_time as the same epoch, so no reference copy exists -- and the counts
would still have reported success, because no sentinel would remain.
Measured on an internal environment: the unbounded predicate matched 34 keys
across 12 workspaces, of which 5 came from the flag window. The other 29
carried genuine client-sent values.
--sentinel-window-from / --sentinel-window-to are now required, matched on
created_at OR last_updated_at so a row created in the window and a
pre-existing row updated in it are both caught. The counts carry the same
window, so 0 means "the flag's damage is gone" rather than "no such value
exists anywhere" -- unbounded, the gate could never clear on an estate
holding any genuine epoch value.
Both bounds are pinned to UTC. The timezone assertion added with the epoch
literal caught this during development: unpinned, the window shifts with the
server timezone and matches nothing.
The test gains a cohort matching the predicate but written outside the
window, asserting it keeps both values.
* [OPIK-7315] describe the window consistently, and cover its two arms
Baz review on #8055. Three of these are my own change not carried through.
--confirm-flag-was-live still said it accepts "every epoch end_time and NaN
ttft in traces" becoming NULL, written before the window existed. It
authorises a window-scoped repair; rows outside are never touched whether or
not it is passed. Corrected in the flag doc and the runtime NOTE.
Both printed follow-up commands omitted the now-mandatory bounds, so each was
guaranteed to exit 2 -- the same defect as the stage A command earlier in this
work. They now carry placeholder bounds and say the script cannot know them.
sentinelCounts interpolated the bounds while its sibling repairSentinels bound
them. Now bound; only the database name stays formatted, an identifier having
no bind form.
And the test tied created_at, last_updated_at and start_time to one value, so
it never exercised the last_updated_at arm and had no row on either boundary.
Adds a row created before the window but updated inside it, and rows exactly
at windowFrom and windowTo. Mutation-checked: dropping the last_updated_at arm
leaves endTime=2 and fails; making windowTo inclusive fails.
* [OPIK-7315] qualify every count the repair reports, and name the carry-forward gap
Thiago's review on #8055. The window scoping silently changed what the output
means, and I qualified one message out of four.
The three that report counts still asserted table-wide facts, so bounds given
in local time would produce 0 in-window, an unqualified clean bill of health,
and exit 0 over unrepaired damage -- ticking the runbook box that gates
finalize.sh. All three now name the window, and the driver prints the SAME
aggregates over an all-time range beside them: a 0 in-window against a
non-zero total is the signature of a wrong window, and is now visible rather
than silent. Both readings come from the one shipped .sql file, so they cannot
drift.
The carry-forward gap is real and verified in TraceDAO.UPDATE, which copies
created_at and (when the patch omits them) end_time/ttft verbatim while
last_updated_at defaults to now64(6). A trace created pre-window, patched
in-window under the flag, then patched again post-revert has a live version
matching neither arm, and the repair clears the older in-window version so the
gate still reports success. Documented, and the README claim that both arms
catch every case is removed, since this case falsifies it.
I have NOT redefined --sentinel-window-to as the repair time. That closes this
hole by opening the opposite one: a row holding a genuine epoch end_time,
merely patched inside the widened range, then matches and is nulled
irrecoverably -- and end_time is carried forward verbatim, so nothing in the
data separates the two. Measured here: 0 keys are pre-window-created and
touched since, so this estate has no instances of either. The trade is now
stated so the bound is chosen knowingly.
Also: the sentinel_counts header said it takes no window while doing three
substitutions, and the window/mode check had landed between a comment and the
two flag checks it documents.
* [OPIK-7315] cover the DateTime64 range, pin the carry-forward gap, own finalize.sh's limits
Baz review on #8055.
The unbounded comparison capped at 2100-01-01, an arbitrary number in a
dataset where far-future timestamps are real (see the runbook's far-future id
section) -- exactly the rows an operator would want the comparison to surface.
Now 1900..2299, the DateTime64 range.
The carry-forward gap Thiago found is now asserted rather than only described:
a cohort with two versions of one key, the in-window one repaired and the
live one outside the window keeping its epoch, with the window-scoped counts
still reading 0. Asserting a known limitation is deliberate -- change the
window semantics without addressing it and the test flips, which is the point.
Needed an explicit-id overload and a FINAL-collapsed count helper, since the
claim is about the live row rather than any version.
Not taken: repairing "the latest row for each key across the full table".
Across the full table is the unbounded predicate this PR removes, which
destroyed 29 rows' genuine values on the environment measured here.
And the checklist claimed to gate finalize.sh. It does not: finalize.sh has
zero references to the repair and reads no marker proving one ran with the
right window. Said plainly, so the box is understood as the only control
rather than a mechanical one.
---------1 parent c6fc00a commit 9dde5a0
5 files changed
Lines changed: 303 additions & 76 deletions
File tree
- apps/opik-backend
- data-migrations/traces-local-v2-cutover
- scripts
- db-app-analytics
- src/test/java/com/comet/opik/infrastructure
Lines changed: 40 additions & 10 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1036 | 1036 | | |
1037 | 1037 | | |
1038 | 1038 | | |
1039 | | - | |
1040 | | - | |
1041 | | - | |
| 1039 | + | |
| 1040 | + | |
| 1041 | + | |
1042 | 1042 | | |
| 1043 | + | |
1043 | 1044 | | |
1044 | | - | |
| 1045 | + | |
1045 | 1046 | | |
1046 | | - | |
| 1047 | + | |
1047 | 1048 | | |
1048 | 1049 | | |
1049 | 1050 | | |
| |||
1198 | 1199 | | |
1199 | 1200 | | |
1200 | 1201 | | |
1201 | | - | |
| 1202 | + | |
| 1203 | + | |
1202 | 1204 | | |
| 1205 | + | |
| 1206 | + | |
| 1207 | + | |
| 1208 | + | |
| 1209 | + | |
| 1210 | + | |
| 1211 | + | |
| 1212 | + | |
| 1213 | + | |
| 1214 | + | |
| 1215 | + | |
| 1216 | + | |
| 1217 | + | |
| 1218 | + | |
| 1219 | + | |
| 1220 | + | |
| 1221 | + | |
| 1222 | + | |
| 1223 | + | |
| 1224 | + | |
| 1225 | + | |
1203 | 1226 | | |
1204 | 1227 | | |
1205 | 1228 | | |
| |||
1237 | 1260 | | |
1238 | 1261 | | |
1239 | 1262 | | |
1240 | | - | |
1241 | | - | |
1242 | | - | |
1243 | | - | |
| 1263 | + | |
| 1264 | + | |
| 1265 | + | |
| 1266 | + | |
| 1267 | + | |
| 1268 | + | |
| 1269 | + | |
| 1270 | + | |
| 1271 | + | |
| 1272 | + | |
| 1273 | + | |
1244 | 1274 | | |
1245 | 1275 | | |
1246 | 1276 | | |
| |||
Lines changed: 38 additions & 24 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
| 4 | + | |
5 | 5 | | |
6 | 6 | | |
7 | | - | |
8 | | - | |
| 7 | + | |
| 8 | + | |
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
13 | 24 | | |
14 | | - | |
15 | | - | |
| 25 | + | |
16 | 26 | | |
17 | 27 | | |
18 | | - | |
19 | | - | |
20 | | - | |
21 | | - | |
22 | | - | |
23 | | - | |
24 | | - | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
29 | | - | |
30 | | - | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
31 | 32 | | |
32 | 33 | | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | | - | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
37 | 41 | | |
38 | | - | |
39 | | - | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
40 | 54 | | |
41 | 55 | | |
42 | 56 | | |
| |||
Lines changed: 11 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
41 | | - | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
42 | 48 | | |
43 | 49 | | |
44 | 50 | | |
| |||
47 | 53 | | |
48 | 54 | | |
49 | 55 | | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
50 | 60 | | |
0 commit comments