Release v2.9.0#911
Merged
erikdarlingdata merged 82 commits intomainfrom Apr 29, 2026
Merged
Conversation
Add Feature/auto scrolling
Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Add trailing newlines to ScrollPanBehavior files
…ving race Addresses security findings from #840: - #846: Escape single quotes in file paths interpolated into read_parquet() and COPY TO - #847: Use DuckDB $1 parameters for DateTime values instead of string interpolation - #849: Make IsArchiving volatile-backed to prevent stale reads across threads Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…ening Harden DuckDB queries and fix IsArchiving race condition
Moves Teams and Slack webhook URLs from plaintext settings.json/preferences.json to Windows Credential Manager (DPAPI-encrypted), matching the existing pattern used for SMTP passwords and SQL Server credentials. Includes automatic migration: on first settings load, any plaintext URLs are moved to Credential Manager and removed from the JSON file. Closes #848 Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Encrypt webhook URLs with DPAPI via Credential Manager
…rst visit Initial tab open and Refresh button now only load the currently visible tab. First switch to any tab triggers a full refresh of that tab (all sub-tabs). Subsequent refreshes only hit the active sub-tab. Ctrl+Click on Refresh Tab (or Ctrl+F5) refreshes all tabs at once. Apply to All Tabs retains existing full-refresh behavior. Fixes #835 — prevents heavy queries (e.g. GetQueryStatsAsync) from running on tab open when the user is only viewing Overview. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
GetQueryStatsAsync, GetProcedureStatsAsync, and GetQueryStoreDataAsync were returning unbounded result sets. With 49 databases and 742K rows in query_stats over 3 days, the GROUP BY with plan XML could produce thousands of rows and timeout after 120 seconds. TOP 500 ordered by avg CPU desc is plenty for a grid view and prevents the query from consuming unbounded memory on large installations. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Lazy-load server tabs and cap query grid results to TOP 500
The CAST(DECOMPRESS(...)) NOT LIKE N'WAITFOR%' filter was decompressing query text on every row in query_stats and query_store_data just to skip WAITFOR queries. WAITFOR has no plan and no meaningful stats — it only matters in query snapshots (active sessions), where the filter remains. On a 742K-row query_stats table, this was a significant contributor to the 120-second query timeouts reported in #835. The snapshot filters (report.query_snapshots) and MCP phased queries are untouched — they filter after TOP on already-hydrated text. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
All three grid queries now use a 3-phase pattern: 1. Aggregate numerics into temp table (no DECOMPRESS) 2. Sum across lifetimes, rank TOP 500 3. OUTER APPLY to decompress text/plan for only the 500 winners On a 742K-row query_stats table, this reduces DECOMPRESS calls from 742K to 500 — eliminating the 16+ minute query times reported in #835. Matches the existing phased pattern used by the MCP query tools. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…press Remove WAITFOR DECOMPRESS filters from query stats and query store
TDE moved to Standard Edition in SQL 2019, so dm_db_persisted_sku_features no longer reports it as Enterprise-only. Add version check to give version-appropriate licensing guidance instead of falsely claiming no databases use TDE. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…on-awareness Fix FinOps TDE recommendation on SQL Server 2019+
Port PS PRs #216, #217, #219, #224, #229, #230, #231 to PM. PlanAnalyzer changes: - Rule 5: Suppress for Key Lookups (point lookups mislead per-execution estimates) - Rule 8: Enhanced parallel skew with batch mode sort detection and practical context - Rule 9: Large memory grant shows top 3 consumers sorted by row count - Rule 10: Key lookup overhaul — show output columns, check predicate filtering, softer advice - Rules 11/12/29: Suppress on 0-execution nodes (operator never ran) - Rule 11: I/O wait severity elevation when scan hits disk - Rule 24: FormatNodeRef helper includes object name for data access operators - Rule 26: Suppress when row goal prediction was correct, specific cause detection - Wait stats: DescribeWaitType with full wait type coverage, multi-wait summary - New helpers: GetWaitLabel, HasSignificantIoWaits, IdentifyRowGoalCause, FormatNodeRef - GetOperatorOwnElapsedMs changed to internal for BenefitScorer access BenefitScorer (new file): - Stage 1: MaxBenefitPercent for operator-level rules (filter, spill, lookup, etc.) - Stage 2: Wait stats benefit scoring with parallel allocation (Joe's formula) PlanModels additions: - MaxBenefitPercent and ActionableFix on PlanWarning - WaitBenefit class and WaitBenefits list on PlanStatement Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…apr16 Sync PlanAnalyzer + BenefitScorer from PerformanceStudio (Apr 9-16)
…857) On Azure SQL DB, some logins (e.g. Microsoft Dynamics 365 FO) are granted access only to a specific user database and not to master. The three collectors that enumerate databases via master — query_stats, database_size_stats, file_io_stats — would fail the first time and produce an empty screen. GetAzureDatabaseListAsync now catches known access-denied/login-failed errors from the master connection, caches the per-server decision, and returns the connection's InitialCatalog as a single-element list. The three callers already loop per-database, so single-DB mode works without further changes. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…lback Fall back to single-DB mode when Azure master is inaccessible (#857)
Phase 3 OUTER APPLY hydration of compressed query_text/plan_text was forcing an Eager Index Spool over the full collect.query_stats table (and similar for procedure_stats / query_store_data), which took 104 seconds on a 742K-row table in #835. Changes: - Remove CONVERT(binary(8), nvarchar-hash, 1) anti-pattern from OUTER APPLY WHERE clauses by keeping query_hash as native binary(8) in temp tables. query_hash is only converted to nvarchar(20) in the final output projection. - Add three nonclustered indexes (install script and upgrade script): IX_query_stats_hash_lookup (query_hash, database_name, collection_time DESC) IX_procedure_stats_name_lookup (database_name, schema_name, object_name, collection_time DESC) IX_query_store_data_id_lookup (database_name, query_id, collection_time DESC) - Indexes use SORT_IN_TEMPDB = ON and DATA_COMPRESSION = PAGE. - ONLINE = ON is applied conditionally via dynamic SQL based on SERVERPROPERTY('EngineEdition') — Enterprise/Developer/Azure only, since Standard/Web/Express don't support online index operations. Tested against CADelete's 742K-row table: Phase 3 went from 104s to well under 1s (5s total for the full three-phase query). Fixes #835 Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…exes Add nonclustered indexes for query/procedure/query store lookups
On Azure SQL Database, logins without access to master can't resolve cross-database rows returned by sys.dm_exec_requests, which caused the Live Snapshot button and the query snapshots collector to error in D365FO-style environments (reported by @TrudAX in #857 after PR #858). BuildQuerySnapshotsQuery now takes an isAzureSqlDatabase flag and emits AND der.database_id = DB_ID() only when true. Boxed SQL Server, MI, and elastic pool behavior is unchanged. The Live Snapshot button path gets the flag through a new ServerTab constructor parameter wired from the cached ServerConnectionStatus.SqlEngineEdition. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…ure-scope Scope query snapshots to current database on Azure SQL DB (#857)
- Chart X-axis prints the date line only on the first tick and on ticks where the date changes; all other ticks show time only. Format respects current culture (en-GB → dd/MM, de-DE → dd.MM, 24h clocks, etc.). Implemented as a DateTimeTicksBottomDateChange() extension in Lite/Helpers/AxesExtensions.cs and applied to every DateTimeTicksBottom call site in ServerTab and CorrelatedTimelineLanesControl. - Server name no longer duplicated in the ServerTab header status line; ConnectionStatusText now shows just "Connecting..." / "Last refresh: ...". - Chart tick label font bumped from 12 to 13 for readability. - New SubTabItemStyle (thin accent underline, transparent background) in all three themes, applied to Queries / Memory / File I/O / Blocking / Perfmon / Running Jobs sub-TabControls so sub-tab selection no longer looks identical to main-tab selection. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…lish Polish Lite chart axes and sub-tab styling
Dashboard polish (ports the same items merged to Lite in #862): - New Dashboard/Helpers/AxesExtensions.cs with DateTimeTicksBottomDateChange(), culture-aware (dd/MM for en-GB, dd.MM for de-DE, 24h clocks, etc.). All 52 call sites of DateTimeTicksBottom() across 10 files swapped to use it. - TabHelpers.ApplyTheme + ReapplyAxisColors bump chart tick label font from 12 to 13 so numbers read cleaner on wide charts. - SubTabItemStyle added to Dark / Light / CoolBreeze themes: thin accent underline + transparent background instead of filled cyan, so sub-tabs don't look identical to main tabs when selected. Wired via ItemContainerStyle on 11 sub-TabControls (Overview's inner tabs, Collection Health's inner tabs, Locking, ConfigChanges, CurrentConfig, FinOps, Memory, ResourceMetrics ×2, SystemEvents, QueryPerformance). LSP diagnostics cleanup (tracked work from chore/lsp-diagnostics-cleanup): - Small nullability/warning fixes across Dashboard and Lite services, analysis helpers, and BenefitScorer / PlanAnalyzer. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…eanup Port Lite chart/tab polish to Dashboard + LSP diagnostics cleanup
Root cause: the control wired `Unloaded += ...Dispose()` on the crosshair manager, and WPF fires Unloaded for transient reasons (tab virtualization, layout rebuilds, etc.), not just when the control is actually going away. Dispose() clears the manager's lane list, after which ReattachVLines runs over an empty list and the crosshair is gone permanently. Changes: - Remove the Unloaded → Dispose() handler in both Lite and Dashboard copies. The manager holds only managed state (a Popup + lane references) — GC will clean it up with the control. - Remove the now-redundant `_isRefreshing` flag from CorrelatedCrosshairManager. The `lane.VLine == null` check in OnMouseMove is a sufficient "not ready" guard and is self-healing once VLines are recreated. - Wrap ReattachVLines in a try/finally on the control side, with a new idempotent EnsureVLinesAttached() safety net that only creates VLines for lanes where they're still null. - Make CreateVLine catch per-lane exceptions so one failing chart can't prevent the others from recovering. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Pulls in two upstream bugfix releases relevant to Lite's collector pattern: - 1.5.2 fixes unbounded row group growth on indexed tables under repeated load+insert cycles, and memory leaks/race conditions in prepared statements. - 1.5.1 hardens WAL checkpoint marking, prevents memory corruption in concurrent TrimFreeBlocks, and improves Windows UTF-8/UTF-16 handling. No storage version change within 1.5.x. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Patch-level upgrades only: - Microsoft.Extensions.Configuration / Configuration.Json / Hosting / Logging: 10.0.5 -> 10.0.7 (Dashboard, Lite) - System.Text.Json: 10.0.5 -> 10.0.7 (Lite) - ScottPlot.WPF: 5.1.57 -> 5.1.58 (Dashboard, Lite) Microsoft.Data.SqlClient (6.1.4 -> 7.0.1) and ModelContextProtocol (0.7.0-preview.1 -> 1.2.0) intentionally left out — both deserve dedicated PRs after a focused review. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Bump DuckDB.NET to 1.5.2
Bump safe NuGet packages: M.Extensions 10.0.7, System.Text.Json 10.0.7, ScottPlot 5.1.58
SqlClient 7.0 split Azure/Entra dependencies out of the core package, so projects with Entra-Interactive auth paths (ActiveDirectoryInteractive) also need the new Microsoft.Data.SqlClient.Extensions.Azure helper to keep MFA login working at runtime. Bumps to 7.0.1 across: - Dashboard (+ Extensions.Azure 1.0.0) - Lite (+ Extensions.Azure 1.0.0) - Installer.Core (+ Extensions.Azure 1.0.0; transitive via Installer/InstallerGui/Installer.Tests) - InstallerGui (+ Extensions.Azure 1.0.0) - Installer (no Extensions.Azure — no Entra path) - Installer.Tests (no Extensions.Azure — no Entra path) Connection strings already set Encrypt explicitly everywhere, so the 4.0-era default flip is a no-op for this repo. SQL Server 2012+ remains supported (so all of 2016/2017/2019/2022/2025 stay reachable). Verified: - All six projects build clean - Installer.Tests: 46/46 passing against real SQL - Lite.Tests: 257/257 passing against real SQL - Dashboard and Lite launch and stay running Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Bump Microsoft.Data.SqlClient to 7.0.1 (+ Extensions.Azure for Entra)
Moves Dashboard and Lite from the 0.7.0-preview.1 SDK to the stable 1.2.0 release. The C# SDK landed 1.0 between these two points and the codebase happens to use only the stable subset of the surface (attributes, AddMcpServer/WithHttpTransport/WithTools<T>/MapMcp, DI-bound tool methods) — none of the breaking changes (filter API rename, RequestContext ctor, RunSessionHandler, binary-content types, McpServerHandlers, legacy SSE) touch this repo. 154 [McpServerTool] sites and 39 [McpServerToolType] sites compile unchanged. Zero source code changes — packaging only. Verified: - Dashboard and Lite build clean (0 errors) - Lite launches; the in-process MCP server starts on :5151 - A POST initialize against the new Streamable HTTP transport returns the full server capabilities and tool descriptions Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Bump ModelContextProtocol to 1.2.0
Patch-level upgrade in the two test projects (Installer.Tests, Lite.Tests). Test-only — no shipping code touched. Verified: Installer.Tests 46/46, Lite.Tests 257/257 passing. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
….4.0 Bump Microsoft.NET.Test.Sdk to 18.4.0
ExecuteInstallationAsync applied StandardTimeoutSeconds (300s) to every batch in the main install script list. 98_validate_installation.sql runs every enabled collector with @debug = 1 via a cursor in a single batch, which on large databases (e.g. 7M-row collect.query_stats) takes longer than 5 minutes and fails the entire install/upgrade. ExecuteAllUpgradesAsync already uses UpgradeTimeoutSeconds (3600s) for upgrades/{from}-to-{to}/ scripts (cfd7d6e, #538/#539). Apply the same ceiling to the main install loop so files like 98_validate_installation and large-table DDL get the same hour instead of the 5 minutes that was only ever a comfortable default for small databases. Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
- New "Purge Now" button on Manage Servers window with override modes (configured / 1 / 3 / 7 / custom / all). All option uses TRUNCATE. - Right-click menu now mirrors all per-row actions (Edit, Toggle Favorite, Check Server Version, Purge Now, Remove) above existing copy/export. - config.data_retention reworked: @retention_days = NULL respects per-collector schedule, 0 TRUNCATEs every collect.* table, N > 0 overrides every cutoff to N days. Old @truncate_all parameter removed; @retention_days = 0 covers that case. Truncate path snapshots row count before wiping for reporting. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…d-manage-servers-context-menu Add Purge Now action to Manage Servers (closes #900)
The CPU alert and headline previously only used SQL Server's scheduler ProcessUtilization, which answers "how busy are SQL's schedulers" — not "is the box in trouble." On a noisy host that distinction matters. Changes (Lite): - Overview cards now show total non-idle CPU prominently with the SQL number alongside, e.g. "64% (SQL 60%)". Color tracks the alert metric. - New CpuAlertMode enum (Total / SqlOnly), default Total. Settings has a "measured as" dropdown next to the CPU threshold. - Alert evaluator and tray notifications use CpuPercentForAlert and label the value as "Total CPU" or "SQL CPU" so users know which metric tripped. - Persists alert_cpu_mode in settings.json. No data model or schema changes — sqlserver_cpu_utilization and other_process_cpu_utilization were already collected; only the presentation/alert layer needed work. Dashboard mirror is a follow-up. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…le-cpu-alert Lite: surface total non-idle CPU + alert toggle (closes #899)
…manceStudio Ports PerformanceStudio PRs #285 and #288 (net result; the temporary R/D/G overlay from #285 was replaced by real icons in #288). PlanIconMapper.GetIconName now takes optional storageType and logicalOp: - Columnstore scans (Clustered/Index Scan with Storage="ColumnStore" on the Object element) route to the columnstore_index_* icons. Covers both CCI and NCCI for scan/delete/insert/update/merge. - The three Parallelism subtypes (Repartition/Distribute/Gather Streams) route to their own icons instead of all sharing parallelism.png. ShowPlanParser: the IconName assignment moves from immediately after PhysicalOp parsing to after StorageType and LogicalOp are populated, so the new routing has the inputs it needs. Three new icons (MIT-licensed contribution from @rferraton via PS #288) added to both Dashboard and Lite Resources/PlanIcons. The existing Resource glob in each csproj picks them up automatically. Last upstream sync from PerformanceStudio was 2026-04-16 (#856), scoped to PlanAnalyzer + BenefitScorer. This is a follow-up scoped to plan-viewer icon routing. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
When the Off preset, an Agent stoppage, or a server reboot pauses collection for hours, the next run of query_stats / procedure_stats / query_store would dump everything that accumulated during the gap into their delta tables in one go. On query_stats specifically (issue #885), that was enough to blow tempdb overnight. Each of the three procs now reads MAX(config.collection_log.collection_time) for its own collector_name (where status = SUCCESS) right after computing the normal cutoff. If the gap to now exceeds 5x the configured frequency (or 30 minutes, whichever is larger), it clamps the cutoff to SYSDATETIME() so only forward-going data is collected on the resume run. NULL/0 frequency_minutes safely floors to 30 minutes. XE-backed collectors (blocked_process_xml, deadlock_xml, system_health, default_trace, trace_analysis) are bounded by their own @minutes_back / @hours_back parameters and don't have the catch-up problem, so they're left alone. Snapshot collectors (wait_stats, file_io_stats, etc) insert one row per run regardless of gap and were never at risk. Verified on sql2016/2017/2019/2022/2025: all three procs deploy cleanly, heuristic fires on a 3-hour synthetic gap, stays quiet on normal runs. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…etection Skip historical sweep when collectors resume after a gap (closes #892)
…tore-icons-from-ps Sync columnstore + Parallelism subtype icons from PerformanceStudio
New config.collector_database_exclusions table holds a per-server list of user databases to skip in per-database collectors. The eight collectors that iterate sys.databases now honor it via a NOT EXISTS filter: query_stats, query_store, procedure_stats, file_io_stats, waiting_tasks, database_configuration, database_size_stats, server_properties. System databases (master/tempdb/model/msdb) and the PerformanceMonitor database itself remain hardcoded skips in the collectors and are not represented in the exclusions list. Dashboard side: - Manage Servers window gets a new "Excluded Databases" button (and matching context menu entry) between Check Server Version and Purge Now. - Default window width bumped 780 → 960 so all per-row buttons fit on first open without resizing. - New ExcludedDatabasesDialog modal: live-queries sys.databases on the target, pre-checks current exclusions, hides system DBs, shows stale entries (in list but not on server) greyed and disabled with "(missing)". Save replaces the table contents transactionally. - ServerManager.GetUserDatabasesAsync, GetCollectorDatabaseExclusionsAsync, and SaveCollectorDatabaseExclusionsAsync handle the connection plumbing. Schema is added in install/01 (initial install) and mirrored in install/03 inside config.ensure_config_tables (resilient re-creation). No upgrade folder needed — installer re-runs install/01 on existing installs and the IF OBJECT_ID guard fires. Verified end-to-end by running the CLI installer against sql2019, then excluding hammerdb_tpcc and confirming database_size_stats_collector skipped it (0 rows) while StackOverflow2010 was still collected. Lite side will follow in a separate PR (different storage model — Lite keeps the exclusion list in servers.json since it doesn't install on targets). Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…-exclusions Per-database exclusions for collectors — Dashboard side (#887)
Lite-side companion to PR #905 — gives users a per-server way to skip specific databases in the per-database collectors. Storage: ExcludedDatabases (List<string>) added to ServerConnection, persisted via the existing servers.json round-trip. Lite doesn't install on targets, so the list lives client-side instead of in a remote config.collector_database_exclusions table the way Dashboard does it. Wiring: 9 collectors get the filter — query_stats, query_store, procedure_stats, query_snapshots, file_io_stats, waiting_tasks, database_configuration, database_scoped_configurations, database_size. Azure-mode collectors that route through GetAzureDatabaseListAsync get exclusions automatically since the helper now applies the filter centrally. Two SQL helpers on RemoteCollectorService: - BuildDatabaseExclusionFilter — parameterized AND <col> NOT IN (@excl_db_N). Used by every collector whose query is plain (non-dynamic) T-SQL. No compatibility-level dependency (avoids OPENJSON / STRING_SPLIT which require compat 130+ on the connection database). - BuildDatabaseExclusionLiteralClause — N'name' literals with single-quote escaping (and a forNestedDynamicSql=true mode that doubles the escape). Used by procedure_stats which builds @SQL then passes to sp_executesql, where parameter binding inside the dynamic statement is awkward. Names come from a user-picked checklist, so literal interpolation with proper escaping is safe. UI: ManageServersWindow gets a new "Excluded Databases" button between Edit and Delete. Right-click context menu now mirrors the buttons — Edit / Excluded Databases / Delete on top, then the existing Copy/Export items below a separator. New ExcludedDatabasesDialog mirrors the Dashboard version: live-queries sys.databases, hides system DBs, pre-checks current exclusions, shows stale entries (in list but not on server) greyed with "(missing)" tag. Save calls ServerManager.UpdateServer to persist via servers.json. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…abase-exclusions Per-database exclusions for collectors — Lite side (closes #887)
Architecture overview of the collection pipeline for both Full and Lite editions: the minute loop, dispatcher, collector shape, schedule table, retention, Dashboard read path, and where-to-look-next pointers for new contributors. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Add docs/how-collection-works.md
…ll, version bumps - New Installed Version column in Manage Servers for both editions: * Full: probes config.installation_history per server in parallel * Lite: shows the running app version (mirrors Full's header for consistency) - Back-ports the Ellipse-with-DataTriggers status dot and right-aligned favorite star from Lite's server list to the Full Dashboard - Bumps Version/AssemblyVersion/FileVersion/InformationalVersion to 2.9.0 in Dashboard, Lite, Installer, and Installer.Core - Rewrites CHANGELOG: fixes the 2.8.0 date to 2026-04-22 (was TBD), moves Off preset (#888) to 2.9.0 since #891 landed after the v2.8.0 tag, and adds the full 2.9.0 entry covering the post-2.8.0 PR set - Updates README's DuckDB version reference (1.5.0 -> 1.5.2) Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
…ersion-column Release v2.9.0: Manage Servers version column, Lite-style indicators in Full, prep
# Conflicts: # CHANGELOG.md # Dashboard/Dashboard.csproj # Dashboard/Themes/CoolBreezeTheme.xaml # Dashboard/Themes/DarkTheme.xaml # Dashboard/Themes/LightTheme.xaml # Installer.Core/Installer.Core.csproj # Installer/PerformanceMonitorInstaller.csproj # Lite/Controls/ServerTab.xaml # Lite/Controls/ServerTab.xaml.cs # Lite/PerformanceMonitorLite.csproj # Lite/Services/RemoteCollectorService.QuerySnapshots.cs # Lite/Services/RemoteCollectorService.cs
Merge main into dev to resolve v2.8.0 squash divergence (release v2.9.0 prep)
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.
Summary
Release v2.9.0.
config.collector_database_exclusionstable on the Full side filters 8 collectors; Lite storesExcludedDatabasesper server inservers.jsonand filters 9 collectors (Per-database exclusions for collectors #887)query_stats,procedure_stats, andquery_storeskip the historical sweep on first run after an Off preset, Agent stoppage, or server reboot, preventing tempdb blowouts ([FEATURE] Implementing blackout window(s) to skip data entirely. #892)CpuAlertModetoggle drives both alert evaluation and headline color ([FEATURE] CPU alerts: surface total non-idle CPU, not just SQL Server scheduler % #899)config.data_retentionsemantics —@truncate_allremoved,@retention_daysdoes the right thing ([FEATURE] Add a native “Purge Now” action to the Dashboard / Control Panel #900) — breaking change for Agent jobs calling the old proc signatureOffcollection preset — disables every collector in one call; pair with a second Agent job for overnight scoping (Add 'Off' collection preset + teach apply_collection_preset to mutate enabled #888)Microsoft.Data.SqlClient6.1.4 → 7.0.1 (+Extensions.Azure 1.0.0for Entra),ModelContextProtocol0.7.0-preview.1 → 1.2.0,DuckDB.NET1.5.0 → 1.5.2, plus patch-level Microsoft.Extensions / System.Text.Json / ScottPlot / Test.SdkCHANGELOG also fixes the v2.8.0 entry's date (was
TBD— actual ship date 2026-04-22) and moves theOffpreset (#888) out of 2.8.0 into 2.9.0 since #891 landed after the v2.8.0 tag.See CHANGELOG.md for the full list.
Test plan
Installer.Tests— 46/46 passeddotnet build -c Debug— 0 errors--reinstall) — 54/54 scripts, 45 collectors, 0 errorsconfig.collection_logacross all 5 servers (sql2016/2017/2019/2022/2025)installation_historySUCCESS with correctprevious_versionacross all upgrade paths2.9.0-nightly.20260429) green🤖 Generated with Claude Code