Merge Dashboards & Dev Tools; WaterfallSpan; port to public ChartSpec

This commit is contained in:
ZacharyZhang-NY committed 2026-10-05 15:46:01 -04:00
1 parent 2a70035674
commit 408aa3ba7d
3 files changed
+16 -16

No files matched your search

+5 -5
View File
@@ -14,8 +14,8 @@ import (
"mujicaui/theme"
)
// TraceSpan is one timed operation of a request; Parent is "" for the root.
type TraceSpan struct {
// WaterfallSpan is one timed operation of a request; Parent is "" for the root.
type WaterfallSpan struct {
ID, Parent string
Name string
Service string
@@ -45,7 +45,7 @@ type traceState struct {
}
// TraceWaterfall lays spans out by parent and time; choosing a span shows its detail.
func TraceWaterfall(c *ui.Context, spans []TraceSpan, opts TraceWaterfallOptions) ChoiceResult {
func TraceWaterfall(c *ui.Context, spans []WaterfallSpan, opts TraceWaterfallOptions) ChoiceResult {
if opts.Height < 0 {
panic("mujica: TraceWaterfall Height is negative")
}
@@ -89,7 +89,7 @@ func TraceWaterfall(c *ui.Context, spans []TraceSpan, opts TraceWaterfallOptions
}
// traceLayout orders spans depth-first by start, only when the spans change.
func traceLayout(st *traceState, spans []TraceSpan) {
func traceLayout(st *traceState, spans []WaterfallSpan) {
key := fmt.Sprintf("%d", len(spans))
if len(spans) > 0 {
key += fmt.Sprintf("%p", &spans[0])
@@ -135,7 +135,7 @@ func traceLayout(st *traceState, spans []TraceSpan) {
}
// traceSpanRow shows a span's name indented by depth beside its bar; it reports a choice.
func traceSpanRow(c *ui.Context, s TraceSpan, depth int, total time.Duration, slot int, selected bool) bool {
func traceSpanRow(c *ui.Context, s WaterfallSpan, depth int, total time.Duration, slot int, selected bool) bool {
k := Tokens(c)
d := Density(c)
u := d.Unit()
+6 -6
View File
@@ -8,14 +8,14 @@ import (
"github.com/egoist/mygo/ui"
)
var traceSample = []TraceSpan{
var traceSample = []WaterfallSpan{
{ID: "db", Parent: "api", Name: "SELECT guests", Service: "postgres", Start: 40 * time.Millisecond, Duration: 90 * time.Millisecond},
{ID: "root", Name: "GET /ball", Service: "gateway", Duration: 320 * time.Millisecond},
{ID: "api", Parent: "root", Name: "ListGuests", Service: "api", Start: 20 * time.Millisecond, Duration: 200 * time.Millisecond},
{ID: "pay", Parent: "root", Name: "Charge", Service: "payments", Start: 230 * time.Millisecond, Duration: 80 * time.Millisecond, Error: true},
}
func traceTester(spans []TraceSpan, changes *int) *ui.Tester {
func traceTester(spans []WaterfallSpan, changes *int) *ui.Tester {
return ui.NewTester(func(c *ui.Context) {
Use(c, Settings{})
if TraceWaterfall(c, spans, TraceWaterfallOptions{}).Changed() {
@@ -54,10 +54,10 @@ func TestTraceWaterfallRulesAndMany(t *testing.T) {
if !tt.HasText("No spans") {
t.Fatal("empty")
}
many := make([]TraceSpan, 100000)
many[0] = TraceSpan{ID: "0", Name: "root", Duration: time.Second}
many := make([]WaterfallSpan, 100000)
many[0] = WaterfallSpan{ID: "0", Name: "root", Duration: time.Second}
for i := 1; i < len(many); i++ {
many[i] = TraceSpan{ID: fmt.Sprint(i), Parent: "0", Name: fmt.Sprint("span ", i), Start: time.Duration(i) * time.Microsecond, Duration: time.Microsecond}
many[i] = WaterfallSpan{ID: fmt.Sprint(i), Parent: "0", Name: fmt.Sprint("span ", i), Start: time.Duration(i) * time.Microsecond, Duration: time.Microsecond}
}
tt = traceTester(many, &n)
if got := len(tt.Texts()); got > 400 {
@@ -68,7 +68,7 @@ func TestTraceWaterfallRulesAndMany(t *testing.T) {
t.Fatal("cycle did not panic")
}
}()
traceTester([]TraceSpan{{ID: "a", Parent: "b", Name: "a"}, {ID: "b", Parent: "a", Name: "b"}}, &n)
traceTester([]WaterfallSpan{{ID: "a", Parent: "b", Name: "a"}, {ID: "b", Parent: "a", Name: "b"}}, &n)
}
func TestTraceWaterfallSnapshot(t *testing.T) {
+5 -5
View File
@@ -60,9 +60,9 @@ func UptimeBar(c *ui.Context, days []UptimeDay, opts UptimeBarOptions) ChartResu
return 0
}
words := [...]string{msg(c, "uptime_bar.ok"), msg(c, "uptime_bar.degraded"), msg(c, "uptime_bar.down"), msg(c, "uptime_bar.nodata")}
res, _ := ch.build(chartSpec{
n: n,
draw: func(p *ui.Painter, r ui.Rect, active int) {
res, _ := ch.build(ChartSpec{
Marks: n,
Draw: func(p *ui.Painter, r ui.Rect, active int) {
b := band(r)
for i, d := range days {
x, w := internal.Snap(p, b.Start(i)), max(b.Width(), 1)
@@ -76,11 +76,11 @@ func UptimeBar(c *ui.Context, days []UptimeDay, opts UptimeBarOptions) ChartResu
}
}
},
pick: func(r ui.Rect, x, _ float32) int {
Pick: func(r ui.Rect, x, _ float32) int {
b := band(r)
return max(0, min(n-1, int((x-r.X)/b.Step())))
},
readout: func(i int) string {
Readout: func(i int) string {
d := days[i]
s := fmt.Sprintf("%s · %s", d.Date.String(), words[level(d.Uptime)])
if !math.IsNaN(d.Uptime) {