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)