Real-Time Dashboards¶
The GraphDashboard class provides a unified interface for tracking and displaying multiple named metric streams simultaneously.
Instead of writing log lines continuously and flooding your terminal screen history, GraphDashboard manages terminal cursors to perform in-place updates.
Basic Concept¶
When you track metrics in a monitoring loop, writing new lines pushes old logs upward, creating an endless trail of text.
GraphDashboard prevents this:
1. It records and keeps separate buffers for each metric name.
2. When .print() is called in a Node.js terminal, it calculates how many lines are in the dashboard and writes ANSI cursor movements (\x1b[NA where N is the line count) to jump back up to the top of the dashboard section, then overwrites the old values cleanly.
3. In Browser consoles, it issues a console.clear() command before re-logging the dashboard lines to create a clean visual panel.
Setting Up a Dashboard¶
Here is a typical implementation simulating a server health dashboard:
import { GraphDashboard } from 'console-graph';
// Create a dashboard with default global options
const dashboard = new GraphDashboard({
bufferSize: 30,
gradient: 'heat',
});
let tick = 0;
setInterval(() => {
// 1. Gather/simulate metrics
const cpu = 20 + Math.sin(tick / 5) * 15 + Math.random() * 5;
const memory = 150 + tick * 0.5 - (tick % 10 === 0 ? 30 : 0);
const latency = 10 + Math.random() * 50;
// 2. Log values (specify overrides like unit or gradient individually)
dashboard.log('CPU', cpu, { unit: '%', min: 0, max: 100 });
dashboard.log('Memory', memory, { unit: 'MB', gradient: 'green' });
dashboard.log('Latency', latency, { unit: 'ms', gradient: 'ocean' });
// 3. Print the consolidated panel
dashboard.print();
tick++;
}, 500);
Flicker Mitigation in Node.js¶
The cursor repositioning mechanism inside GraphDashboard.print() uses standard raw TTY write streams to achieve screen manipulation with zero external binary helper libraries:
// Internal dashboard print logic
const count = this._graphs.size;
if (this._printed) {
process.stdout.write(`\x1b[${count}A`); // Move cursor up count lines
}
for (const graph of this._graphs.values()) {
const output = graph._render();
process.stdout.clearLine && process.stdout.clearLine(0); // Clear current line
process.stdout.cursorTo && process.stdout.cursorTo(0); // Shift cursor to position 0
console.log(output.colored.text);
}
this._printed = true;
Best Practices¶
- Padded Metric Names: To ensure your sparklines align vertically, pad your metric names to equal length:
- Avoid Mixed Output: Avoid calling standard
console.log()while a dashboard is actively printing at short intervals. Standard logs will disrupt the cursor offset tracking, causing lines to scramble. If you need to print standard message logs, write them silently to a file or temporarily pause dashboard printing.