diff --git a/Dashboard/Analysis/FactScorer.cs b/Dashboard/Analysis/FactScorer.cs
index 82382989..78347953 100644
--- a/Dashboard/Analysis/FactScorer.cs
+++ b/Dashboard/Analysis/FactScorer.cs
@@ -308,8 +308,10 @@ private static double ScoreBadActorFact(Fact fact)
///
private static double ScoreAnomalyFact(Fact fact)
{
- if (fact.Key.StartsWith("ANOMALY_CPU_SPIKE") || fact.Key.StartsWith("ANOMALY_READ_LATENCY")
- || fact.Key.StartsWith("ANOMALY_WRITE_LATENCY"))
+ if ( fact.Key.StartsWith("ANOMALY_CPU_SPIKE" , StringComparison.OrdinalIgnoreCase)
+ || fact.Key.StartsWith("ANOMALY_READ_LATENCY" , StringComparison.OrdinalIgnoreCase)
+ || fact.Key.StartsWith("ANOMALY_WRITE_LATENCY", StringComparison.OrdinalIgnoreCase)
+ )
{
// Deviation-based scoring: 2σ = 0.5, 4σ = 1.0
var deviation = fact.Metadata.GetValueOrDefault("deviation_sigma");
@@ -319,7 +321,7 @@ private static double ScoreAnomalyFact(Fact fact)
return base_score * confidence;
}
- if (fact.Key.StartsWith("ANOMALY_WAIT_"))
+ if (fact.Key.StartsWith("ANOMALY_WAIT_", StringComparison.OrdinalIgnoreCase))
{
// Ratio-based scoring: 5x = 0.5, 20x = 1.0
var ratio = fact.Metadata.GetValueOrDefault("ratio");
@@ -327,7 +329,9 @@ private static double ScoreAnomalyFact(Fact fact)
return 0.5 + 0.5 * Math.Min((ratio - 5.0) / 15.0, 1.0);
}
- if (fact.Key.StartsWith("ANOMALY_BLOCKING_SPIKE") || fact.Key.StartsWith("ANOMALY_DEADLOCK_SPIKE"))
+ if ( fact.Key.StartsWith("ANOMALY_BLOCKING_SPIKE", StringComparison.OrdinalIgnoreCase)
+ || fact.Key.StartsWith("ANOMALY_DEADLOCK_SPIKE", StringComparison.OrdinalIgnoreCase)
+ )
{
// Ratio-based: 3x = 0.5, 10x = 1.0
var ratio = fact.Metadata.GetValueOrDefault("ratio");
@@ -859,7 +863,7 @@ private static (double concerning, double? critical)? GetWaitThresholds(string w
///
/// An amplifier definition: a named predicate that boosts severity when matched.
///
-internal class AmplifierDefinition
+internal sealed class AmplifierDefinition
{
public string Description { get; set; } = string.Empty;
public double Boost { get; set; }
diff --git a/Dashboard/Analysis/SqlServerDrillDownCollector.cs b/Dashboard/Analysis/SqlServerDrillDownCollector.cs
index 050ffe30..cf435978 100644
--- a/Dashboard/Analysis/SqlServerDrillDownCollector.cs
+++ b/Dashboard/Analysis/SqlServerDrillDownCollector.cs
@@ -62,10 +62,15 @@ public async Task EnrichFindingsAsync(List findings, AnalysisCo
if (pathKeys.Contains("QUERY_SPILLS"))
await CollectTopSpillingQueries(finding, context);
- if (pathKeys.Contains("IO_READ_LATENCY_MS") || pathKeys.Contains("IO_WRITE_LATENCY_MS"))
+ if ( pathKeys.Contains("IO_READ_LATENCY_MS")
+ || pathKeys.Contains("IO_WRITE_LATENCY_MS")
+ )
await CollectFileLatencyBreakdown(finding, context);
- if (pathKeys.Contains("LCK") || pathKeys.Contains("LCK_M_S") || pathKeys.Contains("LCK_M_IS"))
+ if ( pathKeys.Contains("LCK")
+ || pathKeys.Contains("LCK_M_S")
+ || pathKeys.Contains("LCK_M_IS")
+ )
await CollectLockModeBreakdown(finding, context);
if (pathKeys.Contains("DB_CONFIG"))
@@ -77,7 +82,7 @@ public async Task EnrichFindingsAsync(List findings, AnalysisCo
if (pathKeys.Contains("MEMORY_GRANT_PENDING"))
await CollectPendingGrants(finding, context);
- if (pathKeys.Any(k => k.StartsWith("BAD_ACTOR_")))
+ if (pathKeys.Any(k => k.StartsWith("BAD_ACTOR_", StringComparison.OrdinalIgnoreCase)))
await CollectBadActorDetail(finding, context);
// Plan analysis: for findings with top queries, analyze their cached plans
@@ -618,7 +623,7 @@ private async Task CollectPlanAnalysis(AnalysisFinding finding, AnalysisContext
// Only analyze plans for bad actor findings (1 plan each).
// Skip top_cpu_queries (5 plans would be too heavy).
- if (!finding.RootFactKey.StartsWith("BAD_ACTOR_")) return;
+ if (!finding.RootFactKey.StartsWith("BAD_ACTOR_", StringComparison.OrdinalIgnoreCase)) return;
var queryHash = finding.RootFactKey.Replace("BAD_ACTOR_", "");
if (string.IsNullOrEmpty(queryHash)) return;
diff --git a/Dashboard/Analysis/SqlServerFactCollector.cs b/Dashboard/Analysis/SqlServerFactCollector.cs
index a99d9aa1..446e4277 100644
--- a/Dashboard/Analysis/SqlServerFactCollector.cs
+++ b/Dashboard/Analysis/SqlServerFactCollector.cs
@@ -1671,15 +1671,15 @@ private static void GroupParallelismWaits(List facts, AnalysisContext cont
///
private static bool IsGeneralLockWait(string waitType)
{
- if (!waitType.StartsWith("LCK_M_")) return false;
+ if (!waitType.StartsWith("LCK_M_", StringComparison.OrdinalIgnoreCase)) return false;
// Keep individual: reader/writer locks
if (waitType is "LCK_M_S" or "LCK_M_IS") return false;
// Keep individual: range locks (serializable/repeatable read)
- if (waitType.StartsWith("LCK_M_RS_") ||
- waitType.StartsWith("LCK_M_RIn_") ||
- waitType.StartsWith("LCK_M_RX_")) return false;
+ if (waitType.StartsWith("LCK_M_RS_", StringComparison.OrdinalIgnoreCase) ||
+ waitType.StartsWith("LCK_M_RIn_", StringComparison.OrdinalIgnoreCase) ||
+ waitType.StartsWith("LCK_M_RX_", StringComparison.OrdinalIgnoreCase)) return false;
// Everything else (X, U, IX, SIX, BU, IU, UIX, etc.) -> group
return true;
diff --git a/Dashboard/Controls/FinOpsContent.xaml.cs b/Dashboard/Controls/FinOpsContent.xaml.cs
index 3533b833..e2a3a6c8 100644
--- a/Dashboard/Controls/FinOpsContent.xaml.cs
+++ b/Dashboard/Controls/FinOpsContent.xaml.cs
@@ -16,7 +16,6 @@
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
-using System.Windows.Controls.Primitives;
using System.Windows.Media;
using Microsoft.Win32;
using PerformanceMonitorDashboard.Helpers;
diff --git a/Dashboard/Controls/PlanViewerControl.xaml.cs b/Dashboard/Controls/PlanViewerControl.xaml.cs
index 43590b72..3ec40d49 100644
--- a/Dashboard/Controls/PlanViewerControl.xaml.cs
+++ b/Dashboard/Controls/PlanViewerControl.xaml.cs
@@ -454,7 +454,7 @@ private WpfPath CreateElbowConnector(PlanNode parent, PlanNode child)
};
}
- private object BuildEdgeTooltipContent(PlanNode child)
+ private Border BuildEdgeTooltipContent(PlanNode child)
{
var grid = new Grid { MinWidth = 240 };
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
diff --git a/Dashboard/Dashboard.csproj b/Dashboard/Dashboard.csproj
index f918bc6a..bf2784a3 100644
--- a/Dashboard/Dashboard.csproj
+++ b/Dashboard/Dashboard.csproj
@@ -35,12 +35,12 @@
-
-
+
+
-
+
diff --git a/Dashboard/Mcp/McpAnalysisTools.cs b/Dashboard/Mcp/McpAnalysisTools.cs
index 72ffa00b..c20db796 100644
--- a/Dashboard/Mcp/McpAnalysisTools.cs
+++ b/Dashboard/Mcp/McpAnalysisTools.cs
@@ -433,15 +433,17 @@ public static System.Collections.Generic.List