You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
No guard scans a payload or render projection for a server-local column handed to a UTC-assuming consumer #3208
Three clock-frame defects of one shape have now been found by hand — #2991 (query_stats.creation_time in analysis SQL), #3198 (default_trace_events.event_time in an MCP payload), and the sibling sweep for #3202 that found 16 more MCP fields plus 8 desktop render sites. Nothing in either test suite scans a payload or render projection for a server-local column being handed to a consumer that assumes UTC. A guard over that boundary would have caught all three at once, and it is the more valuable half of the work.
What the three existing guards do and do not reach
bare creation_time compared against a $n window bound
right discriminator shape, wrong roots — neither Service/Mcp/ nor either viewer is in its globs
StoreSqlClockDisciplineTests
store source incl. Service/Mcp/
naive timestamp column compared against a bare clock function
right roots, wrong hazard, and it explicitly disclaims projections at :43-47: "a bare clock in a SET, a VALUES row or a projection is a different defect shape … deliberately out of scope"
CollectorTimestampFrameTests
PerformanceMonitor.Collectors
the frame a collector writes
right per-column reasoning, but it reads collector source only — it says what the frame IS, never who consumes it
the right boundary, scoped to default_trace_events by design
The gap is exactly the diagonal: a column whose frame CollectorTimestampFrameTests knows, reaching a consumer none of the four inspects.
Why the frame cannot be keyed on the column name
The repo has already established this twice and both notes are worth keeping:
StoreSqlClockDisciplineTests maintains AmbiguousFrameColumns = ["sample_time", "event_time", "last_execution_time"] — three names that are two frames across several tables each, with the evidence per table.
CollectorTimestampFrameTests' own remarks record that its first cut was a store-wide "all naive timestamps are UTC" rule that would have forbidden the CPU collector's intentional local clock.
So a guard here must be scoped per (table, column), and the census has to be derivable rather than hand-declared or it rots.
The technique that already works
#3202's EveryAnnotationSourcesDeclaredFrame_MatchesItsOwnCollectorsQueryText derives the frame from the collector's own query text instead of trusting a declaration: this codebase writes alias = expression, so the right-hand side is the provenance. A column assigned from the XE @timestamp is UTC; one assigned from fn_trace_gettable's StartTime or a dm_exec_* / dm_tran_* DMV value is server-local. Critically, it fails when the provenance cannot be read rather than defaulting to UTC — "a frame nobody can read is the state the de-skew defects shipped in."
Run over the whole collector corpus that classifier already resolves the population: 66 CollectorColumnType.Timestamp columns, with 17 server-local columns reaching a consumer. It also finds its own blind spot honestly — BlockedProcessReportCollector's six and DmvBlockingSnapshotCollector.event_time have no T-SQL assignment at all (they are parsed from XML in C#, or stamped from context.CollectionTime), so those need a C#-side arm or an explicit per-column declaration with its evidence. That is the honest shape of the coverage, not a reason to skip them.
What to decide before writing it
One guard or two. The MCP payload boundary (ToString("o") into an anonymous object) and the WPF render boundary (ForDisplay / FormatServerClock / FormatServerTime getters) are different discriminators over different roots. Two focused scans probably beat one that has to understand both.
Floors to pin so a broken glob cannot report a clean bill of health, measured on dev at e63a367e7: 131ToString("o") sites across 27 files in Darling/PerformanceMonitor.Darling.Service/Mcp/; 66 collector timestamp columns; ServerLocalReadFrameDisciplineTests measured 713 production .cs files across Darling/ and Lite/.
Three clock-frame defects of one shape have now been found by hand — #2991 (
query_stats.creation_timein analysis SQL), #3198 (default_trace_events.event_timein an MCP payload), and the sibling sweep for #3202 that found 16 more MCP fields plus 8 desktop render sites. Nothing in either test suite scans a payload or render projection for a server-local column being handed to a consumer that assumes UTC. A guard over that boundary would have caught all three at once, and it is the more valuable half of the work.What the three existing guards do and do not reach
CreationTimeClockFrameDisciplineTestsDarling/PerformanceMonitor.Darling.Analysis,Lite/Analysiscreation_timecompared against a$nwindow boundService/Mcp/nor either viewer is in its globsStoreSqlClockDisciplineTestsService/Mcp/:43-47: "a bare clock in a SET, a VALUES row or a projection is a different defect shape … deliberately out of scope"CollectorTimestampFrameTestsPerformanceMonitor.CollectorsServerLocalReadFrameDisciplineTests(#3202)Darling,Liteproduction.csdefault_trace_eventsby designThe gap is exactly the diagonal: a column whose frame
CollectorTimestampFrameTestsknows, reaching a consumer none of the four inspects.Why the frame cannot be keyed on the column name
The repo has already established this twice and both notes are worth keeping:
StoreSqlClockDisciplineTestsmaintainsAmbiguousFrameColumns = ["sample_time", "event_time", "last_execution_time"]— three names that are two frames across several tables each, with the evidence per table.CollectorTimestampFrameTests' own remarks record that its first cut was a store-wide "all naive timestamps are UTC" rule that would have forbidden the CPU collector's intentional local clock.So a guard here must be scoped per (table, column), and the census has to be derivable rather than hand-declared or it rots.
The technique that already works
#3202's
EveryAnnotationSourcesDeclaredFrame_MatchesItsOwnCollectorsQueryTextderives the frame from the collector's own query text instead of trusting a declaration: this codebase writesalias = expression, so the right-hand side is the provenance. A column assigned from the XE@timestampis UTC; one assigned fromfn_trace_gettable'sStartTimeor adm_exec_*/dm_tran_*DMV value is server-local. Critically, it fails when the provenance cannot be read rather than defaulting to UTC — "a frame nobody can read is the state the de-skew defects shipped in."Run over the whole collector corpus that classifier already resolves the population: 66
CollectorColumnType.Timestampcolumns, with 17 server-local columns reaching a consumer. It also finds its own blind spot honestly —BlockedProcessReportCollector's six andDmvBlockingSnapshotCollector.event_timehave no T-SQL assignment at all (they are parsed from XML in C#, or stamped fromcontext.CollectionTime), so those need a C#-side arm or an explicit per-column declaration with its evidence. That is the honest shape of the coverage, not a reason to skip them.What to decide before writing it
ToString("o")into an anonymous object) and the WPF render boundary (ForDisplay/FormatServerClock/FormatServerTimegetters) are different discriminators over different roots. Two focused scans probably beat one that has to understand both.ServerLocalReadFrameDisciplineTests.KnownReadersdoes it — a bare total lets a Darling site vanish and a Lite one appear and still add up, which is the one-sided-port regression De-skew query_stats.creation_time before comparing it to the analysis window (Part of #2991) #2992 found nothing guarding against.Floors to pin so a broken glob cannot report a clean bill of health, measured on
devate63a367e7: 131ToString("o")sites across 27 files inDarling/PerformanceMonitor.Darling.Service/Mcp/; 66 collector timestamp columns;ServerLocalReadFrameDisciplineTestsmeasured 713 production.csfiles acrossDarling/andLite/.Blocks on, or lands with, #3206 (MCP reads) and #3207 (desktop renders). Related: #3198, #3202, #2991/#2992, #2932.