slfmt/src/slfmt.nim

81 lines
2.3 KiB
Nim

import std/[json, sequtils, streams, strutils, terminal, times]
import timeutils
#import docopt
const VERSION = "0.1.0"
# const USAGE = """Usage:
# slfmt
#
# Options:
#
# -h, --help Print this usage and help information
const fieldDisplayOrder = @[
"scope", "level", "ts", "code", "sid", "sub", "msg", "err", "stack", "method", "args"]
func decorate(
s: string,
fg = fgDefault,
style: set[Style] = {}): string =
result = ""
if style != {}:
result &= toSeq(items(style)).mapIt(ansiStyleCode(it)).join("")
if fg != fgDefault: result &= ansiForegroundColorCode(fg)
result &= s & ansiResetCode
proc formatField(name: string, value: JsonNode): string =
result = decorate(name, fgCyan) & ":" & " ".repeat(max(1, 10 - name.len))
var strVal: string = ""
case name:
of "ts":
let dt = parseIso8601(value.getStr)
strVal = decorate(dt.local.formatIso8601 & " (local) ", fgBlue, {styleBright}) &
dt.utc.formatIso8601 & " (UTC)"
of "sid", "sub": strVal = decorate(value.getStr, fgGreen)
of "err": strVal = decorate(value.getStr, fgRed)
of "msg": strVal = decorate(value.getStr, fgYellow)
of "stack": strVal = decorate(value.getStr, fgBlack, {styleBright})
else: strVal = pretty(value)
let valLines = splitLines(strVal)
if name.len > 10 or strVal.len + 16 > terminalWidth() or valLines.len > 1:
result &= "\n" & valLines.mapIt(" " & it).join("\n") & "\n"
else: result &= strVal & "\n"
proc prettyPrintFormat(logLine: string): string =
try:
var logJson = parseJson(logLine)
result = '-'.repeat(terminalWidth()) & "\n"
# Print the known fields in order first
for f in fieldDisplayOrder:
if logJson.hasKey(f):
result &= formatField(f, logJson[f])
logJson.delete(f)
# Print the rest of the fields
for (key, val) in pairs(logJson): result &= formatField(key, val)
result &= "\n"
except ValueError, JsonParsingError:
result = logLine
when isMainModule:
try:
var line: string = ""
let sin = newFileStream(stdin)
while(sin.readLine(line)): stdout.writeLine(prettyPrintFormat(line))
except:
stderr.writeLine("slfmt - FATAL: " & getCurrentExceptionMsg())
stderr.writeLine(getCurrentException().getStackTrace())
quit(QuitFailure)