// updateChart inserts a dataset into a line chart, scaling appropriately as to // not display weird labels, also updating the chart label accordingly. func updateChart(metric string, data []float64, base *int, chart *termui.LineChart, err error) (realign bool) { dataUnits := []string{"", "K", "M", "G", "T", "E"} timeUnits := []string{"ns", "µs", "ms", "s", "ks", "ms"} colors := []termui.Attribute{termui.ColorBlue, termui.ColorCyan, termui.ColorGreen, termui.ColorYellow, termui.ColorRed, termui.ColorRed} // Extract only part of the data that's actually visible if chart.Width*2 < len(data) { data = data[:chart.Width*2] } // Find the maximum value and scale under 1K high := 0.0 if len(data) > 0 { high = data[0] for _, value := range data[1:] { high = math.Max(high, value) } } unit, scale := 0, 1.0 for high >= 1000 && unit+1 < len(dataUnits) { high, unit, scale = high/1000, unit+1, scale*1000 } // If the unit changes, re-create the chart (hack to set max height...) if unit != *base { realign, *base, *chart = true, unit, *createChart(chart.Height) } // Update the chart's data points with the scaled values if cap(chart.Data) < len(data) { chart.Data = make([]float64, len(data)) } chart.Data = chart.Data[:len(data)] for i, value := range data { chart.Data[i] = value / scale } // Update the chart's label with the scale units units := dataUnits if strings.Contains(metric, "/Percentiles/") || strings.Contains(metric, "/pauses/") || strings.Contains(metric, "/time/") { units = timeUnits } chart.Border.Label = metric if len(units[unit]) > 0 { chart.Border.Label += " [" + units[unit] + "]" } chart.LineColor = colors[unit] | termui.AttrBold if err != nil { chart.LineColor = termui.ColorRed | termui.AttrBold } return }
func UpdateGenericChart(l *ui.LineChart, updateFunc func() float64) { data := make([]float64, 150) for { for i := len(data) - 1; i > 0; i-- { data[i] = data[i-1] } data[0] = updateFunc() l.Data = data time.Sleep(500 * time.Millisecond) } }