Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
version: 2

updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "monthly"
commit-message:
prefix: "chore(gha)"
pull-request-branch-name:
separator: "/"

- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "monthly"
commit-message:
prefix: "chore(gomod)"
pull-request-branch-name:
separator: "/"
34 changes: 34 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: check-json-log-viewer

on:
push:
branches:
- main
pull_request:

jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.20.6'
id: go

- name: Check out code into the Go module directory
uses: actions/checkout@v3

- name: Build
run: make build

- name: Lint
run: make lint

- name: Test
run: make test

- uses: shogo82148/actions-goveralls@v1
with:
path-to-profile: coverage.out
26 changes: 26 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: release-json-log-viewer

on:
push:
tags:
- "*"

jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: '1.20.6'

- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v4
with:
version: latest
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GH_PAT }}
14 changes: 14 additions & 0 deletions .github/workflows/semantic.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: check-pr-semantic

on:
pull_request:
types: [opened, synchronize, reopened]

jobs:
main:
name: Validate PR title
runs-on: ubuntu-latest
steps:
- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
19 changes: 19 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
bin

# IDE
.vscode

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
vendor/
45 changes: 45 additions & 0 deletions .golangci.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"linters": {
"enable-all": true,
"disable": [
"lll",
"gochecknoglobals",
"bodyclose",
"wsl",
"funlen",
"maligned",
"exhaustivestruct",
"gci",
"wrapcheck",
"varnamelen",
"testpackage",
"exhaustive",
"gomnd",
"thelper",
"paralleltest",
"tagliatelle",
"scopelint",
"golint",
"interfacer",
"nonamedreturns",
"exhaustruct",
"nolintlint",
"deadcode",
"wastedassign",
"structcheck",
"varcheck",
"ifshort",
"nosnakecase",
"rowserrcheck",
"depguard",
"ireturn",
"gomoddirectives"
]
},
"linters-settings": {
"goimports": {
"local-prefixes": "github.com/hedhyw/json-log-viewer/"
},
"revive": {}
}
}
45 changes: 45 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
GOLANG_CI_LINT_VER:=v1.53.3
OUT_BIN?=${PWD}/bin/jlv
COVER_PACKAGES=./...
VERSION?=${shell git describe --tags}

run:
@echo "building ${VERSION}"
go run ./cmd/jlv assets/example.log
.PHONY: build

build:
@echo "building ${VERSION}"
go build \
-o ${OUT_BIN} \
--ldflags "-s -w -X main.version=${VERSION}" \
./cmd/jlv
.PHONY: build

install:
go install ./cmd/jlv
.PHONY: install

lint: bin/golangci-lint
./bin/golangci-lint run
.PHONY: lint

test:
go test \
-coverpkg=${COVER_PACKAGES} \
-covermode=count \
-coverprofile=coverage.out \
./...
go tool cover -func=coverage.out
.PHONY: test

vendor:
go mod tidy
go mod vendor
.PHONY: vendor

bin/golangci-lint:
curl \
-sSfL \
https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh \
| sh -s $(GOLANG_CI_LINT_VER)
101 changes: 101 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# JSON Log Viewer

![Version](https://img.shields.io/github/v/tag/hedhyw/json-log-viewer)
![Build Status](https://github.com/hedhyw/json-log-viewer/actions/workflows/check.yml/badge.svg)
[![Go Report Card](https://goreportcard.com/badge/github.com/hedhyw/json-log-viewer)](https://goreportcard.com/report/github.com/hedhyw/json-log-viewer)
[![Coverage Status](https://coveralls.io/repos/github/hedhyw/json-log-viewer/badge.svg?branch=main)](https://coveralls.io/github/hedhyw/json-log-viewer?branch=main)

It is an interactive tool for viewing and analyzing complex log files with structured JSON logs.

![Animation](./assets/animation.webp)

Main features:
1. It is interactive.
2. Is shows similified log records.
3. It is possible to see the full prettified JSON after clicking.
4. It includes non-JSON logs as they are.
5. It understands different field names.
6. It supports case-insensitive filtering.
7. It is simple.

It uses [antonmedv/fx](https://github.com/antonmedv/fx) for viewing JSON and [charmbracelet/bubbletea](https://github.com/charmbracelet/bubbletea) for terminal UI. The tool is inspired by the project [json-log-viewer](https://github.com/gistia/json-log-viewer) which is unfortunately outdated.

## Table of content

- [JSON Log Viewer](#json-log-viewer)
- [Table of content](#table-of-content)
- [Usage](#usage)
- [Install](#install)
- [MacOS/Linux HomeBrew](#macoslinux-homebrew)
- [Go](#go)
- [Package](#package)
- [Standalone Binary](#standalone-binary)
- [Source](#source)
- [Roadmap](#roadmap)
- [Resources](#resources)
- [License](#license)


## Usage

```sh
jlv file.json
```

| Key | Action |
| ------ | -------------- |
| Enter | Open/Close log |
| F | Filter |
| Ctrl+C | Exit |
| Esc | Back |
| ↑↓ | Navigation |

## Install

### MacOS/Linux HomeBrew

```sh
brew install hedhyw/main/json-log-viewer
```

### Go

```bash
go install github.com/hedhyw/json-log-viewer/cmd/jlv@latest
```

### Package

Latest DEB and RPM packages are available on [the releases page](https://github.com/hedhyw/json-log-viewer/releases/latest).

### Standalone Binary

Download latest archive `*.tar.gz` for your target platform from [the releases page](https://github.com/hedhyw/json-log-viewer/releases/latest) and extract it to `/usr/local/bin/jlv`. Add this path to `PATH` environment.

### Source

```
git clone git@github.com:hedhyw/json-log-viewer.git
cd json-log-viewer
make build
cp ./bin/jlv /usr/local/bin
chmod +x /usr/local/bin/jlv
```

## Roadmap

- Accept stream of logs.
- Add colors to log levels.
- Add a configuration file (similar to `.json-log-viewer`).
- Convert number timestamps.

## Resources

Alternatives:
- [mightyguava/jl](https://github.com/mightyguava/jl) - Pretty Viewer for JSON logs.
- [pamburus/hl](https://github.com/pamburus/hl) - A log viewer that translates JSON logs into human-readable representation.
- [json-log-viewer](https://github.com/gistia/json-log-viewer) - Powerful terminal based viewer for JSON logs using ncurses.

## License

[MIT License](LICENSE).
Binary file added assets/animation.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions assets/assets.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package assets

import (
_ "embed"
)

//go:embed example.log
var exampleJSONLog []byte

// ExampleJSONLog returns a copy of the file "example.log".
func ExampleJSONLog() []byte {
target := make([]byte, len(exampleJSONLog))

copy(target, exampleJSONLog)

return target
}
18 changes: 18 additions & 0 deletions assets/assets_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package assets_test

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/hedhyw/json-log-viewer/assets"
)

func TestExampleJSONLog(t *testing.T) {
t.Parallel()

content := assets.ExampleJSONLog()
if assert.NotEmpty(t, content) {
assert.Contains(t, string(content), "{")
}
}
46 changes: 46 additions & 0 deletions assets/example.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{"time":1,"level":"INFO","msg": "Nothing happens unless first we dream.","author": "Carl Sandburg"}
{"timestamp":2,"level":"INFO","message": "Well begun is half done.","author": "Aristotle"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Life is a learning experience, only if you learn.","author": "Yogi Berra"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Self-complacency is fatal to progress.","author": "Margaret Sangster"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Peace comes from within. Do not seek it without.","author": "Buddha"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "What you give is what you get.","author": "Byron Pulsifer"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "We can only learn to love by loving.","author": "Iris Murdoch"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Life is change. Growth is optional. Choose wisely.","author": "Karen Clark"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "You'll see it when you believe it.","author": "Wayne Dyer"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Today is the tomorrow we worried about yesterday.","author": null}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "It's easier to see the mistakes on someone else's paper.","author": null}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Every man dies. Not every man really lives.","author": null}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "To lead people walk behind them.","author": "Lao Tzu"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Having nothing, nothing can he lose.","author": "William Shakespeare"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Trouble is only opportunity in work clothes.","author": "Henry J. Kaiser"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "A rolling stone gathers no moss.","author": "Publilius Syrus"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Ideas are the beginning points of all fortunes.","author": "Napoleon Hill"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Everything in life is luck.","author": "Donald Trump"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Doing nothing is better than being busy doing nothing.","author": "Lao Tzu"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Trust yourself. You know more than you think you do.","author": "Benjamin Spock"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Study the past, if you would divine the future.","author": "Confucius"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "The day is already blessed, find peace within it.","author": null}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "From error to error one discovers the entire truth.","author": "Sigmund Freud"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Well done is better than well said.","author": "Benjamin Franklin"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Bite off more than you can chew, then chew it.","author": "Ella Williams"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Work out your own salvation. Do not depend on others.","author": "Buddha"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "One today is worth two tomorrows.","author": "Benjamin Franklin"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Once you choose hope, anythings possible.","author": "Christopher Reeve"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "God always takes the simplest way.","author": "Albert Einstein"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "One fails forward toward success.","author": "Charles Kettering"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "From small beginnings come great things.","author": null}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Learning is a treasure that will follow its owner everywhere","author": "Chinese proverb"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Be as you wish to seem.","author": "Socrates"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "The world is always in movement.","author": "V. Naipaul"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Never mistake activity for achievement.","author": "John Wooden"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "What worries you masters you.","author": "Haddon Robinson"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "One faces the future with ones past.","author": "Pearl Buck"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Goals are the fuel in the furnace of achievement.","author": "Brian Tracy"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "Who sows virtue reaps honour.","author": "Leonardo da Vinci"}
{"time":"1970-01-01T00:00:00.00","level":"FATAL","message": "Be the chief but never the lord.","author": "Lao Tzu"}
{"time":"1970-01-01T00:00:00.00","level":"PANIC","message": "Fate is in your hands and no one elses","author": "Byron Pulsifer"}
{"time":"1970-01-01T00:00:00.00","level":"ERROR","message": "Genius is one percent inspiration and ninety-nine percent perspiration.","author": "Thomas Edison"}
{"time":"1970-01-01T00:00:00.00","level":"INFO","message": "You can observe a lot just by watching.","author": "Yogi Berra"}
{"time":"1970-01-01T00:00:00.00","level":"DEBUG","message": "A house divided against itself cannot stand.","author": "Abraham Lincoln"}
{"time":"1970-01-01T00:00:00.00","level":"TRACE","message": "Difficulties increase the nearer we get to the goal.","author": "Johann Wolfgang von Goethe"}
plain text log
Loading