diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 4ab445c..3b57ab4 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -14,7 +14,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.23.2' + go-version: '1.24.1' id: go - name: Check out code into the Go module directory diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f2d5378..d5c1952 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -15,7 +15,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v5 with: - go-version: '1.23.2' + go-version: '1.24.1' - name: Fetch vendor run: make vendor diff --git a/.golangci.json b/.golangci.json index d78449a..b977cac 100644 --- a/.golangci.json +++ b/.golangci.json @@ -1,43 +1,72 @@ { + "formatters": { + "enable": [ + "gofmt", + "gofumpt", + "goimports" + ], + "exclusions": { + "generated": "lax", + "paths": [ + "third_party$", + "builtin$", + "examples$" + ] + }, + "settings": { + "goimports": { + "local-prefixes": [ + "github.com/hedhyw/json-log-viewer/" + ] + } + } + }, "linters": { - "enable-all": true, + "default": "all", "disable": [ - "lll", - "gochecknoglobals", "bodyclose", - "wsl", - "funlen", - "gci", - "wrapcheck", - "varnamelen", - "testpackage", + "depguard", "exhaustive", - "gomnd", - "thelper", - "paralleltest", - "tagliatelle", - "nonamedreturns", "exhaustruct", - "nolintlint", - "wastedassign", - "rowserrcheck", - "depguard", - "ireturn", + "funlen", + "gochecknoglobals", "gomoddirectives", - "execinquery", - "tagalign", + "ireturn", + "lll", "mnd", "nlreturn", - "exportloopref" - ] - }, - "linters-settings": { - "goimports": { - "local-prefixes": "github.com/hedhyw/json-log-viewer/" - }, - "cyclop": { - "max-complexity": 15 + "nolintlint", + "nonamedreturns", + "paralleltest", + "rowserrcheck", + "tagalign", + "tagliatelle", + "testpackage", + "thelper", + "varnamelen", + "wastedassign", + "wrapcheck", + "wsl" + ], + "exclusions": { + "generated": "lax", + "paths": [ + "third_party$", + "builtin$", + "examples$" + ], + "presets": [ + "comments", + "common-false-positives", + "legacy", + "std-error-handling" + ] }, - "revive": {} - } -} \ No newline at end of file + "settings": { + "cyclop": { + "max-complexity": 15 + } + } + }, + "version": "2" +} diff --git a/Makefile b/Makefile index e2add41..3fedf2c 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -GOLANG_CI_LINT_VER:=v1.61.0 +GOLANG_CI_LINT_VER:=v2.0.2 GORELEASER_VERSION:=v2.3.2 OUT_BIN?=${PWD}/bin/jlv COVER_PACKAGES=./... diff --git a/assets/example.log b/assets/example.log index caf68f3..8a2eb61 100644 --- a/assets/example.log +++ b/assets/example.log @@ -52,4 +52,5 @@ plain text log {"time":865900800,"level":"TRACE","message": "Money doesn't talk, it swears","author": "Bob Dylan"} {"time":883612800.45,"level":"WARN","message": "If a man knows not to which port he sails, no wind is favorable","author": "Seneca"} {"time":"915148800000.45","level":"VERBOSE","message": "Begin at once to live, and count each separate day as a separate life","author": "Seneca"} -{"time":946684800.45,"level":"VERBOSE","message": "Begin at once to live, and count each separate day as a separate life","author": "Seneca"} \ No newline at end of file +{"time":946684800.45,"level":"VERBOSE","message": "Begin at once to live, and count each separate day as a separate life","author": "Seneca"} +{"@timestamp":"2025-03-06T11:55:53.723682+01:00","@version":1,"host":"bad21ee895cd","message":"Message ..","level":"INFO"} diff --git a/example.jlv.jsonc b/example.jlv.jsonc index 8599b51..8c9786a 100644 --- a/example.jlv.jsonc +++ b/example.jlv.jsonc @@ -18,7 +18,8 @@ "$.timestamp", "$.time", "$.t", - "$.ts" + "$.ts", + "$[\"@timestamp\"]" ], "width": 30, // Year: "2006" "06" diff --git a/internal/app/app_test.go b/internal/app/app_test.go index 2326704..ab99dea 100644 --- a/internal/app/app_test.go +++ b/internal/app/app_test.go @@ -102,6 +102,6 @@ func requireCmdMsg(tb testing.TB, expected tea.Msg, cmd tea.Cmd) { } func getTestError() error { - // nolint: goerr113 // It is a test. + // nolint: err113 // It is a test. return errors.New("error description") } diff --git a/internal/app/lazytable.go b/internal/app/lazytable.go index 2d3c9c4..65b8b4a 100644 --- a/internal/app/lazytable.go +++ b/internal/app/lazytable.go @@ -80,7 +80,7 @@ func (m lazyTableModel) getCellRenderer() func(table.Model, string, table.CellPo if position.Column == cellIDLogLevel { return removeClearSequence( - m.Application.getLogLevelStyle( + m.getLogLevelStyle( m.renderedRows, style, position.RowID, @@ -94,7 +94,7 @@ func (m lazyTableModel) getCellRenderer() func(table.Model, string, table.CellPo func (m lazyTableModel) handleKey(msg tea.KeyMsg, render bool) (lazyTableModel, bool) { // toggle the reverse display of items. - if key.Matches(msg, m.Application.keys.Reverse) { + if key.Matches(msg, m.keys.Reverse) { m.reverse = !m.reverse render = true } @@ -128,21 +128,21 @@ func (m lazyTableModel) handleKey(msg tea.KeyMsg, render bool) (lazyTableModel, increaseOffset, decreaseOffset = decreaseOffset, increaseOffset } - if key.Matches(msg, m.Application.keys.Down) { + if key.Matches(msg, m.keys.Down) { m.follow = false if m.table.Cursor()+1 == m.table.Height() { increaseOffset() // move the viewport } } - if key.Matches(msg, m.Application.keys.Up) { + if key.Matches(msg, m.keys.Up) { m.follow = false if m.table.Cursor() == 0 { decreaseOffset() // move the viewport } } - if key.Matches(msg, m.Application.keys.GotoTop) { + if key.Matches(msg, m.keys.GotoTop) { if m.reverse { // when follow is enabled, rendering will handle setting the offset to the correct value m.follow = true @@ -153,7 +153,7 @@ func (m lazyTableModel) handleKey(msg tea.KeyMsg, render bool) (lazyTableModel, render = true } - if key.Matches(msg, m.Application.keys.GotoBottom) { + if key.Matches(msg, m.keys.GotoBottom) { if m.reverse { m.follow = false m.offset = 0 diff --git a/internal/app/statefiltered.go b/internal/app/statefiltered.go index efbac3e..087a52e 100644 --- a/internal/app/statefiltered.go +++ b/internal/app/statefiltered.go @@ -43,7 +43,7 @@ func (s StateFilteredModel) Init() tea.Cmd { // View renders component. It implements tea.Model. func (s StateFilteredModel) View() string { - footer := s.Application.FooterStyle.Render( + footer := s.FooterStyle.Render( fmt.Sprintf("filtered %d by: %s", s.logEntries.Len(), s.filterText), ) @@ -128,7 +128,7 @@ func (s StateFilteredModel) getApplication() *Application { } func (s StateFilteredModel) refresh() (_ stateModel, cmd tea.Cmd) { - s.table, cmd = s.table.Update(s.Application.LastWindowSize()) + s.table, cmd = s.table.Update(s.LastWindowSize()) return s, cmd } diff --git a/internal/app/stateloaded.go b/internal/app/stateloaded.go index 664c9be..46b8586 100644 --- a/internal/app/stateloaded.go +++ b/internal/app/stateloaded.go @@ -82,7 +82,7 @@ func (s StateLoadedModel) viewHelp() string { Padding(0, 1). Render(s.Version) - width := s.Application.LastWindowSize().Width + width := s.LastWindowSize().Width fillerText := lipgloss.NewStyle(). Background(lipgloss.Color("#353533")). Width(width - lipgloss.Width(toggleText) - lipgloss.Width(versionText)). @@ -160,8 +160,8 @@ func (s StateLoadedModel) getApplication() *Application { func (s StateLoadedModel) refresh() (_ stateModel, cmd tea.Cmd) { var cmdFirst, cmdSecond tea.Cmd - s.table, cmdSecond = s.table.Update(s.Application.LastWindowSize()) - s.table, cmdFirst = s.table.Update(events.LogEntriesUpdateMsg(s.Application.Entries())) + s.table, cmdSecond = s.table.Update(s.LastWindowSize()) + s.table, cmdFirst = s.table.Update(events.LogEntriesUpdateMsg(s.Entries())) return s, tea.Batch(cmdFirst, cmdSecond) } diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go index 6360386..ee725f6 100644 --- a/internal/pkg/config/config.go +++ b/internal/pkg/config/config.go @@ -68,7 +68,7 @@ func GetDefaultConfig() *Config { Fields: []Field{{ Title: "Time", Kind: FieldKindNumericTime, - References: []string{"$.timestamp", "$.time", "$.t", "$.ts"}, + References: []string{"$.timestamp", "$.time", "$.t", "$.ts", "$[\"@timestamp\"]"}, Width: 30, TimeFormat: &defaultTimeFormat, }, { diff --git a/internal/pkg/config/config_test.go b/internal/pkg/config/config_test.go index 78decea..9cf2466 100644 --- a/internal/pkg/config/config_test.go +++ b/internal/pkg/config/config_test.go @@ -110,7 +110,8 @@ func ExampleGetDefaultConfig() { // "$.timestamp", // "$.time", // "$.t", - // "$.ts" + // "$.ts", + // "$[\"@timestamp\"]" // ], // "width": 30, // "time_format": "2006-01-02T15:04:05Z07:00" diff --git a/internal/pkg/source/entry_test.go b/internal/pkg/source/entry_test.go index f20b942..20e1675 100644 --- a/internal/pkg/source/entry_test.go +++ b/internal/pkg/source/entry_test.go @@ -722,7 +722,7 @@ func getTimestampFormattingConfig(fieldKind config.FieldKind, format string) *co cfg.Fields = []config.Field{{ Title: "Time", Kind: fieldKind, - References: []string{"$.timestamp", "$.time", "$.t", "$.ts"}, + References: []string{"$.timestamp", "$.time", "$.t", "$.ts", "$[\"@timestamp\"]"}, Width: 30, TimeFormat: timeFormat, }} diff --git a/internal/pkg/tests/tests.go b/internal/pkg/tests/tests.go index 0008340..2251e4c 100644 --- a/internal/pkg/tests/tests.go +++ b/internal/pkg/tests/tests.go @@ -20,7 +20,7 @@ const ErrTest semerr.Error = "test error" func RequireCreateFile(tb testing.TB, content []byte) string { tb.Helper() - f, err := os.CreateTemp("", "json_log_viewer_test") + f, err := os.CreateTemp(tb.TempDir(), "json_log_viewer_test") require.NoError(tb, err) defer func() { assert.NoError(tb, f.Close()) }()