view.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package tableview
  2. import (
  3. "fmt"
  4. "strings"
  5. "fbtop/internal/shared"
  6. "charm.land/lipgloss/v2"
  7. )
  8. var (
  9. headerStyle = lipgloss.NewStyle().Bold(true)
  10. selectedStyle = lipgloss.NewStyle().Reverse(true)
  11. )
  12. type Params struct {
  13. Comps []shared.ComponentMetrics
  14. PrevComps []shared.ComponentMetrics
  15. Width int
  16. Cursor int
  17. Humanize bool
  18. }
  19. func Render(p Params) string {
  20. prevMap := make(map[string]shared.ComponentMetrics, len(p.PrevComps))
  21. for _, c := range p.PrevComps {
  22. prevMap[c.ID] = c
  23. }
  24. var b strings.Builder
  25. b.WriteString(headerStyle.Render(fmt.Sprintf(" %-4s %-24s %-7s %10s %10s %s", "#", "Component", "Kind", "Rec/s", "Bytes/s", "Extra")))
  26. b.WriteString("\n")
  27. b.WriteString(strings.Repeat("─", p.Width))
  28. b.WriteString("\n")
  29. var lastKind shared.Kind = -1
  30. for i, c := range p.Comps {
  31. if c.Kind != lastKind {
  32. b.WriteString("\n")
  33. b.WriteString(headerStyle.Render(" " + sectionName(c.Kind)))
  34. b.WriteString("\n")
  35. lastKind = c.Kind
  36. }
  37. // Rates from delta
  38. recRate, byteRate := "-", "-"
  39. if prev, ok := prevMap[c.ID]; ok {
  40. dt := c.Stamp.Sub(prev.Stamp)
  41. if dt > 0 {
  42. recRate = shared.FormatRate(shared.Rate(prev.Records(), c.Records(), dt), p.Humanize, false)
  43. byteRate = shared.FormatRate(shared.Rate(prev.Bytes(), c.Bytes(), dt), p.Humanize, true)
  44. }
  45. }
  46. // Extra column
  47. extra := "-"
  48. switch c.Kind {
  49. case shared.KindOutput:
  50. var parts []string
  51. if e := c.Fields["errors"]; e > 0 {
  52. parts = append(parts, fmt.Sprintf("err:%d", e))
  53. }
  54. if r := c.Fields["retries"]; r > 0 {
  55. parts = append(parts, fmt.Sprintf("ret:%d", r))
  56. }
  57. if len(parts) > 0 {
  58. extra = strings.Join(parts, " ")
  59. }
  60. case shared.KindFilter:
  61. if d := c.Fields["drop_records"]; d > 0 {
  62. extra = fmt.Sprintf("drop:%d", d)
  63. }
  64. }
  65. row := fmt.Sprintf(" %-4d %-24s %-7s %10s %10s %s", i+1, c.ID, c.Kind, recRate, byteRate, extra)
  66. if i == p.Cursor {
  67. row = selectedStyle.Render(row)
  68. }
  69. b.WriteString(row)
  70. b.WriteString("\n")
  71. }
  72. return b.String()
  73. }
  74. func sectionName(k shared.Kind) string {
  75. switch k {
  76. case shared.KindInput:
  77. return "SOURCES"
  78. case shared.KindFilter:
  79. return "FILTERS"
  80. case shared.KindOutput:
  81. return "OUTPUTS"
  82. default:
  83. return "ALL"
  84. }
  85. }