diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..5ff966f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +root = true + +[*.cs] + +# CA1873: Avoid potentially expensive logging +# +# This rule fires on any non-literal argument to a logging method (including +# trivial field accesses like `_logger.LogInformation("X: {Path}", _path)`), +# on the theory that the argument might be expensive to evaluate when the +# level is disabled. In this codebase the cost is consistently negligible — +# the proper fix is migrating to LoggerMessage source generators, which is +# a larger separate effort. Until then, this rule is pure noise. +dotnet_diagnostic.CA1873.severity = none diff --git a/Dashboard/ServerTab.Plans.cs b/Dashboard/ServerTab.Plans.cs index c07435f..bbb5a6f 100644 --- a/Dashboard/ServerTab.Plans.cs +++ b/Dashboard/ServerTab.Plans.cs @@ -341,7 +341,7 @@ private async Task ShowBlockedProcessPlanAsync(object sender, bool blockingSide) int stmtStart = 0; int stmtEnd = -1; - int.TryParse(frame.Attribute("stmtstart")?.Value, out stmtStart); + _ = int.TryParse(frame.Attribute("stmtstart")?.Value, out stmtStart); if (int.TryParse(frame.Attribute("stmtend")?.Value, out var se)) stmtEnd = se; frames.Add((handle!, stmtStart, stmtEnd)); @@ -426,7 +426,7 @@ private async void ViewDeadlockProcessPlan_Click(object sender, RoutedEventArgs !string.Equals(procHandle, ZeroSqlHandle, StringComparison.OrdinalIgnoreCase)) { int ps = 0, pe = -1; - int.TryParse(process.Attribute("stmtstart")?.Value, out ps); + _ = int.TryParse(process.Attribute("stmtstart")?.Value, out ps); if (int.TryParse(process.Attribute("stmtend")?.Value, out var peParsed)) pe = peParsed; frames.Add((procHandle!, ps, pe)); } @@ -441,7 +441,7 @@ private async void ViewDeadlockProcessPlan_Click(object sender, RoutedEventArgs if (string.Equals(handle, ZeroSqlHandle, StringComparison.OrdinalIgnoreCase)) continue; int fs = 0, fe = -1; - int.TryParse(frame.Attribute("stmtstart")?.Value, out fs); + _ = int.TryParse(frame.Attribute("stmtstart")?.Value, out fs); if (int.TryParse(frame.Attribute("stmtend")?.Value, out var feParsed)) fe = feParsed; frames.Add((handle!, fs, fe)); } diff --git a/Lite/Controls/CorrelatedTimelineLanesControl.xaml.cs b/Lite/Controls/CorrelatedTimelineLanesControl.xaml.cs index 2b73b71..af872f0 100644 --- a/Lite/Controls/CorrelatedTimelineLanesControl.xaml.cs +++ b/Lite/Controls/CorrelatedTimelineLanesControl.xaml.cs @@ -174,11 +174,11 @@ await Task.WhenAll(cpuTask, waitTask, blockingTask, deadlockTask, memoryTask, fi $"Comparison: refFrom={refFrom:o}, refTo={refTo:o}, shift={timeShift.TotalHours:F1}h, " + $"cpuRows={refCpuTask.Result?.Count ?? 0}, waitRows={refWaitTask.Result?.Count ?? 0}"); - if (refCpuTask.IsCompletedSuccessfully) + if (refCpuTask.IsCompletedSuccessfully && refCpuTask.Result != null) AddGhostLine(CpuChart, refCpuTask.Result .Select(d => (d.SampleTime.Add(timeShift).ToOADate(), (double)d.SqlServerCpu)).ToList(), "#4FC3F7"); - if (refWaitTask.IsCompletedSuccessfully) + if (refWaitTask.IsCompletedSuccessfully && refWaitTask.Result != null) AddGhostLine(WaitStatsChart, refWaitTask.Result .Select(d => (d.CollectionTime.AddMinutes(utcOffset).Add(timeShift).ToOADate(), d.WaitTimeMsPerSecond)).ToList(), "#FFB74D"); diff --git a/Lite/Mcp/McpAnalysisTools.cs b/Lite/Mcp/McpAnalysisTools.cs index c29dca0..fbbd48b 100644 --- a/Lite/Mcp/McpAnalysisTools.cs +++ b/Lite/Mcp/McpAnalysisTools.cs @@ -840,7 +840,7 @@ public static List GetForStoryPath(string storyPath) /// Formats baseline context from anomaly fact metadata into a human-readable object /// for MCP output. Example: "4.1σ above baseline for Tue 14:00, mean 68.2" /// - private static object? FormatBaselineContext(Dictionary metadata) + private static Dictionary? FormatBaselineContext(Dictionary metadata) { var result = new Dictionary();