Skip to content

Release v1.2.0#115

Merged
erikdarlingdata merged 64 commits intomainfrom
dev
Feb 18, 2026
Merged

Release v1.2.0#115
erikdarlingdata merged 64 commits intomainfrom
dev

Conversation

@erikdarlingdata
Copy link
Owner

Summary

Release v1.2.0 — one week birthday!

New Features

Bug Fixes

Infrastructure

Test plan

  • All 4 projects build with 0 errors, 0 warnings
  • Dashboard and Lite tested side by side with updated packages
  • 5-minute log monitoring shows no errors or crashes

erikdarlingdata and others added 30 commits February 15, 2026 12:41
Materialize the ring buffer XML into a table variable before shredding
with CROSS APPLY .nodes(). The inline subquery pattern forced SQL Server
to repeatedly parse the full 4MB+ XML blob, causing 2+ minute execution
times and 30-second CommandTimeout failures during sustained load.

Applied to all 4 XE ring buffer queries:
- Deadlock collection (on-prem + Azure SQL DB)
- Blocked process report collection (on-prem + Azure SQL DB)

Performance: ~2:44 → ~0.46s (~350x improvement).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…-timeout

Fix XE ring buffer query timeouts on large buffers
Surface the existing GetCollectionHealthAsync() data in a new tab showing
per-collector status, run counts, failure rates, avg duration, timestamps,
and last error message. Includes column-level filtering.

The backend data (collection_log table, health computation) already existed
but was never displayed in the UI — only accessible via status bar tooltip
or MCP tool.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…th-view

Add Collection Health tab to Lite UI
Expand the Collection Health tab into three sub-tabs:

- Health Summary: existing per-collector status grid (from #39)
- Collection Log: recent collection_log entries showing per-run timing
  (total, SQL, DuckDB split), rows collected, status, and errors
- Duration Trends: ScottPlot chart showing collector duration over time

Also adds:
- GetRecentCollectionLogAsync() query and CollectionLogRow model
- "Open Log File" button to open today's log in default editor
- Column-level filtering on the collection log grid

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nostics

Add collector performance diagnostics to Lite UI
…column

- SafeToDecimal() guards against Infinity/NaN from SQL Server float columns
  that crash Convert.ToDecimal() (e.g. query_cost in dm_exec_query_memory_grants)
- Add Last Error At timestamp column to Health Summary grid so users can tell
  when an error occurred, not just what it was
- Add last_error_time to GetCollectionHealthAsync() query

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…erflow

Fix query_cost overflow and add Last Error At column
Replace hardcoded US-style date formats (MM/dd, MMM d, h:mm tt) with the
"g" general format specifier which respects the user's system locale.

Dashboard:
- ServerConnectionStatus: "Checked" and "Online since" timestamps
- ManageServersWindow: Last Connected column
- CollectorScheduleWindow: Last Run and Next Run columns

Lite:
- ServerConnectionStatus: same "Checked" and "Online since" timestamps
- CollectorHealthRow/CollectionLogRow: all formatted timestamp properties

Does not change the time range picker (AM/PM hour list) — that needs a
separate design discussion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change hour picker from "12 AM", "1 AM", ... "11 PM" to
"00:00", "01:00", ... "23:00". Consistent with chart axis labels,
SQL Server log conventions, and international users.

Parse logic is index-based (SelectedIndex 0-23) so no functional change.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…atetime

Use locale-aware date/time formatting throughout UI
The custom date range was already in server time (from LocalToServerTime),
but the chart axis limit code added UtcOffsetMinutes again, shifting the
X-axis by the server's UTC offset. With UTC-8 this caused an 8-hour shift
(e.g. picking 8 AM-12 PM showed 12 AM-4 AM on the axis).

Fixed in all 4 chart methods: blocking trend, deadlock trend, wait stats,
and perfmon.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…-fix

Fix chart X-axis timezone double-conversion
AlertStateService rewritten with JSON persistence (alert_state.json)
for silenced servers and acknowledged alerts. Acknowledgement now uses
timestamps instead of count comparison — switching time ranges no longer
re-triggers dismissed alerts. Only genuinely new events (collected after
the ack time) clear the acknowledgement.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wait stats chart now has a Metric dropdown to switch between:
- Wait Time (ms/sec): existing per-second rate (default)
- Avg Wait Time (ms/wait): delta_wait_time_ms / delta_waiting_tasks

Shows which waits are individually painful vs just high volume.
Both Dashboard and Lite get the toggle, hover tooltip unit updates
to match, and Lite summary grid gains AvgWaitMsPerTask property.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
#53)

Dashboard: SettingsWindow was creating its own UserPreferencesService
instance, so preference changes weren't visible to MainWindow's instance
(stale in-memory cache). Now shares the same instance via constructor
injection.

Lite: SystemTrayService always hid window on minimize with no preference
check. Added App.MinimizeToTray property, wired to settings.json
(key already existed but was unused), added checkbox to Settings UI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix minimize-to-tray setting ignored in both apps (#53)
…ide (#52, #56-59)

New alert types for both Dashboard and Lite: Long-Running Queries,
Poison Waits, TempDB Space, Long-Running Jobs — each with configurable
thresholds in Settings, email notifications, tray toasts, and auto-clear
when conditions resolve.

Alerts History view aggregates all alerts across servers in a timeline
with severity-colored rows, time range and server filters, column-level
filtering, copy/export context menu, and dismiss/hide functionality.

Dashboard persists alert history to JSON on exit and reloads on startup.
Alerts are hidden (not deleted) when dismissed, surviving across sessions.
Lite stores alerts in DuckDB with a dismissed column (schema v9 migration).

Both apps auto-refresh the alerts view when visible and support
multi-select dismiss and bulk dismiss-all with confirmation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Deadlock and blocked process XML processors now check whether
sp_BlitzLock / sp_HumanEventsBlockViewer actually produced parsed
results. If 0 results are returned, rows stay unprocessed for
automatic retry on the next run instead of being silently marked
done. Logs NO_RESULTS status with descriptive error message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ke sure something works, and then you get so excited about it working that you just sit there marveling at it working and then forget to put it back? It me.

Fix Lite deadlock and blocked process collectors inserting duplicate rows (#61). Both collectors query the XE ring buffer every minute but the buffer holds ~10 minutes of events, so each event was inserted ~10 times. Now each collector queries MAX(timestamp) from DuckDB before collection and passes it as a SQL Server parameter to filter out already-collected events. Falls back to a 10-minute window on first run.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…cate-events

Fix Lite duplicate deadlock and blocked process events (#61)
Some organizations require a vendor relationship or invoice before deploying
open-source software. Added Supported ($500/yr) and Priority ($2,500/yr) tiers
with links to the blog post and purchase page. No features are gated — the
commercial tiers provide support, compatibility guarantees, and compliance
paperwork.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…-support

Add commercial support tiers to README
Dashboard: Sub-tab badges (Locking, Memory, Resource Metrics) now update when
alerts fire from the independent alert engine. Previously only the server-level
Overview badge updated. Also fix deadlock badge race condition where
EvaluateAlertConditionsAsync consumed the previous deadlock count before the
badge delta calculation could use it.

Lite: Fix DuckDB v9 migration silently failing — ALTER TABLE ADD COLUMN does
not support NOT NULL constraint in DuckDB. Changed to nullable with DEFAULT.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ixes

Fix Dashboard sub-tab badges and DuckDB dismissed column migration
Wire ChartHoverHelper to every remaining chart in the Dashboard that
was missing mouse-over tooltips showing series name, value, and
timestamp:

- MemoryContent: 5 charts (overview, grants, clerks, plan cache, pressure)
- QueryPerformanceContent: 4 charts (query/proc/QS durations, exec counts)
- SystemEventsContent: 19 charts (corruption, contention, errors, IO,
  scheduler, memory conditions, CPU tasks, memory broker, node OOM)
- ResourceMetricsContent: 6 charts (CPU utilization, TempDB stats/latency,
  server trends CPU/TempDB/memory/perfmon)
- ServerTab: 9 charts (4 resource overview + 5 locking trends)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ooltips

Add hover tooltips to all Dashboard charts
…B schema tests

- ci.yml: Build all 5 projects + run Lite.Tests on PR/push to dev
- sql-validation.yml: Install all SQL scripts on 2017/2019/2022/2025 matrix, validate 93 objects exist
- ci_validate_installation.sql: OBJECT_ID checks for all schemas, tables, procedures, views
- Lite.Tests: 6 xUnit tests for DuckDB schema init, version, idempotency, indexes

All tests verified locally against sql2022 and DuckDB.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
erikdarlingdata and others added 29 commits February 16, 2026 17:14
When disabled, clicking a server card in Overview creates the tab
without switching away from the current view. Existing-tab clicks
always focus regardless of setting. Default is true (current behavior).

Closes #71

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Four fixes for the deadlock chart pipeline:

- Dashboard charts: plot raw per-interval columns instead of delta columns
  (blocking_event_count, deadlock_count, etc.) since delta framework
  incorrectly computed current-previous=0 for per-interval values
- XAML: remove "(Delta)" from all four Locking > Trends chart titles
- Analyzer: filter collect.deadlocks on collection_time instead of
  event_date so late-arriving XE deadlock events are not missed
- Process XML: add +1 second buffer to @end_date so sp_BlitzLock's
  strict less-than filter works when processing a single deadlock event

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ipping

Fix text clipping in DataGrid rows
…-tab-setting

Add setting to control server tab auto-focus
…n Lite

Wire up ChartHoverHelper for the three Lite charts that were missing
tooltip support. Wait Stats, Perfmon, TempDB File I/O, and File I/O
charts already had this; CPU, Memory, and TempDB (by type) did not.

Closes #81

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…oltips

Fix missing chart tooltips for CPU, Memory, TempDB in Lite
The dashboard doesn't display blocking/deadlock or wait stats data from
sp_HealthParser. Passing @skip_locks = 1 and @skip_waits = 1 (defaulted
on) reduces collection time from 43s to 1.6s (27x improvement).

Requires sp_HealthParser 3.3+ (DarlingData PR #666/#667).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e schedule (#86)

- Blocked process and deadlock XML collectors now chain-trigger their
  parsers and analyzer immediately when rows are found, eliminating up
  to 15 min pipeline latency
- Materialize XE ring buffer XML into table variable before shredding,
  avoiding repeated XML document validation (35s → 300ms under load)
- Master collector passes @minutes_back = frequency * 2 instead of
  defaulting to 15 min lookback every cycle
- Bump 18 cheap collectors to 1-min frequency, 4 medium to 2-min

Tested on sql2022 under TPC-C workload: 79 deadlock events collected
in 297ms (was 35s), chain triggers fire correctly, zero CHAIN_ERRORs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Pass @skip_locks and @skip_waits to health collector wrapper
…re-firing

AddWithValue infers types incorrectly — for DateTime it sends legacy datetime
(3.33ms precision) instead of datetime2, causing the deadlock dedup cutoff to
round and re-collect the same event every cycle. Replaced all 28 usages across
7 files with explicitly typed SqlParameter.

Fixed alert re-firing: ServerTab used CollectionTime (always new) instead of
DeadlockTime/EventTime for ack comparison. Overview deadlock count query also
filtered by collection_time instead of deadlock_time, inflating counts with
duplicate rows and triggering spurious popup alerts.

Tested: zero AddWithValue remaining, all 3 projects build clean, dedup confirmed
working under HammerDB load (97 new deadlocks collected, zero duplicates).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… status (#85, #91, #93)

#85: Blocking/deadlock trend charts now show a visible flat line at zero
instead of empty space. Added negative Y-axis margin so zero-value data
renders above the axis border. Reduced fallback Y range from +100 to +1.

#91: Added server_name column to collection_log DuckDB table (schema v10)
so log entries identify which server produced them without a lookup join.

#93: Sidebar status dots now reflect actual connection check results
(IsOnline) instead of the IsEnabled user config toggle. Added IsOnline
property to ServerConnection model, synced from connection status in
RefreshServerList and CheckConnectionsAndNotify. Fixed first-check
refresh so dots update as soon as initial connection checks complete.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix chart zero lines, collection log server name, and overview status (#85, #91, #93)
…n-triggers

Chain-trigger parsers, optimize XML collection, tune schedule
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update schema version assertion to v10 in tests
…ded value

Made CurrentSchemaVersion internal and added InternalsVisibleTo so the
test project references the constant directly. Schema bumps no longer
require updating tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ynamic

Use DuckDbInitializer.CurrentSchemaVersion in tests instead of hardcoded value
CLI: --reset-schedule flag prepends TRUNCATE to 04_create_schedule_table.sql
GUI: "Reset collection schedule to recommended defaults" checkbox
Both pass resetSchedule to installer logic which truncates config.collection_schedule
before the WHERE NOT EXISTS inserts re-populate with current defaults.

Tested on sql2022 with update install — schedule reset to 33 collectors with
current recommended frequencies.

Closes #92

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add --reset-schedule flag for CLI and GUI installers
RunDueCollectorsAsync now checks IsOnline status before queuing collectors
for each server. Servers marked offline by the connection check are skipped
entirely, eliminating wasted timeout cycles. Connection timeout reduced
from 15s to 5s to match the connection check timeout.

Tested under 30-min HammerDB TPC-C load: 437 Lite collections at 100%
success rate, avg 176ms. Zero offline server attempts.

Closes #90

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ervers

Skip offline servers during Lite collection
PRs to dev now get the same build validation as PRs to main,
so package updates and other changes can be verified before merge.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Issue #101 update NuGet packages to latest stable version
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@erikdarlingdata erikdarlingdata merged commit cccb314 into main Feb 18, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants