diff --git a/chronicles/chronos_tools.nim b/chronicles/chronos_tools.nim index 88a27f2..266e41a 100644 --- a/chronicles/chronos_tools.nim +++ b/chronicles/chronos_tools.nim @@ -11,12 +11,5 @@ proc catchOrQuit*(error: Exception) = proc traceAsyncErrors*(fut: FutureBase) = fut.addCallback do (arg: pointer): - if not fut.error.isNil: + if fut.failed(): catchOrQuit fut.error[] - -template traceAwaitErrors*(fut: FutureBase) = - let f = fut - yield f - if not f.error.isNil: - catchOrQuit f.error[] - diff --git a/chronicles/log_output.nim b/chronicles/log_output.nim index 0f42a2e..2e1d948 100644 --- a/chronicles/log_output.nim +++ b/chronicles/log_output.nim @@ -551,6 +551,41 @@ proc initLogRecord*(r: var TextLineRecord, r.level = lvl appendHeader(r, lvl, topics, name, true) +const + controlChars = {'\x00'..'\x1f'} + extendedAsciiChars = {'\x7f'..'\xff'} + escapedChars*: set[char] = strutils.Newlines + {'"', '\\'} + controlChars + extendedAsciiChars + quoteChars*: set[char] = {' ', '='} + +func containsEscapedChars*(str: string|cstring): bool = + for c in str: + if c in escapedChars: + return true + return false + +func needsQuotes*(str: string|cstring): bool = + for c in str: + if c in quoteChars: + return true + return false + +proc writeEscapedString*(output: var string, str: string|cstring) = + for c in str: + case c + of '"': output.add "\\\"" + of '\\': output.add "\\\\" + of '\r': output.add "\\r" + of '\n': output.add "\\n" + of '\t': output.add "\\t" + else: + const hexChars = "0123456789abcdef" + if c >= char(0x20) and c <= char(0x7e): + output.add c + else: + output.add("\\x") + output.add hexChars[int(c) shr 4 and 0xF] + output.add hexChars[int(c) and 0xF] + proc setProperty*( r: var TextLineRecord, key: string, val: auto) {.raises: [].} = append(r.output, " ") @@ -566,20 +601,20 @@ proc setProperty*( # This is similar to how it's done in logfmt: # https://github.com/csquared/node-logfmt/blob/master/lib/stringify.js#L13 let - needsEscape = valText.find(Newlines + {'"', '\\'}) > -1 - needsQuote = valText.find({' ', '='}) > -1 + needsEscape = valText.find(escapedChars) > -1 + needsQuote = valText.find(quoteChars) > -1 if needsEscape or needsQuote: escaped = newStringOfCap(valText.len + valText.len div 8) + add(escaped, '"') if needsEscape: # addQuoted adds quotes and escapes a bunch of characters # XXX addQuoted escapes more characters than what we look for in above # needsEscape check - it's a bit weird that way - addQuoted(escaped, valText) + escaped.writeEscapedString(valText) elif needsQuote: - add(escaped, '"') add(escaped, valText) - add(escaped, '"') + add(escaped, '"') valueToWrite = addr escaped else: valueToWrite = unsafeAddr valText