Skip to content

Instantly share code, notes, and snippets.

@jeffutter
Created August 6, 2015 17:31
Show Gist options
  • Save jeffutter/05a5b44bfa3d59b506f2 to your computer and use it in GitHub Desktop.
Save jeffutter/05a5b44bfa3d59b506f2 to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"encoding/json"
"fmt"
"github.com/fatih/color"
"github.com/nsf/termbox-go"
"os"
"strings"
"time"
)
var red func(...interface{}) string
var green func(...interface{}) string
var yellow func(...interface{}) string
var magenta func(...interface{}) string
var bold func(...interface{}) string
type Level struct {
level string
}
func (l *Level) Color() string {
switch l.level {
case "DEBUG":
return l.level
case "INFO":
return magenta(l.level)
case "WARN":
return yellow(l.level)
case "ERROR":
return red(l.level)
case "FATAL":
return red(l.level)
}
return l.level
}
type Terminal struct {
Width int
Height int
}
type LogLine struct {
Timestamp time.Time
Message string
Level Level
Subchannel string
Data map[string]interface{}
}
const inTimeFormat = "2006-01-02T15:04:05.9999999"
const outTimeFormat = "[2006-01-02 15:04:05] "
func (l *LogLine) Print(w int) {
ts := l.Timestamp.Format(outTimeFormat)
leftBorder := "| "
rightBorder := " | "
levelPadding := strings.Repeat(" ", 5-len(l.Level.level))
level := fmt.Sprintf("%s:%s", bold(l.Level.Color()), levelPadding)
levelWidth := 5
timeWidth := len(outTimeFormat)
subchannelWidth := 20
middleWidth := w - (timeWidth + levelWidth + len(leftBorder) + len(rightBorder) + subchannelWidth)
leftPadding := strings.Repeat(" ", timeWidth+levelWidth)
messageRunes := []rune(l.Message)
messageLength := len(messageRunes)
for i := 0; i < messageLength; i += middleWidth {
var chunkEnd int
if messageLength < i+middleWidth {
chunkEnd = messageLength
} else {
chunkEnd = i + middleWidth
}
lineMessage := string(messageRunes[i:chunkEnd])
lineMessage = strings.TrimSpace(lineMessage)
lineMessageLength := len(lineMessage)
rightPaddingLength := middleWidth - lineMessageLength
rightPadding := strings.Repeat(" ", rightPaddingLength)
if i == 0 {
fmt.Printf("%s%s %s%s%s%s\n", ts, level, bold(lineMessage), rightPadding, rightBorder, bold(green(l.Subchannel)))
} else {
fmt.Printf("%s%s%s%s%s%s\n", leftPadding, leftBorder, bold(lineMessage), rightPadding, rightBorder, bold(green(l.Subchannel)))
}
}
if len(l.Data) > 0 {
for key, val := range l.Data {
lineMessage := fmt.Sprintf("%s: %s", key, val)
lineMessageLength := len(lineMessage)
rightPaddingLength := middleWidth - lineMessageLength
var rightPadding string
if rightPaddingLength > 0 {
rightPadding = strings.Repeat(" ", rightPaddingLength)
} else {
rightPadding = ""
}
fmt.Printf("%s%s%s%s%s%s\n", leftPadding, leftBorder, lineMessage, rightPadding, rightBorder, bold(green(l.Subchannel)))
}
}
}
func main() {
red = color.New(color.FgRed).SprintFunc()
green = color.New(color.FgGreen).SprintFunc()
yellow = color.New(color.FgYellow).SprintFunc()
magenta = color.New(color.FgMagenta).SprintFunc()
bold = color.New(color.Bold).SprintFunc()
scanner := bufio.NewScanner(os.Stdin)
if err := termbox.Init(); err != nil {
panic(err)
}
w, h := termbox.Size()
terminal := Terminal{Width: w, Height: h}
// defer termbox.Close()
termbox.Close()
var j interface{}
for scanner.Scan() {
line := scanner.Text()
err := json.Unmarshal([]byte(line), &j)
if err != nil {
fmt.Println(line)
} else {
logLine := LogLine{}
l := j.(map[string]interface{})
if val, ok := l["timestamp"]; ok {
delete(l, "timestamp")
timestamp := val.(string)
t, _ := time.Parse(inTimeFormat, timestamp)
logLine.Timestamp = t
}
if val, ok := l["message"]; ok {
delete(l, "message")
logLine.Message = val.(string)
}
if val, ok := l["level"]; ok {
delete(l, "level")
logLine.Level = Level{strings.ToUpper(val.(string))}
}
if val, ok := l["subchannel"]; ok {
delete(l, "subchannel")
logLine.Subchannel = val.(string)
}
logLine.Data = l
logLine.Print(terminal.Width)
}
}
if err := scanner.Err(); err != nil {
fmt.Fprintln(os.Stderr, "reading standard input: ", err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment