From 9e58bb41727251b77e9ff5606fe8a49fc43d8b4d Mon Sep 17 00:00:00 2001 From: "Y.Matsuda" Date: Sun, 31 Mar 2024 11:52:16 +0900 Subject: [PATCH] dynamic time unit support --- .../internal/tui/component/timeline.go | 40 ++++++++++++--- .../internal/tui/component/timeline_test.go | 51 +++++++++++++++++++ 2 files changed, 84 insertions(+), 7 deletions(-) diff --git a/tuiexporter/internal/tui/component/timeline.go b/tuiexporter/internal/tui/component/timeline.go index 5ea510c..fdac067 100644 --- a/tuiexporter/internal/tui/component/timeline.go +++ b/tuiexporter/internal/tui/component/timeline.go @@ -45,10 +45,14 @@ func DrawTimeline(traceID string, cache *telemetry.TraceCache, setFocusFn func(p } // Write some text along the horizontal line. - durunit := duration.Milliseconds() / 10 - tview.Print(screen, "0", x+getXByRatio(0, width), centerY, width-2, tview.AlignLeft, tcell.ColorYellow) - for i := 1; i < 10; i++ { - tview.Print(screen, fmt.Sprintf("%dms", durunit*int64(i)), x+getXByRatio(float64(i)*0.1, width), centerY, width-2, tview.AlignLeft, tcell.ColorYellow) + unit, count := calculateTimelineUnit(duration) + for i := 0; i < count; i++ { + ratio := float64(i) / float64(count) + label := roundDownDuration(unit * time.Duration(i)).String() + if i == 0 { + label = "0" + } + tview.Print(screen, label, x+getXByRatio(ratio, width), centerY, width-2, tview.AlignLeft, tcell.ColorYellow) } // Space for other content. @@ -131,6 +135,28 @@ func DrawTimeline(traceID string, cache *telemetry.TraceCache, setFocusFn func(p } } +func calculateTimelineUnit(duration time.Duration) (unit time.Duration, count int) { + // TODO: set count depends on the width + count = 5 + unit = duration / time.Duration(count) + return +} + +func roundDownDuration(d time.Duration) time.Duration { + if d < time.Microsecond { + return d - (d % time.Nanosecond) + } else if d < time.Millisecond { + return d - (d % time.Microsecond) + } else if d < time.Second { + return d - (d % time.Millisecond) + } else if d < time.Minute { + return d - (d % time.Second) + } else if d < time.Hour { + return d - (d % time.Minute) + } + return d +} + func placeSpan(grid *tview.Grid, node *spanTreeNode, row, depth int, tvs *[]*tview.TextView, nodes *[]*spanTreeNode) int { row++ label := node.label @@ -181,8 +207,8 @@ func newSpanTree(traceID string, cache *telemetry.TraceCache) (rootNodes []*span node := nodes[spanMemo[current]] st, en := span.Span.StartTimestamp().AsTime().Sub(start), span.Span.EndTimestamp().AsTime().Sub(start) d := en - st - node.box = createSpan(current, int(duration.Milliseconds()), int(st.Milliseconds()), int(en.Milliseconds())) - node.label = fmt.Sprintf("%s %dms", span.Span.Name(), d.Milliseconds()) + node.box = createSpan(current, duration, st, en) + node.label = fmt.Sprintf("%s %s", span.Span.Name(), d.String()) parent := span.Span.ParentSpanID().String() _, parentExists := cache.GetSpanByID(parent) @@ -224,7 +250,7 @@ func getXByRatio(ratio float64, width int) int { return int(float64(width) * ratio) } -func createSpan(name string, total, start, end int) (span *tview.Box) { +func createSpan(name string, total, start, end time.Duration) (span *tview.Box) { return tview.NewBox().SetBorder(false). SetDrawFunc(func(screen tcell.Screen, x, y, width, height int) (int, int, int, int) { // Draw a horizontal line across the middle of the box. diff --git a/tuiexporter/internal/tui/component/timeline_test.go b/tuiexporter/internal/tui/component/timeline_test.go index 84ea673..1e6c259 100644 --- a/tuiexporter/internal/tui/component/timeline_test.go +++ b/tuiexporter/internal/tui/component/timeline_test.go @@ -52,3 +52,54 @@ func TestNewSpanTree(t *testing.T) { assert.Equal(t, sds[4].Span, st[1].span.Span) assert.Equal(t, sds[5].Span, st[1].children[0].span.Span) } + +func TestRoundDownDuration(t *testing.T) { + tests := []struct { + name string + duration time.Duration + want string + }{ + { + name: "0", + duration: 0, + want: "0s", // do nothing + }, + { + name: "10 nano second", + duration: 10 * time.Nanosecond, + want: "10ns", // do nothing + }, + { + name: "10.25 micro second", + duration: 10250 * time.Nanosecond, + want: "10µs", + }, + { + name: "10.25 milli second", + duration: 10250 * time.Microsecond, + want: "10ms", + }, + { + name: "10.25 second", + duration: 10250 * time.Millisecond, + want: "10s", + }, + { + name: "10.25 minute", + duration: 615 * time.Second, + want: "10m0s", + }, + { + name: "10.25 hour", + duration: 615 * time.Minute, + want: "10h15m0s", // do nothing + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := roundDownDuration(tt.duration) + assert.Equal(t, tt.want, got.String()) + }) + } +}