|
@@ -0,0 +1,111 @@
|
|
|
+using NetBootServerCore.Components.UI.Cui.Logging;
|
|
|
+using Spectre.Console;
|
|
|
+using System.Collections.Concurrent;
|
|
|
+
|
|
|
+namespace NetBootServerCore.Components.UI.Cui
|
|
|
+{
|
|
|
+ public class LiveConsole : NbsComponentBase
|
|
|
+ {
|
|
|
+ public LiveConsole() : base(LiveConsoleLogger.Null)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ private readonly BlockingCollection<LiveConsoleItem> _queue = new();
|
|
|
+
|
|
|
+ private int RequestsHandled = 0;
|
|
|
+ private int InBytes = 0;
|
|
|
+ private int OutBytes = 0;
|
|
|
+
|
|
|
+ private List<LogEntry> _logs = new();
|
|
|
+
|
|
|
+ public void Enqueue(LiveConsoleItem item)
|
|
|
+ {
|
|
|
+ if (!_queue.IsAddingCompleted) _queue.TryAdd(item);
|
|
|
+ }
|
|
|
+
|
|
|
+ public LiveConsoleLogger CreateLogger(string tag) => new(this, tag);
|
|
|
+
|
|
|
+ protected override void OnStart() => Task.Run(RunInternal);
|
|
|
+
|
|
|
+ protected override void OnStop()
|
|
|
+ {
|
|
|
+ _queue.CompleteAdding();
|
|
|
+
|
|
|
+ var wait = 0;
|
|
|
+ while (_queue.Count != 0 && wait < 10)
|
|
|
+ {
|
|
|
+ Thread.Sleep(500);
|
|
|
+ ++wait;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void RunInternal()
|
|
|
+ {
|
|
|
+ Table tableMain;
|
|
|
+ TableColumn ct1UpTime;
|
|
|
+ TableColumn ct2RequestHandled;
|
|
|
+ {
|
|
|
+ tableMain = new Table() { Border = TableBorder.None, Expand = true };
|
|
|
+ var colMain = new TableColumn("");
|
|
|
+ tableMain.AddColumn(colMain);
|
|
|
+ var tableTitle = new Table();
|
|
|
+ {
|
|
|
+ ct1UpTime = new TableColumn("");
|
|
|
+ ct2RequestHandled = new TableColumn("");
|
|
|
+ tableTitle.AddColumn(ct1UpTime);
|
|
|
+ tableTitle.AddColumn(ct2RequestHandled);
|
|
|
+ }
|
|
|
+ colMain.Header = tableTitle;
|
|
|
+
|
|
|
+ tableMain.AddRow(new Panel("Logs Brrr"));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ ct2RequestHandled.Header = new Text($"Reqs: {RequestsHandled} In: {InBytes} Out: {OutBytes}");
|
|
|
+
|
|
|
+ do
|
|
|
+ {
|
|
|
+ AnsiConsole.Clear();
|
|
|
+ var live = AnsiConsole.Live(tableMain);
|
|
|
+ live.Cropping(VerticalOverflowCropping.Bottom)
|
|
|
+ .Start(ctx =>
|
|
|
+ {
|
|
|
+ var conW = Console.WindowWidth;
|
|
|
+ var conH = Console.WindowHeight;
|
|
|
+ do
|
|
|
+ {
|
|
|
+ void RefreshCycle()
|
|
|
+ {
|
|
|
+ var now = DateTime.Now;
|
|
|
+ var up = now - NbsProgram.StartTime;
|
|
|
+ ct1UpTime.Header = new Text($"UP: {(int)up.TotalDays:00}D {up.Hours:00}H {up.Minutes:00}M {up.Seconds:00}S {up.Milliseconds:000}");
|
|
|
+ if (_logs.Any() && Console.WindowHeight > 4) tableMain.UpdateCell(0, 0, new Rows(_logs.TakeLast(conH - 4).Select(p => p.ToMarkup(conW))));
|
|
|
+ ctx.Refresh();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (conW != Console.WindowWidth || conH != Console.WindowHeight)
|
|
|
+ {
|
|
|
+ live.AutoClear = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (_queue.TryTake(out var item, 1000))
|
|
|
+ {
|
|
|
+ switch (item.Type)
|
|
|
+ {
|
|
|
+ case LiveConsoleItemType.Log:
|
|
|
+ _logs.Add(item.ToLog());
|
|
|
+ RefreshCycle();
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ RefreshCycle();
|
|
|
+ }
|
|
|
+ } while (_queue.IsAddingCompleted == false || _queue.Count > 0);
|
|
|
+ });
|
|
|
+ } while (_queue.IsAddingCompleted == false || _queue.Count > 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|