asciigraph

repository·master·Indexed 25 days ago

https://github.com/guptarohit/asciigraph

A lightweight Go package and CLI tool used to generate ASCII line graphs. It supports single and multiple data series, custom formatting, coloring, and threshold highlighting. The library provides functions like Plot() and PlotMany(), while the CLI supports piping data from stdin for static or real-time streaming graphs with customizable dimensions, legends, and ANSI colors.

Tokens
4.9K
Snippets
13
Records
29
Agent score
84%

What's inside asciigraph

  1. Install the asciigraph CLI

    master

    You can install the asciigraph command-line utility using go install (assuming $GOPATH/bin is in your $PATH), by pulling the Docker image, or by downloading binaries from the releases page.

    Via Go Install:

    go install github.com/guptarohit/asciigraph/cmd/asciigraph@latest

    Via Docker:

    docker pull ghcr.io/guptarohit/asciigraph:latest
  2. Install and run asciigraph via CLI or Docker

    master

    You can use asciigraph by piping data points into it via stdin. You can install it locally or run it using a Docker image.

    To feed data points via stdin:

    seq 1 72 | asciigraph -h 10 -c "plot data from stdin" -xmin 0 -xmax 40 -xt 5

    To use the Docker image:

    seq 1 72 | docker run -i --rm ghcr.io/guptarohit/asciigraph -h 10 -c "plot data from stdin" -xmin 0 -xmax 40 -xt 5
    seq 1 72 | asciigraph -h 10 -c "plot data from stdin" -xmin 0 -xmax 40 -xt 5
  3. Use the asciigraph CLI to plot data from stdin

    master

    The asciigraph CLI tool reads data points from stdin and renders them as an ASCII graph. Data should be provided as lines of values, with each value representing a data point in a series. If multiple series are used, provide values separated by a delimiter (default is a comma ,).

    Usage:

    [command/data source] | asciigraph [options]

    Note: Invalid values in the input stream are logged to stderr and ignored.

  4. Use asciigraph for real-time data streaming

    master

    To enable real-time graphing for a continuous data stream, use the -r flag. This is useful for monitoring live metrics like ping latency.

    Example of a real-time graph for Google ping latency:

    ping -i.2 google.com | grep -oP '(?<=time=).*(?=ms)' --line-buffered | asciigraph -r -h 10 -w 40 -c "realtime plot data (google ping in ms) from stdin"
    ping -i.2 google.com | grep -oP '(?<=time=).*(?=ms)' --line-buffered | asciigraph -r -h 10 -w 40 -c "realtime plot data (google ping in ms) from stdin"
  5. Create multi-series real-time graphs

    master

    For datasets with multiple columns (series), use the -sn flag to specify the number of series, -sc to set series colors, and -sl to provide legends for each series. Data should be delimited (default is ,).

    Example comparing Google vs DuckDuckGo ping latency:

    {unbuffer paste -d, <(ping -i 0.4 google.com | sed -u -n -E 's/.*time=(.*)ms.*/\1/p') <(ping -i 0.4 duckduckgo.com | sed -u -n -E 's/.*time=(.*)ms.*/\1/p') } | asciigraph -r -h 15 -w 60 -sn 2 -sc "blue,red" -c "Ping Latency Comparison" -sl "Google, DuckDuckGo"
    {unbuffer paste -d, <(ping -i 0.4 google.com | sed -u -n -E 's/.*time=(.*)ms.*/\1/p') <(ping -i 0.4 duckduckgo.com | sed -u -n -E 's/.*time=(.*)ms.*/\1/p') } | asciigraph -r -h 15 -w 60 -sn 2 -sc "blue,red" -c "Ping Latency Comparison" -sl "Google, DuckDuckGo"
  6. Add an X-axis with XAxisRange and XAxisTickCount

    master

    You can add a labeled X-axis using the following options:

    • asciigraph.XAxisRange(min, max): Defines the range for the X-axis.
    • asciigraph.XAxisTickCount(n): Controls the number of tick marks (default is 5, minimum is 2).
    package main
    
    import (
        "fmt"
        "github.com/guptarohit/asciigraph"
    )
    
    func main() {
        data := []float64{3, 4, 9, 6, 2, 4, 5, 8, 5, 10, 2, 7, 2, 5, 6}
        graph := asciigraph.Plot(data,
            asciigraph.XAxisRange(0, 14),
            asciigraph.XAxisTickCount(3),
        )
    
        fmt.Println(graph)
    }
  7. Apply colors to series with SeriesColors

    master

    Use asciigraph.SeriesColors(...) to assign specific colors to each series in a multi-series graph. Supported colors include asciigraph.Red, asciigraph.Yellow, asciigraph.Green, and asciigraph.Blue.

    package main
    
    import (
        "fmt"
        "github.com/guptarohit/asciigraph"
        "math"
    )
    
    func main() {
        data := make([][]float64, 4)
    
        for i := 0; i < 4; i++ {
            for x := -20; x <= 20; x++ {
                v := math.NaN()
                if r := 20 - i; x >= -r && x <= r {
                    v = math.Sqrt(math.Pow(float64(r), 2)-math.Pow(float64(x), 2)) / 2
                }
                data[i] = append(data[i], v)
            }
        }
        graph := asciigraph.PlotMany(data, asciigraph.Precision(0), asciigraph.SeriesColors(
            asciigraph.Red,
            asciigraph.Yellow,
            asciigraph.Green,
            asciigraph.Blue,
        ))
    
        fmt.Println(graph)
    }
  8. Highlight values with threshold coloring

    master

    Use ColorAbove and ColorBelow to highlight points that breach specific thresholds. These take precedence over SeriesColorGradient and SeriesColors.

    • asciigraph.ColorAbove(color, threshold): Colors points where value > threshold.
    • asciigraph.ColorBelow(color, threshold): Colors points where value < threshold.

    If both thresholds match the same point, ColorAbove wins.

    package main
    
    import (
        "fmt"
        "github.com/guptarohit/asciigraph"
    )
    
    func main() {
        data := []float64{42, 48, 55, 81, 85, 91, 87, 34, 12, 17, 10, 18, 55, 50}
        graph := asciigraph.Plot(data,
            asciigraph.Height(10),
            asciigraph.Width(25),
            asciigraph.LowerBound(0),
            asciigraph.UpperBound(100),
            asciigraph.Caption("CPU usage % (red: critical, green: idle)"),
            asciigraph.ColorAbove(asciigraph.Red, 80),
            asciigraph.ColorBelow(asciigraph.Green, 25),
        )
        fmt.Println(graph)
    }
  9. Add legends to colored graphs with SeriesLegends

    master

    Use asciigraph.SeriesLegends(...string) to add labels for each series in a multi-series graph.

    package main
    
    import (
        "fmt"
        "github.com/guptarohit/asciigraph"
        "math"
    )
    
    func main() {
        data := make([][]float64, 3)
        for i := 0; i < 3; i++ {
            for x := -12; x <= 12; x++ {
                v := math.NaN()
                if r := 12 - i; x >= -r && x <= r {
                    v = math.Sqrt(math.Pow(float64(r), 2)-math.Pow(float64(x), 2)) / 2
                }
                data[i] = append(data[i], v)
            }
        }
        graph := asciigraph.PlotMany(data,
            asciigraph.Precision(0),
            asciigraph.SeriesColors(asciigraph.Red, asciigraph.Green, asciigraph.Blue),
            asciigraph.SeriesLegends("Red", "Green", "Blue"),
            asciigraph.Caption("Series with legends"))
        fmt.Println(graph)
    }
  10. Create multiple series graphs with PlotMany()

    master

    Use asciigraph.PlotMany(data) to render a graph containing multiple data series. The input data should be a 2D slice of float64 ([][]float64).

    package main
    
    import (
        "fmt"
        "github.com/guptarohit/asciigraph"
    )
    
    func main() {
        data := [][]float64{{0, 1, 2, 3, 3, 3, 2, 0}, {5, 4, 2, 1, 4, 6, 6}}
        graph := asciigraph.PlotMany(data)
    
        fmt.Println(graph)
    }
  11. Format Y-axis values with YAxisValueFormatter

    master

    Use the asciigraph.YAxisValueFormatter(func(v float64) string) option to customize how values are displayed on the Y-axis. This is useful for adding units like bytes or GiB.

    package main
    
    import (
        "fmt"
        "github.com/guptarohit/asciigraph"
    )
    
    func main() {
        data := []float64{
            30 * 1024 * 1024 * 1024,
            70 * 1024 * 1024 * 1024,
            2 * 1024 * 1024 * 1024,
        }
    
        graph := asciigraph.Plot(data,
            asciigraph.Height(5),
            asciigraph.Width(45),
            asciigraph.YAxisValueFormatter(func(v float64) string {
                return fmt.Sprintf("%.2f GiB", v/1024/1024/1024)
            }),
        )
    
        fmt.Println(graph)
    }