Created
August 6, 2015 17:31
-
-
Save jeffutter/05a5b44bfa3d59b506f2 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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