Skip to content

Add dismissed_archive_alerts sidecar table for parquet-aware dismissal (#718)#730

Merged
erikdarlingdata merged 14 commits intoerikdarlingdata:devfrom
HannahVernon:feature/dismissed-archive-sidecar-718
Mar 27, 2026
Merged

Add dismissed_archive_alerts sidecar table for parquet-aware dismissal (#718)#730
erikdarlingdata merged 14 commits intoerikdarlingdata:devfrom
HannahVernon:feature/dismissed-archive-sidecar-718

Conversation

@HannahVernon
Copy link
Copy Markdown
Contributor

What does this PR do?

Addresses issue #718 where alert dismissal silently fails for archived alerts. The dismiss flow targets the live config_alert_log table, but alerts archived to parquet files are read-only UPDATE returns 0 affected rows with no user feedback.

This PR adds a sidecar table (dismissed_archive_alerts) that tracks which archived alerts have been dismissed, and modifies the v_config_alert_log view to filter them out.

Changes

File Change
Lite/Database/Schema.cs New dismissed_archive_alerts table (alert_time, server_id, metric_name, dismissed_at) with composite index
Lite/Database/DuckDbInitializer.cs Schema version 2223 with migration; v_config_alert_log parquet half now excludes rows present in sidecar via NOT EXISTS
Lite/Services/LocalDataService.AlertHistory.cs DismissAlertsAsync: when UPDATE returns 0 rows, falls back to sidecar INSERT with duplicate prevention. DismissAllVisibleAlertsAsync: after live UPDATE, inserts remaining undismissed archived alerts into sidecar
Lite.Tests/DuckDbSchemaTests.cs Updated table count assertion from 28 to 29
Lite.Tests/Helpers/TestAlertDataHelper.cs Reusable test utility for inserting live alerts and creating archived parquet files
Lite.Tests/DismissedArchiveSidecarTests.cs 7 new xUnit tests

How it works

Before: Archived alerts appear in the grid (via the view's parquet union) but UPDATE config_alert_log can never reach them. Clicking Dismiss silently does nothing.

After: When DismissAlertsAsync detects a 0-rows-affected UPDATE, it INSERTs the alert's key into dismissed_archive_alerts. The view's parquet half uses NOT EXISTS against this sidecar table to filter them out. The archived alert disappears from the grid on the next refresh.

Design decisions

  • No ALTER TABLE the sidecar is a new table, not a column addition. No DuckDB NULL-on-upgrade issues.
  • Not in ArchivableTables the sidecar is a small metadata table (one row per dismissed archive alert), not time-series data. It does not need its own archival cycle.
  • Duplicate prevention all INSERT paths use WHERE NOT EXISTS to prevent duplicate sidecar entries.
  • Complements PR Add source column to distinguish live vs archived alerts (#718) #729 this works independently, but pairs well with the source column feature for a complete solution.

Which component(s) does this affect?

  • Full Dashboard
  • Lite Dashboard
  • Lite Tests
  • SQL collection scripts
  • CLI Installer
  • GUI Installer
  • Documentation

How was this tested?

  • All 218 existing Lite tests pass (including updated SchemaStatements_MatchTableCount)
  • 7 new tests covering:
    • SidecarTable_ExistsAfterInit table created by migration
    • SidecarTable_HasCorrectColumns schema validation
    • SidecarInsert_HidesArchivedAlertFromView core feature: sidecar hides archived alert
    • SidecarInsert_DoesNotAffectLiveAlerts live alerts unaffected by sidecar
    • SidecarInsert_PreventsDuplicates NOT EXISTS prevents double-insert
    • DismissAll_HandlesLiveAndArchivedAlerts mixed live+archive dismiss flow
    • SchemaVersion_IsUpdatedTo23 migration applied correctly

Checklist

  • I have read the contributing guide
  • My code builds with zero warnings (dotnet build -c Debug)
  • I have tested my changes against at least one SQL Server version
  • I have not introduced any hardcoded credentials or server names

HannahVernon and others added 12 commits March 10, 2026 17:08
- Parse detail_text to extract Database, Query Text, and Wait Type
  when using 'Mute This Alert' from alert history (both editions)
- Add PopulateFromDetailText() to AlertMuteContext for structured
  field extraction from the label: value format
- Add 'Default expiration for new mute rules' dropdown to Settings
  in both editions (1 hour, 24 hours, 7 days, Never; default 24h)
- MuteRuleDialog now selects the configured default expiration
  instead of always defaulting to 'Never'
- Persist setting as mute_rule_default_expiration in settings.json
  (Lite) and preferences.json (Dashboard)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The XML doc claimed Job Name extraction but the parser did not
implement it. Add the missing branch in both Dashboard and Lite
editions so the behavior matches the documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Collapse newlines in Truncate/TruncateText so detail_text fields
  stay single-line in the label: value format
- Handle multi-line query values in PopulateFromDetailText by
  accumulating continuation lines until the next indented field
- Recognize variant query labels (Blocked Query, Blocking Query,
  Victim SQL) in addition to Query

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Explain that the field is a case-insensitive substring match and
suggest entering a distinctive fragment like a table or procedure name.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
erikdarlingdata#718)

The dismiss flow targets the live config_alert_log table, but alerts
archived to parquet are read-only. This adds a sidecar table that tracks
dismissed archived alerts so the view can filter them out.

Schema:
- New dismissed_archive_alerts table (alert_time, server_id, metric_name,
  dismissed_at) with composite index
- Schema version bumped to 23 with migration

View:
- v_config_alert_log parquet half now excludes rows present in the
  sidecar table via NOT EXISTS

Dismiss logic:
- DismissAlertsAsync: when UPDATE returns 0 rows (archived alert),
  falls back to sidecar INSERT with duplicate prevention
- DismissAllVisibleAlertsAsync: after live UPDATE, inserts remaining
  undismissed archived alerts into the sidecar table

Tests:
- 7 new xUnit tests covering sidecar creation, view filtering, duplicate
  prevention, mixed live+archive dismiss, and schema version
- Updated DuckDbSchemaTests table count from 28 to 29

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@HannahVernon
Copy link
Copy Markdown
Contributor Author

Once 729 is merged in, I'll resolve the conflicts and update the PR.

@erikdarlingdata
Copy link
Copy Markdown
Owner

@HannahVernon #729 was mergered already

@HannahVernon
Copy link
Copy Markdown
Contributor Author

@erikdarlingdata - rebased cleanly ready for merge whenever you are 🚀

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