feat: style changes and event reworks.
Going to work on process restart so I can test those messages.
This commit is contained in:
parent
b43cab8b0a
commit
adcee5f69e
@ -65,7 +65,7 @@ func proxyHandler(ch chan<- model.Event) http.Handler {
|
|||||||
ch <- model.Event{
|
ch <- model.Event{
|
||||||
Time: time.Now().Local(),
|
Time: time.Now().Local(),
|
||||||
Type: model.EventTypeWarn,
|
Type: model.EventTypeWarn,
|
||||||
Body: fmt.Sprintf("(%s) failed to read request body", request.ID),
|
Body: fmt.Sprintf("(%s) failed to read request body: %v", getEndOfUUID(request.ID), err),
|
||||||
Request: request,
|
Request: request,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -86,7 +86,7 @@ func proxyHandler(ch chan<- model.Event) http.Handler {
|
|||||||
ch <- model.Event{
|
ch <- model.Event{
|
||||||
Time: time.Now().Local(),
|
Time: time.Now().Local(),
|
||||||
Type: model.EventTypeRequestStarted,
|
Type: model.EventTypeRequestStarted,
|
||||||
Body: fmt.Sprintf("-> %+v", request),
|
Body: fmt.Sprintf("(%s) %s %s", getEndOfUUID(request.ID), request.Method, request.RawURL),
|
||||||
Request: request,
|
Request: request,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ func proxyHandler(ch chan<- model.Event) http.Handler {
|
|||||||
ch <- model.Event{
|
ch <- model.Event{
|
||||||
Time: time.Now().Local(),
|
Time: time.Now().Local(),
|
||||||
Type: model.EventTypeRequestFailed,
|
Type: model.EventTypeRequestFailed,
|
||||||
Body: fmt.Sprintf("upstream error for %s %s: %v", outReq.Method, outReq.URL.String(), err),
|
Body: fmt.Sprintf("(%s) upstream error: %v", getEndOfUUID(request.ID), err),
|
||||||
Request: request,
|
Request: request,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -115,7 +115,7 @@ func proxyHandler(ch chan<- model.Event) http.Handler {
|
|||||||
ch <- model.Event{
|
ch <- model.Event{
|
||||||
Time: time.Now().Local(),
|
Time: time.Now().Local(),
|
||||||
Type: model.EventTypeWarn,
|
Type: model.EventTypeWarn,
|
||||||
Body: fmt.Sprintf("(%s) failed to read response body", request.ID),
|
Body: fmt.Sprintf("(%s) failed to read response body: %v", getEndOfUUID(request.ID), err),
|
||||||
Request: request,
|
Request: request,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -133,7 +133,7 @@ func proxyHandler(ch chan<- model.Event) http.Handler {
|
|||||||
ch <- model.Event{
|
ch <- model.Event{
|
||||||
Time: time.Now().Local(),
|
Time: time.Now().Local(),
|
||||||
Type: model.EventTypeRequestFailed,
|
Type: model.EventTypeRequestFailed,
|
||||||
Body: fmt.Sprintf("write response body %s %s: %v", outReq.Method, outReq.URL.String(), err),
|
Body: fmt.Sprintf("(%s) failed to write response body: %v", getEndOfUUID(request.ID), err),
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ func proxyHandler(ch chan<- model.Event) http.Handler {
|
|||||||
ch <- model.Event{
|
ch <- model.Event{
|
||||||
Time: time.Now().Local(),
|
Time: time.Now().Local(),
|
||||||
Type: model.EventTypeRequestFinished,
|
Type: model.EventTypeRequestFinished,
|
||||||
Body: fmt.Sprintf("<- %+v %s", request, formatHeaders(resp.Request.Header)),
|
Body: fmt.Sprintf("(%s) %s %s %d %dms", getEndOfUUID(request.ID), request.Method, request.RawURL, request.Status, request.Duration.Milliseconds()),
|
||||||
Request: request,
|
Request: request,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -199,6 +199,10 @@ func formatHeaders(headers http.Header) string {
|
|||||||
return strings.Join(parts, ", ")
|
return strings.Join(parts, ", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getEndOfUUID(id uuid.UUID) string {
|
||||||
|
return id.String()[24:]
|
||||||
|
}
|
||||||
|
|
||||||
// BUG: Not sure if this actually works, seems to favor the 502
|
// BUG: Not sure if this actually works, seems to favor the 502
|
||||||
func statusFromUpstreamError(req *http.Request, resp *http.Response, err error) int {
|
func statusFromUpstreamError(req *http.Request, resp *http.Response, err error) int {
|
||||||
if resp != nil {
|
if resp != nil {
|
||||||
|
|||||||
@ -23,7 +23,7 @@ func (m Model) renderStatusBar(w int) string {
|
|||||||
|
|
||||||
avg := int(msSum) / max(1, len(m.requests))
|
avg := int(msSum) / max(1, len(m.requests))
|
||||||
left := fmt.Sprintf(" tap %3d reqs | %d err | avg %dms", len(m.requests), errCount, avg)
|
left := fmt.Sprintf(" tap %3d reqs | %d err | avg %dms", len(m.requests), errCount, avg)
|
||||||
right := "j/k nav / search tab panel e events o output r replay q quit "
|
right := "j/k nav / search tab panel e events o output r replay ctrl+r restart q quit "
|
||||||
|
|
||||||
spaceSize := max(w-(len(left)+len(right)), 0)
|
spaceSize := max(w-(len(left)+len(right)), 0)
|
||||||
space := strings.Repeat(" ", spaceSize)
|
space := strings.Repeat(" ", spaceSize)
|
||||||
@ -31,6 +31,7 @@ func (m Model) renderStatusBar(w int) string {
|
|||||||
return m.theme.Header.Render(left + space + right)
|
return m.theme.Header.Render(left + space + right)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Implement
|
||||||
func (m Model) renderSearchPane(w, h int) []string {
|
func (m Model) renderSearchPane(w, h int) []string {
|
||||||
lines := make([]string, h)
|
lines := make([]string, h)
|
||||||
for y := range lines {
|
for y := range lines {
|
||||||
@ -91,6 +92,7 @@ func (m Model) renderRequestPane(w, h int) []string {
|
|||||||
return lines
|
return lines
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Implement
|
||||||
func (m Model) renderDetailsPane(w, h int) []string {
|
func (m Model) renderDetailsPane(w, h int) []string {
|
||||||
lines := make([]string, h)
|
lines := make([]string, h)
|
||||||
for y := range lines {
|
for y := range lines {
|
||||||
@ -123,22 +125,33 @@ func (m Model) renderEventsPane(w, h int) []string {
|
|||||||
lines := []string{status}
|
lines := []string{status}
|
||||||
|
|
||||||
for _, event := range events {
|
for _, event := range events {
|
||||||
line := fmt.Sprintf(
|
var (
|
||||||
"%s %-15s %s",
|
eTime string = m.theme.TextMuted.Render(event.Time.Format("15:04:05") + " ")
|
||||||
event.Time.Format("15:04:05"),
|
eType string = getEventColor(m.theme, event.Type).Render(fmt.Sprintf("%-15s ", event.Type))
|
||||||
event.Type,
|
|
||||||
event.Body,
|
avail int = max(0, w-lipgloss.Width(eTime+eType))
|
||||||
|
body string = clampRendered(m.theme.Text.Render(event.Body), avail)
|
||||||
)
|
)
|
||||||
if event.PID > 0 {
|
|
||||||
line = fmt.Sprintf(
|
if event.Type == model.EventTypeRequestFailed || event.Type == model.EventTypeFatal {
|
||||||
"%s %-15s %d %s",
|
body = clampRendered(m.theme.TextError.Render(event.Body), avail)
|
||||||
event.Time.Format("15:04:05"),
|
eTime = m.theme.TextMutedError.Render(event.Time.Format("15:04:05") + " ")
|
||||||
event.Type,
|
|
||||||
event.PID,
|
|
||||||
event.Body,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
lines = append(lines, truncate(line, w))
|
|
||||||
|
line := eTime + eType + body
|
||||||
|
if event.PID > 0 {
|
||||||
|
pid := m.theme.TextMuted.Render(fmt.Sprintf("%d ", event.PID))
|
||||||
|
|
||||||
|
avail = max(0, w-lipgloss.Width(eTime+eType+pid))
|
||||||
|
body = clampRendered(m.theme.Text.Render(event.Body), avail)
|
||||||
|
line = eTime + eType + pid + body
|
||||||
|
}
|
||||||
|
|
||||||
|
if event.Type == model.EventTypeRequestFailed || event.Type == model.EventTypeFatal {
|
||||||
|
line += m.theme.TextError.Render(strings.Repeat(" ", w-lipgloss.Width(line)))
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = append(lines, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package tui
|
|||||||
import (
|
import (
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
"github.com/charmbracelet/x/ansi"
|
"github.com/charmbracelet/x/ansi"
|
||||||
|
"termtap.dev/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Theme struct {
|
type Theme struct {
|
||||||
@ -17,10 +18,15 @@ type Theme struct {
|
|||||||
TextError lipgloss.Style
|
TextError lipgloss.Style
|
||||||
TextMutedError lipgloss.Style
|
TextMutedError lipgloss.Style
|
||||||
|
|
||||||
EventGreen lipgloss.Style
|
EventDefault lipgloss.Style
|
||||||
EventRed lipgloss.Style
|
EventSession lipgloss.Style
|
||||||
EventBlue lipgloss.Style
|
EventProcess lipgloss.Style
|
||||||
EventOrange lipgloss.Style
|
EventProxy lipgloss.Style
|
||||||
|
EventRequestInFlight lipgloss.Style
|
||||||
|
EventSuccess lipgloss.Style
|
||||||
|
EventWarn lipgloss.Style
|
||||||
|
EventError lipgloss.Style
|
||||||
|
EventFatal lipgloss.Style
|
||||||
}
|
}
|
||||||
|
|
||||||
const background = lipgloss.Color("#010e1f")
|
const background = lipgloss.Color("#010e1f")
|
||||||
@ -29,8 +35,11 @@ const text = lipgloss.Color("#dfe5ed")
|
|||||||
const textMuted = lipgloss.Color("#7c7e80")
|
const textMuted = lipgloss.Color("#7c7e80")
|
||||||
|
|
||||||
const blue = lipgloss.Color("#2280f2")
|
const blue = lipgloss.Color("#2280f2")
|
||||||
|
const cyan = lipgloss.Color("#22b8f2")
|
||||||
|
const violetBlue = lipgloss.Color("#6f7dff")
|
||||||
const orange = lipgloss.Color("#f2a813")
|
const orange = lipgloss.Color("#f2a813")
|
||||||
const red = lipgloss.Color("#e6130b")
|
const red = lipgloss.Color("#e6130b")
|
||||||
|
const fatalRed = lipgloss.Color("#ff4d4d")
|
||||||
const green = lipgloss.Color("#10e31e")
|
const green = lipgloss.Color("#10e31e")
|
||||||
|
|
||||||
func newTheme() Theme {
|
func newTheme() Theme {
|
||||||
@ -64,18 +73,42 @@ func newTheme() Theme {
|
|||||||
Foreground(textMuted).
|
Foreground(textMuted).
|
||||||
Background(backgroundError),
|
Background(backgroundError),
|
||||||
|
|
||||||
EventGreen: lipgloss.NewStyle().
|
EventDefault: lipgloss.NewStyle().
|
||||||
Foreground(green).
|
Foreground(text).
|
||||||
Background(background),
|
Background(background).
|
||||||
EventBlue: lipgloss.NewStyle().
|
Bold(true),
|
||||||
|
EventSession: lipgloss.NewStyle().
|
||||||
|
Foreground(textMuted).
|
||||||
|
Background(background).
|
||||||
|
Bold(true),
|
||||||
|
EventProcess: lipgloss.NewStyle().
|
||||||
Foreground(blue).
|
Foreground(blue).
|
||||||
Background(background),
|
Background(background).
|
||||||
EventRed: lipgloss.NewStyle().
|
Bold(true),
|
||||||
Foreground(red).
|
EventProxy: lipgloss.NewStyle().
|
||||||
Background(backgroundError),
|
Foreground(violetBlue).
|
||||||
EventOrange: lipgloss.NewStyle().
|
Background(background).
|
||||||
|
Bold(true),
|
||||||
|
EventRequestInFlight: lipgloss.NewStyle().
|
||||||
|
Foreground(cyan).
|
||||||
|
Background(background).
|
||||||
|
Bold(true),
|
||||||
|
EventSuccess: lipgloss.NewStyle().
|
||||||
|
Foreground(green).
|
||||||
|
Background(background).
|
||||||
|
Bold(true),
|
||||||
|
EventWarn: lipgloss.NewStyle().
|
||||||
Foreground(orange).
|
Foreground(orange).
|
||||||
Background(background),
|
Background(background).
|
||||||
|
Bold(true),
|
||||||
|
EventError: lipgloss.NewStyle().
|
||||||
|
Foreground(red).
|
||||||
|
Background(backgroundError).
|
||||||
|
Bold(true),
|
||||||
|
EventFatal: lipgloss.NewStyle().
|
||||||
|
Foreground(fatalRed).
|
||||||
|
Background(backgroundError).
|
||||||
|
Bold(true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,3 +121,42 @@ func clampRendered(s string, maxCols int) string {
|
|||||||
}
|
}
|
||||||
return ansi.Truncate(s, maxCols, "...")
|
return ansi.Truncate(s, maxCols, "...")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getEventColor(theme Theme, event model.EventType) lipgloss.Style {
|
||||||
|
switch event {
|
||||||
|
case model.EventTypeSessionStarted,
|
||||||
|
model.EventTypeSessionStopped:
|
||||||
|
return theme.EventSession
|
||||||
|
|
||||||
|
case model.EventTypeProxyStarted,
|
||||||
|
model.EventTypeProxyStarting,
|
||||||
|
model.EventTypeProxyStopped:
|
||||||
|
return theme.EventProxy
|
||||||
|
|
||||||
|
case model.EventTypeRequestStarted:
|
||||||
|
return theme.EventRequestInFlight
|
||||||
|
|
||||||
|
case model.EventTypeRequestFinished:
|
||||||
|
return theme.EventSuccess
|
||||||
|
|
||||||
|
case model.EventTypeFatal:
|
||||||
|
return theme.EventFatal
|
||||||
|
|
||||||
|
case model.EventTypeRequestFailed:
|
||||||
|
return theme.EventError
|
||||||
|
|
||||||
|
case model.EventTypeProcessStarting,
|
||||||
|
model.EventTypeProcessStarted,
|
||||||
|
model.EventTypeProcessExited,
|
||||||
|
model.EventTypeProcessSignaled,
|
||||||
|
model.EventTypeProcessStdout,
|
||||||
|
model.EventTypeProcessStderr:
|
||||||
|
return theme.EventProcess
|
||||||
|
|
||||||
|
case model.EventTypeWarn:
|
||||||
|
return theme.EventWarn
|
||||||
|
|
||||||
|
default:
|
||||||
|
return theme.EventDefault
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user