diff --git a/tuiexporter/internal/tui/component/page.go b/tuiexporter/internal/tui/component/page.go index 73089c8..eabe969 100644 --- a/tuiexporter/internal/tui/component/page.go +++ b/tuiexporter/internal/tui/component/page.go @@ -160,7 +160,7 @@ func (p *TUIPages) createTracePage(store *telemetry.Store) *tview.Flex { func (p *TUIPages) createTimelinePage() *tview.Flex { page := tview.NewFlex().SetDirection(tview.FlexRow) - page.Box.SetTitle("Timeline").SetBorder(true) + page.Box.SetBorder(false) page.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { if event.Key() == tcell.KeyEsc { p.pages.SwitchToPage(PAGE_TRACES) diff --git a/tuiexporter/internal/tui/component/timeline.go b/tuiexporter/internal/tui/component/timeline.go index fdac067..9700d45 100644 --- a/tuiexporter/internal/tui/component/timeline.go +++ b/tuiexporter/internal/tui/component/timeline.go @@ -11,6 +11,8 @@ import ( "github.com/ymtdzzz/otel-tui/tuiexporter/internal/telemetry" ) +const TIMELINE_DETAILS_IDX = 1 // index of details in the base flex container + type spanTreeNode struct { span *telemetry.SpanData label string @@ -65,6 +67,7 @@ func DrawTimeline(traceID string, cache *telemetry.TraceCache, setFocusFn func(p SetBorders(true). AddItem(title, 0, 0, 1, 1, 0, 0, false). AddItem(timeline, 0, 1, 1, 1, 0, 0, false) + grid.SetTitle("Trace Timeline (t)").SetBorder(true) var ( tvs []*tview.TextView @@ -88,7 +91,7 @@ func DrawTimeline(traceID string, cache *telemetry.TraceCache, setFocusFn func(p if totalRow > 0 { currentRow := 0 setFocusFn(tvs[currentRow]) - treeTitle := "Span Details" + treeTitle := "Details (d)" grid.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { // FIXME: key 'j' and 'k' should be used to move the focus @@ -100,7 +103,7 @@ func DrawTimeline(traceID string, cache *telemetry.TraceCache, setFocusFn func(p setFocusFn(tvs[currentRow]) // update details - oldDetails := base.GetItem(1) + oldDetails := base.GetItem(TIMELINE_DETAILS_IDX) base.RemoveItem(oldDetails) details := getSpanInfoTree(nodes[currentRow].span, treeTitle) base.AddItem(details, 0, 3, false) @@ -113,7 +116,7 @@ func DrawTimeline(traceID string, cache *telemetry.TraceCache, setFocusFn func(p details = getSpanInfoTree(nodes[currentRow].span, treeTitle) // update details - oldDetails := base.GetItem(1) + oldDetails := base.GetItem(TIMELINE_DETAILS_IDX) base.RemoveItem(oldDetails) details := getSpanInfoTree(nodes[currentRow].span, treeTitle) base.AddItem(details, 0, 3, false) @@ -124,11 +127,25 @@ func DrawTimeline(traceID string, cache *telemetry.TraceCache, setFocusFn func(p }) } - details.SetBorder(true).SetTitle("Span Details") + details.SetBorder(true).SetTitle("Details (d)") base.AddItem(grid, 0, 7, true). AddItem(details, 0, 3, false) + base.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + switch event.Rune() { + case 'd': + log.Printf("d key pressed") + setFocusFn(base.GetItem(TIMELINE_DETAILS_IDX)) + return nil + case 't': + log.Printf("t key pressed") + setFocusFn(grid) + return nil + } + return event + }) + return base, KeyMaps{ *tcell.NewEventKey(tcell.KeyUp, ' ', tcell.ModNone): "Move up", *tcell.NewEventKey(tcell.KeyDown, ' ', tcell.ModNone): "Move down", @@ -398,5 +415,9 @@ func getSpanInfoTree(span *telemetry.SpanData, title string) *tview.TreeView { } root.AddChild(links) + tree.SetSelectedFunc(func(node *tview.TreeNode) { + node.SetExpanded(!node.IsExpanded()) + }) + return tree } diff --git a/tuiexporter/internal/tui/component/trace.go b/tuiexporter/internal/tui/component/trace.go index 91d0e54..7db6baa 100644 --- a/tuiexporter/internal/tui/component/trace.go +++ b/tuiexporter/internal/tui/component/trace.go @@ -92,18 +92,16 @@ func getTraceInfoTree(spans []*telemetry.SpanData) *tview.TreeView { scopes := tview.NewTreeNode("Scopes") for si := 0; si < rs.ScopeSpans().Len(); si++ { ss := rs.ScopeSpans().At(si) - scope := tview.NewTreeNode(fmt.Sprintf("Scope %d", si)) + scope := tview.NewTreeNode(ss.Scope().Name()) sschema := tview.NewTreeNode(fmt.Sprintf("schema url: %s", ss.SchemaUrl())) scope.AddChild(sschema) - isc := tview.NewTreeNode("Instrumentation Scope") - isc.AddChild(tview.NewTreeNode(fmt.Sprintf("name: %s", ss.Scope().Name()))) - isc.AddChild(tview.NewTreeNode(fmt.Sprintf("version: %s", ss.Scope().Version()))) - isc.AddChild(tview.NewTreeNode(fmt.Sprintf("dropped attributes count: %d", ss.Scope().DroppedAttributesCount()))) + scope.AddChild(tview.NewTreeNode(fmt.Sprintf("version: %s", ss.Scope().Version()))) + scope.AddChild(tview.NewTreeNode(fmt.Sprintf("dropped attributes count: %d", ss.Scope().DroppedAttributesCount()))) attrs := tview.NewTreeNode("Attributes") appendAttrsSorted(attrs, ss.Scope().Attributes().AsRaw()) - isc.AddChild(attrs) + scope.AddChild(attrs) scopes.AddChild(scope) } diff --git a/tuiexporter/internal/tui/component/trace_test.go b/tuiexporter/internal/tui/component/trace_test.go index 9aa95f4..a5f52d8 100644 --- a/tuiexporter/internal/tui/component/trace_test.go +++ b/tuiexporter/internal/tui/component/trace_test.go @@ -137,7 +137,7 @@ func TestGetTraceInfoTree(t *testing.T) { ResourceSpan: testdata.RSpans[1], ScopeSpans: testdata.SSpans[2], }) - sw, sh := 55, 15 + sw, sh := 55, 20 screen := tcell.NewSimulationScreen("") screen.Init() screen.SetSize(sw, sh) @@ -172,10 +172,15 @@ func TestGetTraceInfoTree(t *testing.T) { │ ├──resource index: %!s(int64=0) │ └──service.name: test-service-1 └──Scopes - ├──Scope 0 - │ └──schema url: - └──Scope 1 - └──schema url: + ├──test-scope-1-1 + │ ├──schema url: + │ ├──version: v0.0.1 + │ ├──dropped attributes count: 2 + │ └──Attributes + │ └──scope index: %!s(int64=0) + └──test-scope-1-2 + ├──schema url: + └──version: v0.0.1 ` assert.Equal(t, want, got.String()) }