Repository navigation
Analysis facts, drill-downs and anomaly counts for blocking and deadlocks count events by when they happened, in both apps - #4913
Merged
Conversation
… and deadlocks that belong to databases monitored as their own targets
…s for databases monitored as their own targets
… from the live store set, by store id
…ases, and the deadlock every-process rule lives in one place
…he sustained-blocking template warns about a master target
…findings skip databases monitored as their own targets
…indings skip databases monitored as their own targets
…ck findings skip databases monitored as their own targets
…k findings skip databases monitored as their own targets
…its closing parenthesis, since another argument now follows it
…ence and fact reads
BLOCKING_CHAIN and the blocking/deadlock drill-downs skip databases monitored as their own targets.
The fact and compare reads fill the list like AnalyzeAsync. The deadlock count counts a deadlock whose
victim database is outside the list in SQL and parses graphs only for the rest. {SCOPE} sits at the end
of its line so an empty list gives the old text. The static provider is internal and a throwing provider
falls back to unscoped.
… master target; bound the deadlock graph read BLOCKING_CHAIN drops pairs of databases monitored as their own targets. The top-deadlock and top-blocking drill-downs apply the same rule. Deadlocks whose named victim database is not separately monitored are counted in SQL and their graphs are not read; the anomaly path uses the detector's command timeout. The list is passed raw and both sides fold with one lower(). MCP analyze_server and the web read tools resolve the list per call from the live registry.
… and recognises Azure SQL Database by its stored engine edition
…ostgreSQL deadlock capture count events by when they happened, not when they were collected
…indow on the event time
…d row is checked by its graph, and the unscoped text is unchanged
…a failing scope resolver degrades to unscoped
…downs, including the Azure master scoped variants, window blocked-process reports and deadlocks on when the event happened, and the PostgreSQL deadlock capture on occurred_at with a collection_time fallback
…, including the Azure master scoped variants, count blocked-process reports and deadlocks by when they happened, and the seeders that set no event time now set it equal to the collection time
…ected event, so the event-time count differs from the collection-time one
…stamp pg deadlock read pin, and floor pin for the two chain reads
… MCP deadlock reader stamps, sorts and identifies a NULL-occurred_at report by its collection time
…s a pinned, deliberate difference from Darling's continuous aggregate
# Conflicts: # Darling/PerformanceMonitor.Darling.Analysis/PgAnomalyDetector.cs # Darling/PerformanceMonitor.Darling.Analysis/PgDrillDownCollector.Blocking.cs # Darling/PerformanceMonitor.Darling.Analysis/PgFactCollector.Waits.cs # Lite.Tests/AzureMasterAnalysisScopeTests.cs # Lite/Analysis/AnomalyDetector.cs # Lite/Analysis/DrillDownCollector.Blocking.cs # Lite/Analysis/DuckDbFactCollector.Waits.cs # Lite/Analysis/SeparatelyMonitoredScope.cs
…tch checks (xUnit2013)
erikdarlingdata
marked this pull request as ready for review
October 1, 2026 18:21
erikdarlingdata
added a commit
that referenced
this pull request
Oct 1, 2026
Dev moved the blocking reads to event_time (#4909, #4913). A read that now windows on event_time calls StoredEventCopies without collectedFrom and keeps its event_time bounds in its filter: a stored copy keeps its first copy's event_time, so both are inside the window or both are outside it. The alert engine's read of blocked process reports still windows on collection_time, so it keeps collectedFrom. OnEventTime now swaps only the events CTE's own local-clock keys and window. Swapping every collection_time in the CTE would also rewrite the copy rule inside the blocking baseline's source, and that rule must stay on collection_time.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Builds on #4906 (an Azure SQL Database master's analysis findings skip separately monitored databases), which rewrote these same queries and is now merged; this PR's diff against dev is the window columns below.
What a user saw
The analysis findings, the drill-downs and the anomaly detector counted blocked-process reports (BPRs) and deadlocks by when they were COLLECTED. The grids and cards count by when the event HAPPENED (#4909). So a finding could cite a deadlock count for its window that the Deadlocks grid for the same window doesn't show.
What changed
Every analysis read of
blocked_process_reportsanddeadlocksnow windows, and buckets, on the event's own time.Darling: each read is now the event column in the window, plus
collection_time >= EventWindowFloor.For(start)(#3895), with no upper bound oncollection_time.date_binbucket);pg_deadlocks(PostgreSQL targets): the exemplar count, the exemplar list and the MCP deadlock reader now agree. Each isCOALESCE(occurred_at, collection_time)in the window, plus the floor.occurred_atis nullable, and a row without one counts by its collection time, as it did before. The MCP reader already usedoccurred_atbut dropped a row without one; the fact and the drill-down usedcollection_time. The MCP reader also stamps, sorts and builds its report identity from the same expression, and the detail lookup matches on it, so a row withoutoccurred_atis listed by its collection time (not as 0001-01-01 at the top of the page) and its identity resolves.Lite: the event predicate alone. The reads:
collection_time, because coverage means when the collector ran.EventBaselineSqlitself is unchanged: it's pinned byte-identical to Darling's.Left alone, and why
event_timeIS its collection time.collection_timefloor, like every other read here.Pins
EventTimeAnalysisReadsLiveTests: three rows per table:The facts (both forms), the anomaly counts (both forms), the drill-downs and the
pg_deadlocksreads count b and c, not a. The a/b/c row counts differ per table, so a collection-time window can't match by accident. Forpg_deadlocks, a fourth row with nooccurred_atcounts by its collection time.EventTimeAnalysisReadsTests: the same rows through the facts, the drill-downs, the anomaly counts and the baselines. An event at 10:58 collected at 11:03 lands in the 10:00 baseline bucket.PgDeadlockRemaskTestsbinds the exemplar list's new floor parameter,PgTargetDeadlockDrillDownTestsasserts the COALESCE form, andLocalClockBucketKeyTestsreads the event column in the baseline's local-clock day.DarlingEventBaselineCoveredDaysTestsstill pins the same shared baseline body and collectors in both products, and now also pins the deliberate difference: Lite's Blocking and Deadlock arms wrap it withOnEventTime(..., "event_time")and(..., "deadlock_time"), and Darling's continuous-aggregate arms don't wrap.TopDeadlocksSkippingSeparateSql,TopBlockingChainsSkippingSeparateSql, bothDeadlockOutsideCountSqlcopies andBlockingSkippingSeparateCountSql. Lite's scoped deadlock count and its chain/fact scoping moved the same way. The reconstructed chains were already on the event time.$4. A scoped read keeps Azure SQL Database: a monitored master's analysis findings no longer repeat the blocking and deadlocks of databases monitored as their own targets #4906's list at$4and takes the floor as$5. Every caller binds the list first, then the floor.["GP"]overHSrows), which exercises Azure SQL Database: a monitored master's analysis findings no longer repeat the blocking and deadlocks of databases monitored as their own targets #4906's skipping variants. Lite adds scoped cases for the deadlock fact and the top deadlocks.occurred_atreader pin (the stamp, the sort and the identity round trip), andBlockingChainReadsFloorTests(2 of 2).EventBaselineCoveredDaysTests, Lite'sAnomalyTileWindowEndTests, andAzureMasterAnalysisScopeTests.SeedBprAsync.AnomalyTileWindowEndTeststext pin counts the open-ended window onevent_time < $3/deadlock_time < $3as well, and still rejects the closed spellings.3653d8efb.EventTimeAnalysisReadsLiveTestsfailed 6 of 6, on assertions:BlockingAndDeadlockFacts_…(plain and Azure-master forms);AnomalyDetectorCurrentWindowCounts_…(both forms);DrillDownTopDeadlocksAndTopChains_…;PgDeadlockCapture_CountsByOccurrenceWithTheCollectionTimeFallback_….CI's RED run was skipped while Actions is degraded.
collection_time. Every pin seeds row (a) (happened before the window, collected inside it) and row (c) (happened inside it, collected after it ended). The old predicate counts (a) and drops (c).BlockingEventsFact_…andDeadlocksFact_…seed a second (c) row and assert a count of 3 (b + 2c). The old read counts a + b = 2.TopDeadlocks_…asserts victims[c, b], andTopBlockingChains_…waits[300, 200]. The old read returns a and b.AnomalyDetector_CurrentCounts_…asserts 6 events (3 b + 3 c). The old read counts 1 a + 3 b = 4.BaselineBuckets_CountEventsByWhenTheyHappened(blocking and deadlocks) asserts that the 10:58-event / 11:03-collected row lands in hour 10 and not 11. The old read buckets by collection, into hour 11.AzureMasterAnalysisScopeLiveTests,AnomalyDetectorErrorGuardLiveTests,AnalysisCoverageLivePostgresTests,AnalysisFactsReadRunsDetectorParityTests,CountFamilyZeroHistoryTests,DarlingAnomalyBaselineTests,PgTarget*,PgDeadlockRemaskTests,PgFactCollectorTests,McpPageContractTests,DarlingAnalysisPipelineTests,AnomalyTileWindowEndTests,AzureMasterScopeTestsand Azure SQL Database: a monitored master's analysis findings no longer repeat the blocking and deadlocks of databases monitored as their own targets #4906's new classes. Lite.Tests builds with 0 errors; CI runs it.CHANGELOG
The collection-time windows shipped in v3.8.0, so this is a Fixed entry.
SECTION: Fixed
ENTRY: - Analysis findings, drill-downs and anomaly checks count blocking and deadlocks by when they happened, matching the grids ([#4913]) - These reads counted events by when they were collected, so a finding's count for a window could differ from the grid's for the same window. On PostgreSQL targets, the deadlock fact, drill-down and MCP reader now also agree, and a deadlock without a timestamp is counted by when it was collected.
REF: [#4913]: #4913