From 63e9634df8f44603adf1ccf8d12f41480bf73271 Mon Sep 17 00:00:00 2001 From: Tom McDonald Date: Mon, 17 Apr 2023 23:07:57 -0400 Subject: [PATCH] Fix incorrect rendering of counters (#3816) * Fix incorrect rendering of counters * Fixing IDE0008 Use explicit type instead of 'var' build error * PR feedback and truncate output for multiple providers * Simplify counter refresh console output * Better drawing for very small console height screens * Remove lambda to avoid unnecessary memory allocations --- .../Exporters/ConsoleWriter.cs | 95 ++++++++++++++----- 1 file changed, 73 insertions(+), 22 deletions(-) diff --git a/src/Tools/dotnet-counters/Exporters/ConsoleWriter.cs b/src/Tools/dotnet-counters/Exporters/ConsoleWriter.cs index ded01c7d8..76f06931f 100644 --- a/src/Tools/dotnet-counters/Exporters/ConsoleWriter.cs +++ b/src/Tools/dotnet-counters/Exporters/ConsoleWriter.cs @@ -28,8 +28,13 @@ namespace Microsoft.Diagnostics.Tools.Counters.Exporters public readonly CounterProvider KnownProvider; } + private interface ICounterRow + { + int Row { get; set; } + } + /// Information about an observed counter. - private class ObservedCounter + private class ObservedCounter : ICounterRow { public ObservedCounter(string displayName) => DisplayName = displayName; public string DisplayName { get; } // Display name for this counter. @@ -41,7 +46,7 @@ namespace Microsoft.Diagnostics.Tools.Counters.Exporters public double LastValue { get; set; } } - private class ObservedTagSet + private class ObservedTagSet : ICounterRow { public ObservedTagSet(string tags) { @@ -128,6 +133,19 @@ namespace Microsoft.Diagnostics.Tools.Counters.Exporters { Clear(); + // clear row data on all counters + foreach (ObservedProvider provider in _providers.Values) + { + foreach (ObservedCounter counter in provider.Counters.Values) + { + counter.Row = -1; + foreach (ObservedTagSet tagSet in counter.TagSets.Values) + { + tagSet.Row = -1; + } + } + } + _consoleWidth = Console.WindowWidth; _consoleHeight = Console.WindowHeight; _maxNameLength = Math.Max(Math.Min(80, _consoleWidth) - (CounterValueLength + Indent + 1), 0); // Truncate the name to prevent line wrapping as long as the console width is >= CounterValueLength + Indent + 1 characters @@ -144,38 +162,67 @@ namespace Microsoft.Diagnostics.Tools.Counters.Exporters Console.WriteLine(_errorText); row += GetLineWrappedLines(_errorText); } - Console.WriteLine(); row++; // Blank line. - foreach (ObservedProvider provider in _providers.Values.OrderBy(p => p.KnownProvider == null).ThenBy(p => p.Name)) // Known providers first. + bool RenderRow(ref int row, string lineOutput = null, ICounterRow counterRow = null) { - Console.WriteLine($"[{provider.Name}]"); row++; + if (row >= _consoleHeight + _topRow) // prevents from displaying more counters than vertical space available + { + return false; + } + + if (lineOutput != null) + { + Console.Write(lineOutput); + } - foreach (ObservedCounter counter in provider.Counters.Values.OrderBy(c => c.DisplayName)) + if (row < _consoleHeight + _topRow - 1) // prevents screen from scrolling due to newline on last line of console { + Console.WriteLine(); + } + + if (counterRow != null) + { + counterRow.Row = row; + } + + row++; - string name = MakeFixedWidth($"{new string(' ', Indent)}{counter.DisplayName}", Indent + _maxNameLength); - counter.Row = row++; - if (counter.RenderValueInline) + return true; + } + + if (RenderRow(ref row)) // Blank line. + { + foreach (ObservedProvider provider in _providers.Values.OrderBy(p => p.KnownProvider == null).ThenBy(p => p.Name)) // Known providers first. + { + if (!RenderRow(ref row, $"[{provider.Name}]")) { - if (row >= _consoleHeight) // prevents from displaying more counters than vertical space available - { - break; - } - Console.WriteLine($"{name} {FormatValue(counter.LastValue)}"); + break; } - else + + foreach (ObservedCounter counter in provider.Counters.Values.OrderBy(c => c.DisplayName)) { - Console.WriteLine(name); - foreach (ObservedTagSet tagSet in counter.TagSets.Values.OrderBy(t => t.Tags)) + string name = MakeFixedWidth($"{new string(' ', Indent)}{counter.DisplayName}", Indent + _maxNameLength); + if (counter.RenderValueInline) { - if (row >= _consoleHeight) + if (!RenderRow(ref row, $"{name} {FormatValue(counter.LastValue)}", counter)) { break; } - - string tagName = MakeFixedWidth($"{new string(' ', 2 * Indent)}{tagSet.Tags}", Indent + _maxNameLength); - Console.WriteLine($"{tagName} {FormatValue(tagSet.LastValue)}"); - tagSet.Row = row++; + } + else + { + if (!RenderRow(ref row, name, counter)) + { + break; + } + foreach (ObservedTagSet tagSet in counter.TagSets.Values.OrderBy(t => t.Tags)) + { + string tagName = MakeFixedWidth($"{new string(' ', 2 * Indent)}{tagSet.Tags}", Indent + _maxNameLength); + if (!RenderRow(ref row, $"{tagName} {FormatValue(tagSet.LastValue)}", tagSet)) + { + break; + } + } } } } @@ -253,6 +300,10 @@ namespace Microsoft.Diagnostics.Tools.Counters.Exporters } int row = counter.RenderValueInline ? counter.Row : tagSet.Row; + if (row < 0) + { + return; + } SetCursorPosition(Indent + _maxNameLength + 1, row); Console.Write(FormatValue(payload.Value)); } -- 2.34.1