Changing our mind: message -> msg; timestamp -> ts; error -> err

This commit is contained in:
2025-07-14 15:30:21 -05:00
parent bff544ab89
commit f0f0084cfd
2 changed files with 64 additions and 64 deletions

View File

@@ -1,6 +1,6 @@
# Package # Package
version = "2.0.3" version = "2.1.0"
author = "Jonathan Bernard" author = "Jonathan Bernard"
description = "Wrapper around std/logging to provide namespaced logging." description = "Wrapper around std/logging to provide namespaced logging."
license = "MIT" license = "MIT"

View File

@@ -23,7 +23,7 @@ type
ErrorHandlerFunc* = ErrorHandlerFunc* =
proc (error: ref Exception, msg: string) {.gcsafe,nimcall.} proc (err: ref Exception, msg: string) {.gcsafe,nimcall.}
LogService* = object LogService* = object
@@ -66,21 +66,21 @@ type
LogMessage* = object LogMessage* = object
scope*: string scope*: string
level*: Level level*: Level
error*: Option[ref Exception] err*: Option[ref Exception]
timestamp*: DateTime ts*: DateTime
message*: string msg*: string
additionalData*: JsonNode additionalData*: JsonNode
LogMessageFormatter* = proc (msg: LogMessage): string {.gcsafe.} LogMessageFormatter* = proc (msg: LogMessage): string {.gcsafe.}
ConsoleMessage = object ConsoleMessage = object
message: string msg: string
useStderr: bool useStderr: bool
FileMessage = object FileMessage = object
message: string msg: string
absPath: Path absPath: Path
@@ -139,16 +139,16 @@ initLock(loggingThreadInitLock)
proc initLogMessage*( proc initLogMessage*(
scope: string, scope: string,
lvl: Level, lvl: Level,
message: string, msg: string,
error: Option[ref Exception] = none[ref Exception](), err: Option[ref Exception] = none[ref Exception](),
additionalData: JsonNode = JNULL): LogMessage = additionalData: JsonNode = JNULL): LogMessage =
LogMessage( LogMessage(
scope: scope, scope: scope,
level: lvl, level: lvl,
error: error, err: err,
timestamp: now(), ts: now(),
message: message, msg: msg,
additionalData: additionalData) additionalData: additionalData)
@@ -156,15 +156,16 @@ proc initLogMessage*(
scope: string, scope: string,
lvl: Level, lvl: Level,
msg: JsonNode, msg: JsonNode,
error: Option[ref Exception] = none[ref Exception]()): LogMessage = err: Option[ref Exception] = none[ref Exception]()): LogMessage =
LogMessage( LogMessage(
scope: scope, scope: scope,
level: lvl, level: lvl,
error: error, err: err,
timestamp: now(), ts: now(),
message: msg:
if msg.hasKey("message"): msg["message"].getStr if msg.hasKey("msg"): msg["msg"].getStr
elif msg.hasKey("message"): msg["message"].getStr
else: "", else: "",
additionalData: msg) additionalData: msg)
@@ -196,7 +197,7 @@ proc shutdownThreadedConsoleLogging() =
consoleLogging.shutdown.store(true) # signal shutdown consoleLogging.shutdown.store(true) # signal shutdown
# Send sentinel values to wake up the writer thread # Send sentinel values to wake up the writer thread
try: consoleLogging.chan.send(ConsoleMessage(message: "", useStderr: false)) try: consoleLogging.chan.send(ConsoleMessage(msg: "", useStderr: false))
except Exception: discard except Exception: discard
joinThread(consoleLogging.writerThread) joinThread(consoleLogging.writerThread)
@@ -210,7 +211,7 @@ proc shutdownThreadedFileLogging() =
fileLogging.shutdown.store(true) # signal shutdown fileLogging.shutdown.store(true) # signal shutdown
withLock loggingThreadInitLock: withLock loggingThreadInitLock:
try: fileLogging.chan.send(FileMessage(message: "", absPath: Path("/"))) try: fileLogging.chan.send(FileMessage(msg: "", absPath: Path("/")))
except Exception: discard except Exception: discard
joinThread(fileLogging.writerThread) joinThread(fileLogging.writerThread)
@@ -334,13 +335,13 @@ func `%`*(msg: LogMessage): JsonNode =
result = %*{ result = %*{
"scope": msg.scope, "scope": msg.scope,
"level": fmtLevel(msg.level), "level": fmtLevel(msg.level),
"message": msg.message, "msg": msg.msg,
"timestamp": msg.timestamp.formatIso8601 "ts": msg.ts.formatIso8601
} }
if msg.error.isSome: if msg.err.isSome:
result["error"] = %($msg.error.get.name & ": " & msg.error.get.msg) result["err"] = %($msg.err.get.name & ": " & msg.err.get.msg)
result["stacktrace"] = %($msg.error.get.trace) result["stacktrace"] = %($msg.err.get.trace)
if msg.additionalData.kind == JObject: if msg.additionalData.kind == JObject:
for (k, v) in pairs(msg.additionalData): for (k, v) in pairs(msg.additionalData):
@@ -373,7 +374,7 @@ proc setRootThreshold*(ls: ThreadLocalLogService, lvl: Level) {.gcsafe.} =
setRootThreshold(ls[], lvl) setRootThreshold(ls[], lvl)
func formatSimpleTextLog*(msg: LogMessage): string {.gcsafe.} = msg.message func formatSimpleTextLog*(msg: LogMessage): string {.gcsafe.} = msg.msg
func formatJsonStructuredLog*(msg: LogMessage): string {.gcsafe.} = $(%msg) func formatJsonStructuredLog*(msg: LogMessage): string {.gcsafe.} = $(%msg)
@@ -515,13 +516,12 @@ template log*(l: Logger, lvl: Level, msg: untyped) =
sendToAppenders(l, initLogMessage(l.scope, lvl, msg)) sendToAppenders(l, initLogMessage(l.scope, lvl, msg))
template log*[T: ref Exception](l: Logger, lvl: Level, err: T, msg: untyped) = template log*(l: Logger, lvl: Level, err: ref Exception, msg: untyped) =
ensureFreshness(l.threadSvc) ensureFreshness(l.threadSvc)
if lvl >= l.getEffectiveThreshold: if lvl >= l.getEffectiveThreshold:
sendToAppenders( sendToAppenders(l, initLogMessage(
l, l.scope, lvl, msg, some(cast[ref Exception](err))))
initLogMessage(l.scope, lvl, msg, some(cast[ref Exception](err))))
template log*(l: Option[Logger], lm: LogMessage) = template log*(l: Option[Logger], lm: LogMessage) =
if l.isSome: log(l.get, lm) if l.isSome: log(l.get, lm)
@@ -532,9 +532,9 @@ template log*(l: Option[Logger], lvl: Level, msg: untyped) =
template log*( template log*(
l: Option[Logger], l: Option[Logger],
lvl: Level, lvl: Level,
error: ref Exception, err: ref Exception,
msg: untyped) = msg: untyped) =
if l.isSome: log(l.get, lvl, error, msg) if l.isSome: log(l.get, lvl, err, msg)
template debug*[L: Logger or Option[Logger], M](l: L, msg: M) = template debug*[L: Logger or Option[Logger], M](l: L, msg: M) =
log(l, lvlDebug, msg) log(l, lvlDebug, msg)
@@ -551,14 +551,14 @@ template warn*[L: Logger or Option[Logger], M](l: L, msg: M) =
template error*[L: Logger or Option[Logger], M](l: L, msg: M) = template error*[L: Logger or Option[Logger], M](l: L, msg: M) =
log(l, lvlError, msg) log(l, lvlError, msg)
template error*[L: Logger or Option[Logger], M](l: L, error: ref Exception, msg: M) = template error*[L: Logger or Option[Logger], M](l: L, err: ref Exception, msg: M) =
log(l, lvlError, error, msg) log(l, lvlError, err, msg)
template fatal*[L: Logger or Option[Logger], M](l: L, msg: M) = template fatal*[L: Logger or Option[Logger], M](l: L, msg: M) =
log(l, lvlFatal, msg) log(l, lvlFatal, msg)
template fatal*[L: Logger or Option[Logger], M](l: L, error: ref Exception, msg: M) = template fatal*[L: Logger or Option[Logger], M](l: L, err: ref Exception, msg: M) =
log(l, lvlFatal, error, msg) log(l, lvlFatal, err, msg)
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
@@ -569,13 +569,13 @@ proc consoleWriterLoop() {.thread.} =
while not consoleLogging.shutdown.load(): while not consoleLogging.shutdown.load():
var didSomething = false var didSomething = false
let (hasData, msg) = consoleLogging.chan.tryRecv() let (hasData, cMsgObj) = consoleLogging.chan.tryRecv()
if hasData and msg.message.len > 0: # Skip empty sentinel messages if hasData and cMsgObj.msg.len > 0: # Skip empty sentinel messages
try: try:
let output = let output =
if msg.useStderr: stderr if cMsgObj.useStderr: stderr
else: stdout else: stdout
output.write(msg.message) output.write(cMsgObj.msg)
output.flushFile() output.flushFile()
didSomething = true didSomething = true
except IOError: except IOError:
@@ -605,12 +605,12 @@ proc fileWriterLoop() {.thread.} =
# Organize messages by destination file # Organize messages by destination file
msgsByPath.clear() msgsByPath.clear()
while writeIdx < recvIdx: while writeIdx < recvIdx:
let msg = msgBuf[writeIdx] let fMsgObj = msgBuf[writeIdx]
inc writeIdx inc writeIdx
if msg.message.len > 0: # skip empty sentinel messages if fMsgObj.msg.len > 0: # skip empty sentinel messages
if not msgsByPath.contains(msg.absPath): msgsByPath[msg.absPath] = @[] if not msgsByPath.contains(fMsgObj.absPath): msgsByPath[fMsgObj.absPath] = @[]
msgsByPath[msg.absPath].add(msg) msgsByPath[fMsgObj.absPath].add(fMsgObj)
didSomething = true didSomething = true
# Write all messages in file order to optimize file open/flush/close # Write all messages in file order to optimize file open/flush/close
@@ -622,7 +622,7 @@ proc fileWriterLoop() {.thread.} =
continue continue
for m in msgs: for m in msgs:
try: writeLine(f, m.message) try: writeLine(f, m.msg)
except Exception: discard except Exception: discard
flushFile(f) flushFile(f)
close(f) close(f)
@@ -735,7 +735,7 @@ proc appendLogMessageMultiThreaded(
try: try:
consoleLogging.chan.send(ConsoleMessage( consoleLogging.chan.send(ConsoleMessage(
message: cla.formatter(msg), msg: cla.formatter(msg),
useStderr: cla.useStderr)) useStderr: cla.useStderr))
except Exception: except Exception:
try: try:
@@ -746,9 +746,9 @@ proc appendLogMessageMultiThreaded(
output.writeLine(cla.formatter(LogMessage( output.writeLine(cla.formatter(LogMessage(
scope: "namespaced_logging", scope: "namespaced_logging",
level: lvlError, level: lvlError,
error: some(getCurrentException()), err: some(getCurrentException()),
timestamp: now(), ts: now(),
message: "Unable to write log to channel in multi-threaded context." msg: "Unable to write log to channel in multi-threaded context."
))) )))
output.flushFile() output.flushFile()
except Exception: discard except Exception: discard
@@ -820,7 +820,7 @@ proc appendLogMessageMultiThreaded(
try: try:
fileLogging.chan.send(FileMessage( fileLogging.chan.send(FileMessage(
message: fla.formatter(msg), msg: fla.formatter(msg),
absPath: fla.absPath)) absPath: fla.absPath))
except Exception: discard except Exception: discard
@@ -1052,7 +1052,7 @@ when isMainModule:
let logger = ls.getLogger("test") let logger = ls.getLogger("test")
logger.log(lvlDebug, "debug string msg") logger.log(lvlDebug, "debug string msg")
logger.log(lvlInfo, %*{"message": "info json msg"}) logger.log(lvlInfo, %*{"msg": "info json msg"})
logger.log(lvlNotice, "notice string msg") logger.log(lvlNotice, "notice string msg")
logger.log(lvlError, newException(ValueError, "exception msg"), "error ex. msg") logger.log(lvlError, newException(ValueError, "exception msg"), "error ex. msg")
@@ -1060,13 +1060,13 @@ when isMainModule:
check: check:
lm.len == 4 lm.len == 4
lm[0].level == lvlDebug lm[0].level == lvlDebug
lm[0].message.contains("debug string msg") lm[0].msg.contains("debug string msg")
lm[1].level == lvlInfo lm[1].level == lvlInfo
lm[1].message.contains("info json msg") lm[1].msg.contains("info json msg")
lm[2].level == lvlNotice lm[2].level == lvlNotice
lm[2].message.contains("notice string msg") lm[2].msg.contains("notice string msg")
lm[3].level == lvlError lm[3].level == lvlError
lm[3].message.contains("error ex. msg") lm[3].msg.contains("error ex. msg")
test "logger convenience methods work": test "logger convenience methods work":
let logger = ls.getLogger("test") let logger = ls.getLogger("test")
@@ -1097,8 +1097,8 @@ when isMainModule:
let lm = loggedMsgs.get() let lm = loggedMsgs.get()
check: check:
lm.len == 1 lm.len == 1
lm[0].error.isSome lm[0].err.isSome
lm[0].error.get.msg == "test error" lm[0].err.get.msg == "test error"
test "optional logger methods": test "optional logger methods":
@@ -1110,7 +1110,7 @@ when isMainModule:
let lm = loggedMsgs.get() let lm = loggedMsgs.get()
check lm.len == 1 check lm.len == 1
check lm[0].message == "test message" check lm[0].msg == "test message"
suite "Threshold and Filtering": suite "Threshold and Filtering":
setup: setup:
@@ -1182,7 +1182,7 @@ when isMainModule:
let lm = loggedMsgs.get() let lm = loggedMsgs.get()
check: check:
lm.len == 1 lm.len == 1
lm[0].message.contains("Expensive call (1)") lm[0].msg.contains("Expensive call (1)")
expensiveCallCount == 1 expensiveCallCount == 1
suite "Appender Functionality": suite "Appender Functionality":
@@ -1359,9 +1359,9 @@ when isMainModule:
lines[2] == "ERROR [test] message at error" lines[2] == "ERROR [test] message at error"
lm.len == 3 lm.len == 3
lm[0].message.contains("message at notice") lm[0].msg.contains("message at notice")
lm[1].message.contains("message at warn") lm[1].msg.contains("message at warn")
lm[2].message.contains("message at fatal") lm[2].msg.contains("message at fatal")
test "fallbackOnly works when off": test "fallbackOnly works when off":
ls.addAppender(initStdLoggingAppender(fallbackOnly = false)) ls.addAppender(initStdLoggingAppender(fallbackOnly = false))
@@ -1394,6 +1394,6 @@ when isMainModule:
lines[5] == "FATAL [test] message at fatal" lines[5] == "FATAL [test] message at fatal"
lm.len == 3 lm.len == 3
lm[0].message.contains("message at notice") lm[0].msg.contains("message at notice")
lm[1].message.contains("message at warn") lm[1].msg.contains("message at warn")
lm[2].message.contains("message at fatal") lm[2].msg.contains("message at fatal")