5e48db045d9c7d58460e8da85dc4029fe828567f

Author
TheEdgeOfRage <git@theedgeofrage.com>
Committer
TheEdgeOfRage <git@theedgeofrage.com>
Date

Message

Initial commit

Diff

  1diff --git a/.golangci.yml b/.golangci.yml
  2new file mode 100644
  3index 0000000000000000000000000000000000000000..5cb0a2b1577094d6a2884a1fff78125d34ed0186
  4--- /dev/null
  5+++ b/.golangci.yml
  6@@ -0,0 +1,22 @@
  7+---
  8+linters:
  9+  enable:
 10+    - goimports
 11+    - stylecheck
 12+    - lll
 13+    - errcheck
 14+
 15+run:
 16+  go: '1.22'
 17+  timeout: 30s
 18+
 19+issues:
 20+  exclude-rules:
 21+    - linters:
 22+        - lll
 23+      source: "// nolint:lll"
 24+    - linters:
 25+        - unused
 26+        - deadcode
 27+        - varcheck
 28+      source: "// nolint:unused"
 29diff --git a/go.mod b/go.mod
 30new file mode 100644
 31index 0000000000000000000000000000000000000000..031cfca89a1f005ab8044e67a0fe62da86371e75
 32--- /dev/null
 33+++ b/go.mod
 34@@ -0,0 +1,14 @@
 35+module github.com/TheEdgeOfRage/logfmt
 36+
 37+go 1.22.0
 38+
 39+require (
 40+	github.com/fatih/color v1.16.0
 41+	github.com/go-logfmt/logfmt v0.6.0
 42+)
 43+
 44+require (
 45+	github.com/mattn/go-colorable v0.1.13 // indirect
 46+	github.com/mattn/go-isatty v0.0.20 // indirect
 47+	golang.org/x/sys v0.14.0 // indirect
 48+)
 49diff --git a/go.sum b/go.sum
 50new file mode 100644
 51index 0000000000000000000000000000000000000000..9fad359a24bf325299396920c3de725ae0c5341b
 52--- /dev/null
 53+++ b/go.sum
 54@@ -0,0 +1,13 @@
 55+github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
 56+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
 57+github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
 58+github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
 59+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
 60+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
 61+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 62+github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
 63+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 64+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 65+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 66+golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
 67+golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 68diff --git a/main.go b/main.go
 69new file mode 100644
 70index 0000000000000000000000000000000000000000..35a979dfa89d8395a798288aded0f72fc82cb569
 71--- /dev/null
 72+++ b/main.go
 73@@ -0,0 +1,90 @@
 74+package main
 75+
 76+import (
 77+	"fmt"
 78+	"os"
 79+	"strconv"
 80+	"strings"
 81+
 82+	"github.com/fatih/color"
 83+	"github.com/go-logfmt/logfmt"
 84+)
 85+
 86+const (
 87+	Debug   = "DEBUG"
 88+	Info    = "INFO"
 89+	Warning = "WARN"
 90+	Error   = "ERROR"
 91+	Fatal   = "FATAL"
 92+)
 93+
 94+var levelColors map[string]*color.Color
 95+
 96+func init() {
 97+	levelColors = map[string]*color.Color{
 98+		Debug:   color.New(color.FgBlack).Add(color.BgCyan).Add(color.Bold),
 99+		Info:    color.New(color.FgBlack).Add(color.BgGreen).Add(color.Bold),
100+		Warning: color.New(color.FgBlack).Add(color.BgYellow).Add(color.Bold),
101+		Error:   color.New(color.FgBlack).Add(color.BgRed).Add(color.Bold),
102+		Fatal:   color.New(color.FgBlack).Add(color.BgRed).Add(color.Bold),
103+	}
104+}
105+
106+func isNumeric(s string) bool {
107+	_, err := strconv.ParseFloat(s, 64)
108+	return err == nil
109+}
110+
111+func isBoolean(s string) bool {
112+	_, err := strconv.ParseBool(s)
113+	return err == nil
114+}
115+
116+func isNull(s string) bool {
117+	return s == "null" || s == "NULL" || s == "nil" || s == "<nil>" || s == "None"
118+}
119+
120+func getLevel(level string) string {
121+	level = strings.ToUpper(level)
122+	if level == "WARNING" {
123+		level = Warning
124+	}
125+	val, ok := levelColors[level]
126+	if !ok {
127+		return levelColors[Info].Sprintf("[%s]", Info)
128+	}
129+	return val.Sprintf("[%s]", level)
130+}
131+
132+func getValue(value string) string {
133+	if isNumeric(value) || isBoolean(value) {
134+		return color.MagentaString(value)
135+	}
136+	if isNull(value) {
137+		return color.YellowString(value)
138+	}
139+	return color.HiGreenString(value)
140+}
141+
142+func main() {
143+	decoder := logfmt.NewDecoder(os.Stdin)
144+	for decoder.ScanRecord() {
145+		line := ""
146+		level := Info
147+		timestamp := ""
148+		for decoder.ScanKeyval() {
149+			key, value := string(decoder.Key()), string(decoder.Value())
150+			if key == "level" {
151+				level = getLevel(value)
152+				continue
153+			}
154+			if key == "time" || key == "timestamp" {
155+				timestamp = value
156+				continue
157+			}
158+			line += fmt.Sprintf("%s=%s ", color.HiBlueString(key), getValue(value))
159+		}
160+
161+		fmt.Printf("%s %26s %s\n", timestamp, level, line)
162+	}
163+}