feat(tui): ntcharts latency line chart in inline detail panel
Replace block-element sparkline with ntcharts streamline chart in the inline detail panel. Renders a 4-row line chart with thin line style using the theme accent color. Auto-scales Y axis to latency range. Added github.com/NimbleMarkets/ntcharts v0.5.1 dependency (lipgloss v1 compatible). Min/Avg/Max stats rendered below the chart.
This commit is contained in:
@@ -3,6 +3,7 @@ module gitea.lerkolabs.com/lerkolabs/uptop
|
|||||||
go 1.26.4
|
go 1.26.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/NimbleMarkets/ntcharts v0.5.1
|
||||||
github.com/charmbracelet/bubbles v0.21.1-0.20250623103423-23b8fd6302d7
|
github.com/charmbracelet/bubbles v0.21.1-0.20250623103423-23b8fd6302d7
|
||||||
github.com/charmbracelet/bubbletea v1.3.10
|
github.com/charmbracelet/bubbletea v1.3.10
|
||||||
github.com/charmbracelet/harmonica v0.2.0
|
github.com/charmbracelet/harmonica v0.2.0
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||||
|
github.com/NimbleMarkets/ntcharts v0.5.1 h1:HWtekubEXfESwi24pyFynwGo2Hulbb9fPh7INMUc1dg=
|
||||||
|
github.com/NimbleMarkets/ntcharts v0.5.1/go.mod h1:zVeRqYkh2n59YPe1bflaSL4O2aD2ZemNmrbdEqZ70hk=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
|
||||||
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package tui
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/NimbleMarkets/ntcharts/canvas/runes"
|
||||||
|
"github.com/NimbleMarkets/ntcharts/linechart/streamlinechart"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (m Model) latencyChart(latencies []time.Duration, statuses []bool, width, height int) string {
|
||||||
|
if len(latencies) == 0 || width < 10 || height < 3 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
lineStyle := lipgloss.NewStyle().Foreground(m.theme.Accent)
|
||||||
|
slc := streamlinechart.New(width, height,
|
||||||
|
streamlinechart.WithStyles(runes.ThinLineStyle, lineStyle),
|
||||||
|
)
|
||||||
|
|
||||||
|
for i, l := range latencies {
|
||||||
|
ms := float64(l.Milliseconds())
|
||||||
|
if i < len(statuses) && !statuses[i] {
|
||||||
|
ms = 0
|
||||||
|
}
|
||||||
|
slc.Push(ms)
|
||||||
|
}
|
||||||
|
slc.Draw()
|
||||||
|
|
||||||
|
return slc.View()
|
||||||
|
}
|
||||||
@@ -142,7 +142,7 @@ func (m *Model) handleFormMsg(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const detailInlineHeight = 8
|
const detailInlineHeight = 12
|
||||||
|
|
||||||
func (m *Model) recalcLayout() {
|
func (m *Model) recalcLayout() {
|
||||||
chrome := chromeBase
|
chrome := chromeBase
|
||||||
|
|||||||
@@ -67,14 +67,16 @@ func (m Model) viewDetailInline(width int) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(hist.Latencies) > 0 {
|
if len(hist.Latencies) > 0 {
|
||||||
sparkW := width - 30
|
chartW := width - 4
|
||||||
if sparkW < 10 {
|
if chartW < 20 {
|
||||||
sparkW = 10
|
chartW = 20
|
||||||
}
|
}
|
||||||
if sparkW > detailSparkWidth {
|
chartH := 4
|
||||||
sparkW = detailSparkWidth
|
chart := m.latencyChart(hist.Latencies, hist.Statuses, chartW, chartH)
|
||||||
|
if chart != "" {
|
||||||
|
b.WriteString(chart + "\n")
|
||||||
}
|
}
|
||||||
spark := m.latencySparkline(hist.Latencies, hist.Statuses, sparkW, m.theme.Bg)
|
|
||||||
minMs := hist.Latencies[0].Milliseconds()
|
minMs := hist.Latencies[0].Milliseconds()
|
||||||
maxMs := hist.Latencies[0].Milliseconds()
|
maxMs := hist.Latencies[0].Milliseconds()
|
||||||
var sumMs int64
|
var sumMs int64
|
||||||
@@ -93,7 +95,7 @@ func (m Model) viewDetailInline(width int) string {
|
|||||||
m.fmtLatency(time.Duration(minMs)*time.Millisecond),
|
m.fmtLatency(time.Duration(minMs)*time.Millisecond),
|
||||||
m.fmtLatency(time.Duration(avgMs)*time.Millisecond),
|
m.fmtLatency(time.Duration(avgMs)*time.Millisecond),
|
||||||
m.fmtLatency(time.Duration(maxMs)*time.Millisecond))
|
m.fmtLatency(time.Duration(maxMs)*time.Millisecond))
|
||||||
b.WriteString(" " + spark + " " + stats + "\n")
|
b.WriteString(stats + "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
keys := m.st.subtleStyle.Render("[h] History [s] SLA [e] Edit [esc] Close")
|
keys := m.st.subtleStyle.Render("[h] History [s] SLA [e] Edit [esc] Close")
|
||||||
|
|||||||
Reference in New Issue
Block a user