ssm-browse: added structed log view

This commit is contained in:
Leon Mika 2022-03-30 15:07:49 +11:00
parent 9752bb41bc
commit b3d0fbfe29
11 changed files with 546 additions and 0 deletions

View file

@ -0,0 +1,5 @@
package loglines
import "github.com/lmika/awstools/internal/slog-view/models"
type NewLogLineSelected *models.LogLine

View file

@ -0,0 +1,98 @@
package loglines
import (
table "github.com/calyptia/go-bubble-table"
tea "github.com/charmbracelet/bubbletea"
"github.com/charmbracelet/lipgloss"
"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/frame"
"github.com/lmika/awstools/internal/dynamo-browse/ui/teamodels/layout"
"github.com/lmika/awstools/internal/slog-view/models"
"path/filepath"
)
type Model struct {
frameTitle frame.FrameTitle
table table.Model
logFile *models.LogFile
w, h int
}
func New() *Model {
frameTitle := frame.NewFrameTitle("File: ", true)
table := table.New([]string{"level", "error", "message"}, 0, 0)
return &Model{
frameTitle: frameTitle,
table: table,
}
}
func (m *Model) SetLogFile(newLogFile *models.LogFile) {
m.logFile = newLogFile
m.frameTitle.SetTitle("File: " + filepath.Base(newLogFile.Filename))
cols := []string{"level", "error", "message"}
newTbl := table.New(cols, m.w, m.h-m.frameTitle.HeaderHeight())
newRows := make([]table.Row, len(newLogFile.Lines))
for i, r := range newLogFile.Lines {
newRows[i] = itemTableRow{r}
}
newTbl.SetRows(newRows)
m.table = newTbl
}
func (m *Model) Init() tea.Cmd {
return nil
}
func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
//var cmd tea.Cmd
switch msg := msg.(type) {
case tea.KeyMsg:
switch msg.String() {
case "i", "up":
m.table.GoUp()
return m, m.emitNewSelectedParameter()
case "k", "down":
m.table.GoDown()
return m, m.emitNewSelectedParameter()
}
//m.table, cmd = m.table.Update(msg)
//return m, cmd
}
return m, nil
}
func (m *Model) SelectedLogLine() *models.LogLine {
if row, ok := m.table.SelectedRow().(itemTableRow); ok {
return &(row.item)
}
return nil
}
func (m *Model) emitNewSelectedParameter() tea.Cmd {
return func() tea.Msg {
selectedLogLine := m.SelectedLogLine()
if selectedLogLine != nil {
return NewLogLineSelected(selectedLogLine)
}
return nil
}
}
func (m *Model) View() string {
return lipgloss.JoinVertical(lipgloss.Top, m.frameTitle.View(), m.table.View())
}
func (m *Model) Resize(w, h int) layout.ResizingModel {
m.w, m.h = w, h
m.frameTitle.Resize(w, h)
m.table.SetSize(w, h - m.frameTitle.HeaderHeight())
return m
}

View file

@ -0,0 +1,61 @@
package loglines
import (
"fmt"
table "github.com/calyptia/go-bubble-table"
"github.com/lmika/awstools/internal/slog-view/models"
"io"
"strings"
)
type itemTableRow struct {
item models.LogLine
}
func (mtr itemTableRow) Render(w io.Writer, model table.Model, index int) {
// TODO: these cols are fixed, they should be dynamic
level := mtr.renderFirstLineOfField(mtr.item.JSON, "level")
err := mtr.renderFirstLineOfField(mtr.item.JSON, "error")
msg := mtr.renderFirstLineOfField(mtr.item.JSON, "message")
line := fmt.Sprintf("%s\t%s\t%s", level, err, msg)
if index == model.Cursor() {
fmt.Fprintln(w, model.Styles.SelectedRow.Render(line))
} else {
fmt.Fprintln(w, line)
}
}
// TODO: this needs to be some form of path expression
func (mtr itemTableRow) renderFirstLineOfField(d interface{}, field string) string {
switch k := d.(type) {
case map[string]interface{}:
return mtr.renderFirstLineOfValue(k[field])
default:
return mtr.renderFirstLineOfValue(k)
}
}
func (mtr itemTableRow) renderFirstLineOfValue(v interface{}) string {
if v == nil {
return ""
}
switch k := v.(type) {
case string:
firstLine := strings.SplitN(k, "\n", 2)[0]
return firstLine
case int:
return fmt.Sprint(k)
case float64:
return fmt.Sprint(k)
case bool:
return fmt.Sprint(k)
case map[string]interface{}:
return "{}"
case []interface{}:
return "[]"
default:
return "(other)"
}
}