-
Notifications
You must be signed in to change notification settings - Fork 29
Description
Which component(s) does this affect?
- Full Dashboard
- Lite
- SQL collection scripts
- Installer
- Documentation
Problem Statement
Users cannot suppress specific recurring alerts. The only existing options are coarse-grained:
- Server silencing — suppresses ALL alerts for an entire server
- Acknowledgement — temporarily hides badges until conditions worsen
- Database exclusion — filters entire databases from blocking/deadlock counts
There is no way to say "stop alerting me about this specific long-running query" or "mute all blocking alerts from database X" while keeping other alerts active.
Proposed Solution
Add a mute rule system that sits between alert detection and notification. Muted alerts are still collected and logged (with a muted flag) but suppressed from tray notifications, emails, and UI badges.
Two muting modes:
- Pattern-based: match on server, metric type, database, query text substring, wait type, or job name (fields combined with AND logic)
- Instance-based: a tightly-scoped pattern rule auto-populated from a specific alert's context
Data Model
public class MuteRule
{
public string Id { get; set; } // GUID
public bool Enabled { get; set; } = true;
public DateTime CreatedAtUtc { get; set; }
public DateTime? ExpiresAtUtc { get; set; } // null = permanent
public string? Reason { get; set; } // user note
// Match criteria — all non-null fields must match (AND)
public string? ServerName { get; set; } // exact match, null = any
public string? MetricName { get; set; } // exact: "Blocking", "Deadlocks", "High CPU", etc.
public string? DatabasePattern { get; set; } // substring (case-insensitive)
public string? QueryTextPattern { get; set; }// substring (case-insensitive)
public string? WaitTypePattern { get; set; } // substring (case-insensitive)
public string? JobNamePattern { get; set; } // substring (case-insensitive)
}Alert Context for Matching
public class AlertContext
{
public string ServerName { get; set; }
public string MetricName { get; set; } // "Blocking", "Deadlocks", "High CPU", etc.
public string? DatabaseName { get; set; }
public string? QueryText { get; set; }
public string? WaitType { get; set; }
public string? JobName { get; set; }
}Integration Points
Dashboard — EvaluateAlertConditionsAsync() in MainWindow.xaml.cs:
- After each metric's threshold check passes, before sending notifications
- Call
_muteRuleService.IsAlertMuted(context)with available detail - If muted: log alert with
Muted=true, skip tray/email/badge
Lite — CheckPerformanceAlerts() in MainWindow.xaml.cs:
- Same pattern: check mute rules per-metric after threshold triggers
- If muted: log to DuckDB with
muted=TRUE, skip tray/email
Persistence
Dashboard: alert_mute_rules.json in %APPDATA%\PerformanceMonitorDashboard\
Lite: New DuckDB table config_mute_rules
UI
- Alert History tab: right-click context menu → "Mute This Alert" / "Mute Similar Alerts..."
- Mute Rule Dialog: create/edit form with match fields, expiration picker (1h/24h/7d/permanent), reason text
- Manage Mute Rules Window: list all rules, enable/disable/delete, accessible from Settings
- Visual indicator: muted alerts shown grayed/italic in alert history with a "muted" label
Use Case
Alerts which happen frequently, and are well-known, but cannot be immediately actioned, could be muted for a period of time, or muted permanently on a case-by-case basis.
Alternatives Considered
No response
Additional Context
Phase 1: Core Model & Service
- model-mute-rule — Create
MuteRulemodel class (both editions) - service-mute-rule-dashboard — Create
MuteRuleServicefor Dashboard (JSON persistence, match logic) - service-mute-rule-lite — Create
MuteRuleServicefor Lite (DuckDB persistence, match logic) - lite-schema-update — Add
config_mute_rulestable +mutedcolumn toconfig_alert_login Schema.cs
Phase 2: Alert Pipeline Integration
- integrate-dashboard-eval — Wire mute checks into
EvaluateAlertConditionsAsync(per-metric) - integrate-lite-eval — Wire mute checks into
CheckPerformanceAlerts(per-metric) - alert-log-muted-flag-dashboard — Add
Mutedfield toAlertLogEntry, pass throughRecordAlert - alert-log-muted-flag-lite — Add
mutedcolumn to DuckDB insert inEmailAlertService.LogAlertAsync
Phase 3: UI — Mute Rule Management
- dialog-mute-rule-dashboard — Create
MuteRuleDialog.xaml/.csfor creating/editing rules - dialog-mute-rule-lite — Create equivalent for Lite edition
- window-manage-rules-dashboard — Create
ManageMuteRulesWindow(list, enable/disable, delete) - window-manage-rules-lite — Create equivalent for Lite edition
- settings-button-dashboard — Add "Manage Mute Rules..." button to Dashboard SettingsWindow
- settings-button-lite — Add equivalent to Lite SettingsWindow
Phase 4: UI — Alert History Integration
- context-menu-dashboard — Add right-click "Mute" options to Dashboard alert history
- context-menu-lite — Add right-click "Mute" options to Lite AlertsHistoryTab
- visual-indicator-dashboard — Show muted alerts with distinct styling in alert history
- visual-indicator-lite — Same for Lite
Phase 5: MCP & Polish
- mcp-tools-dashboard — Add
get_mute_rulesto Dashboard McpAlertTools - mcp-tools-lite — Add
get_mute_rulesto Lite McpAlertTools - docs-readme — Update README alert section with mute rule documentation
Dependencies
- Phase 2 depends on Phase 1
- Phase 3 depends on Phase 1
- Phase 4 depends on Phase 2 + Phase 3
- Phase 5 depends on Phase 1
Notes
- Match logic uses AND across non-null fields (all specified fields must match)
- Instance-based muting is just a pattern rule with all fields populated from context
- Expired rules are automatically skipped during matching and can be cleaned up periodically
- Existing server silencing / acknowledgement / cooldown mechanisms remain unchanged
- Muted alerts are still written to the alert log for auditability — they just don't trigger notifications
- DuckDB schema version will need to be bumped for the Lite table changes