Found while implementing #1837's probe-failure contract, and deliberately left out of that PR.
DatabaseSizeStatsCollector's per-database cursor (PerformanceMonitor.Collectors/DatabaseSizeStatsCollector.cs, around the #file_space INSERT) runs [db].sys.sp_executesql inside a TRY and discards every failure:
END TRY
BEGIN CATCH
END CATCH;
It is the same swallow shape #1837 closed for the enumerating collectors, with the same consequence: a database that is mid-restore, offline, or inaccessible to the login contributes no used_size_mb rows, the collector reports SUCCESS, and nothing anywhere says a database was skipped. Unlike the other empty CATCHes in this project (ServerPropertiesCollector, BlockedProcessReportCollector) this one is undocumented and drops whole rows rather than leaving one enrichment column NULL.
Why it was not fixed in #1837's PR. The contract that PR shipped is EnumeratedCollectorDriver.ReadEnumerationAsync: an ENUMERATION query may return an optional second result set of (item_name, error_text), which both runners read and summarize onto the collection_log row. database_size_stats is not an enumerating collector — it runs on the plain single-query path, where the one result set IS the payload that ICollectorDefinition.ReadAsync consumes. Giving that path a probe-failure channel means either
- extending
ReadAsync's contract so the plain path also calls NextResult after the payload (touches every definition's read contract, and needs a rule for the collectors that already use a supplemental query), or
- having the collector fold the failures into its own payload rows (needs a sentinel row shape, which then has to be filtered out of every read of
database_size_stats).
Both are design decisions, not a mechanical mirror of what #1837 shipped.
Scope when picked up: decide the plain-path channel, apply it to database_size_stats, and audit the other non-enumeration cursors for the same shape. The note/summary/log plumbing already exists (EnumeratedCollectorDriver.BuildNote, ProbeFailureLogTemplate, and the last_note / note_count columns on all three Collection Health reads) — only the collector-to-runner channel is missing.
Applies to both Lite and Darling (shared collector definition).
Found while implementing #1837's probe-failure contract, and deliberately left out of that PR.
DatabaseSizeStatsCollector's per-database cursor (PerformanceMonitor.Collectors/DatabaseSizeStatsCollector.cs, around the#file_spaceINSERT) runs[db].sys.sp_executesqlinside a TRY and discards every failure:It is the same swallow shape #1837 closed for the enumerating collectors, with the same consequence: a database that is mid-restore, offline, or inaccessible to the login contributes no
used_size_mbrows, the collector reports SUCCESS, and nothing anywhere says a database was skipped. Unlike the other empty CATCHes in this project (ServerPropertiesCollector,BlockedProcessReportCollector) this one is undocumented and drops whole rows rather than leaving one enrichment column NULL.Why it was not fixed in #1837's PR. The contract that PR shipped is
EnumeratedCollectorDriver.ReadEnumerationAsync: an ENUMERATION query may return an optional second result set of(item_name, error_text), which both runners read and summarize onto the collection_log row.database_size_statsis not an enumerating collector — it runs on the plain single-query path, where the one result set IS the payload thatICollectorDefinition.ReadAsyncconsumes. Giving that path a probe-failure channel means eitherReadAsync's contract so the plain path also callsNextResultafter the payload (touches every definition's read contract, and needs a rule for the collectors that already use a supplemental query), ordatabase_size_stats).Both are design decisions, not a mechanical mirror of what #1837 shipped.
Scope when picked up: decide the plain-path channel, apply it to
database_size_stats, and audit the other non-enumeration cursors for the same shape. The note/summary/log plumbing already exists (EnumeratedCollectorDriver.BuildNote,ProbeFailureLogTemplate, and thelast_note/note_countcolumns on all three Collection Health reads) — only the collector-to-runner channel is missing.Applies to both Lite and Darling (shared collector definition).