From 6c978f32cc1cb2da5b8fd72ebf48f67514e9da06 Mon Sep 17 00:00:00 2001 From: Jonathan Bernard Date: Sun, 19 Jan 2025 18:40:38 -0600 Subject: [PATCH] Add --compact option for simpler output. --- slfmt.nimble | 4 ++-- src/slfmt.nim | 51 +++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/slfmt.nimble b/slfmt.nimble index 11dc860..f508864 100644 --- a/slfmt.nimble +++ b/slfmt.nimble @@ -1,6 +1,6 @@ # Package -version = "0.1.2" +version = "0.2.0" author = "Jonathan Bernard" description = "Small utility to pretty-print strucutured logs." license = "MIT" @@ -11,4 +11,4 @@ bin = @["slfmt"] # Dependencies requires @["nim >= 2.2.0", "docopt"] -requires "timeutils" +requires @["timeutils", "zero_functional"] diff --git a/src/slfmt.nim b/src/slfmt.nim index 1a3abca..11f7e48 100644 --- a/src/slfmt.nim +++ b/src/slfmt.nim @@ -1,10 +1,10 @@ import std/[json, options, sequtils, streams, strutils, terminal, times] -import timeutils -import docopt +import docopt, timeutils, zero_functional from std/logging import Level +from std/sequtils import toSeq -const VERSION = "0.1.2" +const VERSION = "0.2.0" const USAGE = """Usage: slfmt [options] @@ -12,6 +12,7 @@ const USAGE = """Usage: Options: -h, --help Print this usage and help information + -c, --compact Compact output -l, --log-level Only show log events at or above this level -n, --namespace Only show log events from this namespace """ @@ -44,7 +45,7 @@ func decorate( result &= s & ansiResetCode -proc formatField(name: string, value: JsonNode): string = +proc fullFormatField(name: string, value: JsonNode): string = result = decorate(name, fgCyan) & ":" & " ".repeat(max(1, 10 - name.len)) var strVal: string = "" @@ -66,20 +67,51 @@ proc formatField(name: string, value: JsonNode): string = result &= "\n" & valLines.mapIt(" " & it).join("\n") & "\n" else: result &= strVal & "\n" -proc prettyPrintFormat(logJson: JsonNode): string = +proc fullFormat(logJson: JsonNode): string = result = '-'.repeat(terminalWidth()) & "\n" # Print the known fields in order first for f in fieldDisplayOrder: if logJson.hasKey(f): - result &= formatField(f, logJson[f]) + result &= fullFormatField(f, logJson[f]) logJson.delete(f) # Print the rest of the fields - for (key, val) in pairs(logJson): result &= formatField(key, val) + for (key, val) in pairs(logJson): result &= fullFormatField(key, val) result &= "\n" +proc compactFormat(logJson: JsonNode): string = + let ts = parseIso8601(logJson["ts"].getStr).local.formatIso8601 + var level = logJson["level"].getStr + if level == "ERROR": level = decorate(alignLeft(level, 7), fgRed) + elif level == "WARN": level = decorate(alignLeft(level, 7), fgYellow) + else: level = alignLeft(level, 7) + + result = "$1 $2 $3: $4" % [ + level, + decorate(alignLeft(ts[0..21], 23), fgBlue, {styleBright}), + decorate(logJson["scope"].getStr, fgGreen), + decorate(logJson["msg"].getStr, fgYellow)] + + let restNodes = (toSeq(pairs(logJson))) --> + filter(not ["level", "scope", "ts", "msg"].contains(it[0])) + + let restMsg = join(restNodes --> + map("$1: $2" % [decorate(it[0], fgCyan), it[1].getStr]), " ") + + if restMsg.len + result.len + 2 < terminalWidth(): + result &= " " & restMsg + else: + var line = " " + for (key, val) in restNodes: + let field = "$1: $2" % [decorate(key, fgCyan), val.getStr] + if line.len + field.len + 2 > terminalWidth(): + result &= "\n " & line + line = " " + line &= field & " " + result &= "\n " & line + proc parseLogLine(logLine: string): JsonNode = result = parseJson(logLine) @@ -95,6 +127,8 @@ when isMainModule: if args["--namespace"]: some($args["--namespace"]) else: none[string]() + let compact = args["--compact"] + var line: string = "" let sin = newFileStream(stdin) while(sin.readLine(line)): @@ -108,7 +142,8 @@ when isMainModule: if namespace.isSome and logJson.hasKey("scope"): if not logJson["scope"].getStr.startsWith(namespace.get): continue - stdout.writeLine(prettyPrintFormat(logJson)) + if compact: stdout.writeLine(compactFormat(logJson)) + else: stdout.writeLine(fullFormat(logJson)) except ValueError, JsonParsingError: stdout.writeLine(line) except: