Merge Dashboards & Dev Tools; WaterfallSpan; port to public ChartSpec
This commit is contained in:
3 files changed
+16
-16
No files matched your search
+5
-5
@@ -14,8 +14,8 @@ import (
|
|||||||
"mujicaui/theme"
|
"mujicaui/theme"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TraceSpan is one timed operation of a request; Parent is "" for the root.
|
// WaterfallSpan is one timed operation of a request; Parent is "" for the root.
|
||||||
type TraceSpan struct {
|
type WaterfallSpan struct {
|
||||||
ID, Parent string
|
ID, Parent string
|
||||||
Name string
|
Name string
|
||||||
Service string
|
Service string
|
||||||
@@ -45,7 +45,7 @@ type traceState struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TraceWaterfall lays spans out by parent and time; choosing a span shows its detail.
|
// 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 {
|
if opts.Height < 0 {
|
||||||
panic("mujica: TraceWaterfall Height is negative")
|
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.
|
// 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))
|
key := fmt.Sprintf("%d", len(spans))
|
||||||
if len(spans) > 0 {
|
if len(spans) > 0 {
|
||||||
key += fmt.Sprintf("%p", &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.
|
// 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)
|
k := Tokens(c)
|
||||||
d := Density(c)
|
d := Density(c)
|
||||||
u := d.Unit()
|
u := d.Unit()
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ import (
|
|||||||
"github.com/egoist/mygo/ui"
|
"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: "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: "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: "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},
|
{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) {
|
return ui.NewTester(func(c *ui.Context) {
|
||||||
Use(c, Settings{})
|
Use(c, Settings{})
|
||||||
if TraceWaterfall(c, spans, TraceWaterfallOptions{}).Changed() {
|
if TraceWaterfall(c, spans, TraceWaterfallOptions{}).Changed() {
|
||||||
@@ -54,10 +54,10 @@ func TestTraceWaterfallRulesAndMany(t *testing.T) {
|
|||||||
if !tt.HasText("No spans") {
|
if !tt.HasText("No spans") {
|
||||||
t.Fatal("empty")
|
t.Fatal("empty")
|
||||||
}
|
}
|
||||||
many := make([]TraceSpan, 100000)
|
many := make([]WaterfallSpan, 100000)
|
||||||
many[0] = TraceSpan{ID: "0", Name: "root", Duration: time.Second}
|
many[0] = WaterfallSpan{ID: "0", Name: "root", Duration: time.Second}
|
||||||
for i := 1; i < len(many); i++ {
|
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)
|
tt = traceTester(many, &n)
|
||||||
if got := len(tt.Texts()); got > 400 {
|
if got := len(tt.Texts()); got > 400 {
|
||||||
@@ -68,7 +68,7 @@ func TestTraceWaterfallRulesAndMany(t *testing.T) {
|
|||||||
t.Fatal("cycle did not panic")
|
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) {
|
func TestTraceWaterfallSnapshot(t *testing.T) {
|
||||||
|
|||||||
+5
-5
@@ -60,9 +60,9 @@ func UptimeBar(c *ui.Context, days []UptimeDay, opts UptimeBarOptions) ChartResu
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
words := [...]string{msg(c, "uptime_bar.ok"), msg(c, "uptime_bar.degraded"), msg(c, "uptime_bar.down"), msg(c, "uptime_bar.nodata")}
|
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{
|
res, _ := ch.build(ChartSpec{
|
||||||
n: n,
|
Marks: n,
|
||||||
draw: func(p *ui.Painter, r ui.Rect, active int) {
|
Draw: func(p *ui.Painter, r ui.Rect, active int) {
|
||||||
b := band(r)
|
b := band(r)
|
||||||
for i, d := range days {
|
for i, d := range days {
|
||||||
x, w := internal.Snap(p, b.Start(i)), max(b.Width(), 1)
|
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)
|
b := band(r)
|
||||||
return max(0, min(n-1, int((x-r.X)/b.Step())))
|
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]
|
d := days[i]
|
||||||
s := fmt.Sprintf("%s · %s", d.Date.String(), words[level(d.Uptime)])
|
s := fmt.Sprintf("%s · %s", d.Date.String(), words[level(d.Uptime)])
|
||||||
if !math.IsNaN(d.Uptime) {
|
if !math.IsNaN(d.Uptime) {
|
||||||
|
|||||||
Reference in new issue
Block a user