Skip to content
ConsoleMonster

Live sessions

A live session redraws about 15 times a second while any thread posts updates, captures console output and handles resizes and small windows.

LiveSession owns the screen while work runs. Updates are LiveEvents addressed to widgets by name; they go into a lock-free queue and are applied on the render thread, which composes the tree, diffs it against the previous frame and writes only the cells that changed, about 15 times a second.

using ConsoleMonster;
using ConsoleMonster.Building;
using ConsoleMonster.Live;
using ConsoleMonster.Styling;
using ConsoleMonster.Widgets;

Dashboard dashboard = new DashboardBuilder("Deploy")
    .Panel("Servers", new Lanes(), out Lanes lanes, caption: "4 workers")
    .Panel("Log", new LogRegion(), out LogRegion log, fill: true)
    .BuildDashboard();

using (LiveSession session = new LiveSession(dashboard)) {
    session.Run(s => {
        LanesHandle servers = lanes.Handle(s);           // thread-safe from any thread
        Parallel.ForEach(new[] { "SRV1", "SRV2", "SRV3" }, server => {
            servers.Start(server);
            servers.Advance(server, StatusKind.Pass, "copying files");
            Console.WriteLine(server + " done");          // captured into the log region
            servers.Complete(server);
        });
    });
}

This is the README's example. The live dashboards page replays the showcases that use the same API under load.

What a session takes care of

  • Threads. Handles (lanes.Handle(session)) post events from any thread. An ambient TerminalScope lets deep code report status without passing the session around.
  • Console output. Console.Out and Console.Error are captured into the log region while the session runs (CaptureConsole, on by default). In PowerShell, Start-ConsoleDashboard runs the script in a runspace whose Write-Host, warnings, errors and verbose output land there too.
  • The end. The screen is restored, also on Ctrl+C and exceptions, and the final state (or LiveSessionOptions.Summary) is printed to the scrollback.
  • Problems. Updates for unknown names, failed updates and frames that could not be laid out are counted (GetCounters()) and reported once the screen is restored.

Inline areas and Write-Progress

LiveMode.Inline (Start-ConsoleDashboard -Inline) draws an area as tall as its content below the cursor; output scrolls above it and the final state stays in the scrollback, or nothing with -Transient. Write-Progress in a dashboard script shows as nested activities, and Use-ConsoleProgress renders an existing script's Write-Progress inline without changing it.

Progress columns

Lanes and ProgressBar take a column model. Without Columns they keep the classic layout: label, bar, percentage, pass, fail and warning counts, and the detail.

lanes.Columns = ProgressColumns.Standard();                     // spinner, description, bar, %, count, elapsed, ETA, status
lanes.Columns.Insert(7, ProgressColumns.Rate(unit: "files"));   // "12 files/s"; Rate(bytes: true) shows "1.5 MB/s"
lanes.Columns.Add(ProgressColumns.Custom("Phase", row => row.IsFinished ? "verified" : "copying"));
lanes.HideCompleted = true;                                     // finished lanes leave; the summary line counts them
New-ConsoleLanes -Name servers -Lane 'DC01', 'DC02' -Total 40 -Column Standard, Rate -HideCompleted
New-ConsoleProgress 'Upload' -Total 500MB -Column Description, Bar, Percent, ByteRate, Remaining

Rate and remaining time are smoothed over a moving window (10 seconds by default), so a stalled task's rate falls instead of freezing. When the region is too narrow, the lowest-priority columns go first, and in stream mode the heartbeat line summarises the running lanes through the same columns.

Replaceable regions and live tables

A Slot is a named region whose widget is replaced while the session runs; the swap goes through the update queue, so it is thread-safe and lands between frames. LiveTable is a table whose rows have stable keys and are added, updated, removed or cleared; its column widths only grow, MaxRows keeps the most recent rows and SortColumn keeps them sorted.

$d = New-ConsoleDashboard -Title 'Domain health' {
    New-ConsolePanel -Title 'Domain controllers' { New-ConsoleRegion -Name main { New-ConsoleSpinner -Label 'Querying' } }
    New-ConsolePanel -Title 'Jobs' -Fill { New-ConsoleLiveTable -Name jobs -Column 'Job', 'State', 'Took' -MaxRows 8 }
}
Start-ConsoleDashboard $d {
    Update-ConsoleTable -Name jobs -Key 'dns@DC01' -Value 'dns', 'Running', ([timespan]::Zero)
    Set-ConsoleRegion -Name main { $controllers | Format-ConsoleTable -AsWidget }
}

A recording keeps the text form of row values; region swaps carry in-process widgets and are not replayed.

Resizing and small windows

A size change clears the screen and redraws it; while a window is dragged, redraws are coalesced to at most one every 100 ms. Narrower panels drop optional parts first, table columns hide by priority and tables turn into cards. When the window is smaller than the dashboard's MinimumSize, it keeps its highest-priority panels, and when even those do not fit, it shows one status line.

100×30 100×30
 TestimoX · ad.evotec.xyz forest assessment · 12…  ● evaluating 332 rules on 6 workers  ·  00:00:27 

✓ Discover 2.8s › ✓ Collect 4.0s › ⠋ Evaluate › ○ Report

╭─ Targets ───────────────────────────────────────────── 6 workers ─╮ ╭─ Results ──────────────────╮ │ ⠋ ad.evotec.xyz (domai… ━━━━━━━━━━━━━━━━╾───── 75% ✓ 8 ✗ 1 ▴ 3 │ │ ██████████████████████████ │ │ ✗ eu.ad.evotec.xyz (do… ━━━━━━━━━━━━━━━━━━━━━━ 100% ✓13 ✗ 1 ▴ 1 │ │ █ Passed 138 80% │ │ ▴ DC01.ad.evotec.xyz ━━━━━━━━━━━━━━━━━━━━━━ 100% ✓26 ✗ 0 ▴ 3 │ │ █ Warnings 23 13% │ │ ▴ DC02.ad.evotec.xyz ━━━━━━━━━━━━━━━━━━━━━━ 100% ✓23 ✗ 0 ▴ 6 │ │ █ Failed 6 3% │ │ ✗ DC03.ad.evotec.xyz ━━━━━━━━━━━━━━━━━━━━━━ 100% ✓23 ✗ 3 ▴ 4 │ │ █ Skipped 5 2% │ │ ✗ DC04.ad.evotec.xyz ━━━━━━━━━━━━━━━━━━━━━━ 100% ✓25 ✗ 1 ▴ 3 │ │ ────────────────────────── │ │ ⠦ DC05.ad.evotec.xyz ━━━━━───────────────── 23% ✓ 6 ✗ 0 ▴ 1 │ │ Evaluated 165 / 332 │ │ ⠧ DC06.ad.evotec.xyz ━━━━╾───────────────── 20% ✓ 6 ✗ 0 ▴ 0 │ │ Average r… 8.3 rules/s │ │ ⠇ DC07.eu.ad.evotec.xyz ━━━━━───────────────── 23% ✓ 6 ✗ 0 ▴ 0 │ │ Remaining ~21s │ │ ⠏ DC08.eu.ad.evotec.xyz ━╾──────────────────── 6% ✓ 1 ✗ 0 ▴ 1 │ │ Targets d… 4 / 12 │ │ ⠋ DC09.eu.ad.evotec.xyz ━╾──────────────────── 6% ✓ 1 ✗ 0 ▴ 1 │ │ Targets f… 2 │ │ ○ DC10.eu.ad.evotec.xyz ────────────────────── │ │ │ ╰───────────────────────────────────────────────────────────────────╯ ╰────────────────────────────╯ ╭─ Throughput ─────────── rules/s ─╮ ╭─ Rule duration ────────────╮ ╭─ Failures by category ───────╮ │ 16│ ⢀⠎ │ │ 57│ ███ │ │ Domain c… ▆▆▆▆▆▆▆▆ 1 │ │ │ ⡀ ⡜⠉⠁ │ │ │ ███ ▆▆▆ │ │ Replicat… ▆▆▆▆▆▆▆▆ 1 │ │ │ ⢠⡀ ⢀ ⡰⠱⡀⢠⠢⡀ ⡀ ⡰⡀ ⢀⡠⠜ │ │ │▃▃ ███ ███ │ │ DNS ▆▆▆▆▆▆▆▆ 1 │ │ │ ⡇⠘⠔⠁⠉⠒⠴⠁ ⠱⠃ ⠑⠉⠈⠑⢄⡰⠁⢱⢀⠎ │ │ │██ ███ ███ │ │ Kerberos ▆▆▆▆▆▆▆▆ 1 │ │ │⡸ ⠁ ⠋ │ │ │██ ███ ███ ▆▆▆ │ │ Security 0 │ │ 0│⣁⣀⣀⣀⣀⡠⠤⣀⣀⣀⣀⡠⠤⣀⣀⣀⣀⣀⣀⣀⡠⠤⣀⡠⠔⠊⠢⣀⣀ │ │ │██ ███ ███ ███ ▁▁▁ │ │ Group Po… 0 │ │ └───────────────────────────── │ │ 0│██ ███ ███ ███ ███ ▁▁▁ │ │ Accounts ▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆▆ 2 │ │ █ completed █ failed │ │ 0s 0.25s 1s 2s 8s │ │ PKI 0 │ ╰──────────────────────────────────╯ ╰────────────────────────────╯ ╰──────────────────────────────╯ 00:27 DC09.eu.ad.evotec.xyz: evaluating 30 rules Ctrl+C stop

64×20 64×20
 TestimoX · …  ● evaluating 332 rules on 6 workers  ·  00:00:27 

✓ Discover 2.8s › ✓ Collect 4.0s › ⠋ Evaluate › ○ Report

╭─ Targets ─────────────────── 6 workers ─╮ ╭─ Results ────────╮ │ ⠋ ad.evotec.xy… ━━━─ 75% ✓ 8 ✗ 1 ▴ 3 │ │ ████████████████ │ │ ✗ eu.ad.evotec… ━━━━ 100% ✓13 ✗ 1 ▴ 1 │ │ █ Pass… 138 80% │ │ ▴ DC01.ad.evot… ━━━━ 100% ✓26 ✗ 0 ▴ 3 │ │ █ Warn… 23 13% │ │ ▴ DC02.ad.evot… ━━━━ 100% ✓23 ✗ 0 ▴ 6 │ │ █ Fail… 6 3% │ │ ✗ DC03.ad.evot… ━━━━ 100% ✓23 ✗ 3 ▴ 4 │ │ █ Skip… 5 2% │ │ ✗ DC04.ad.evot… ━━━━ 100% ✓25 ✗ 1 ▴ 3 │ │ ──────────────── │ │ ⠦ DC05.ad.evot… ━─── 23% ✓ 6 ✗ 0 ▴ 1 │ │ Evalu… 165 / │ │ ⠧ DC06.ad.evot… ━─── 20% ✓ 6 ✗ 0 ▴ 0 │ │ 332 │ │ ⠇ DC07.eu.ad.e… ━─── 23% ✓ 6 ✗ 0 ▴ 0 │ │ Avera… 8.3 │ │ ⠏ DC08.eu.ad.e… ╾─── 6% ✓ 1 ✗ 0 ▴ 1 │ │ rules/s │ │ ⠋ DC09.eu.ad.e… ╾─── 6% ✓ 1 ✗ 0 ▴ 1 │ │ Remai… ~21s │ │ ○ DC10.eu.ad.e… ──── │ │ Targe… 4 / │ │ │ │ 12 │ ╰─────────────────────────────────────────╯ ╰──────────────────╯ Ctrl+C stop

50×12 50×12
TestimoX · 172/332 · ✗6 ▴23 · 00:00… · needs 60×20
 ✓ Discover 2.8s › ✓ Collect 4.0s › ⠋ Evaluate
 ○ Report

⠋ ad.evotec.xyz (… ━━━━━━━━━─── 75% ✓ 8 ✗ 1 ▴ 3 ✗ DC04.ad.evotec.… ━━━━━━━━━━━━ 100% ✓25 ✗ 1 ▴ 3 ⠦ DC05.ad.evotec.… ━━━───────── 23% ✓ 6 ✗ 0 ▴ 1 ⠧ DC06.ad.evotec.… ━━╾───────── 20% ✓ 6 ✗ 0 ▴ 0 ⠇ DC07.eu.ad.evot… ━━━───────── 23% ✓ 6 ✗ 0 ▴ 0 ⠏ DC08.eu.ad.evot… ━─────────── 6% ✓ 1 ✗ 0 ▴ 1 ⠋ DC09.eu.ad.evot… ━─────────── 6% ✓ 1 ✗ 0 ▴ 1 +5 more · 4 done · 1 queued

The assessment dashboard halfway through its recording, composed at 100×30, 64×20 and 50×12. Its MinimumSize is 60×20.

Without a console

In CI, with redirected output and in stream mode, a session narrates append-only lines instead of redrawing, with [mm:ss] prefixes when a CI system is detected. Plain mode does the same in ASCII without colour, and text that reaches stream and plain output is stripped of escape sequences and control characters.

Edit this page on GitHub