Add CustomLogAppender to allow extensible log appenders.
This commit is contained in:
parent
0eb0d33573
commit
e0dba8125c
@ -1,6 +1,6 @@
|
|||||||
# Package
|
# Package
|
||||||
|
|
||||||
version = "1.0.1"
|
version = "1.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"
|
||||||
|
@ -52,6 +52,9 @@ type
|
|||||||
## console.
|
## console.
|
||||||
useStderr*: bool
|
useStderr*: bool
|
||||||
|
|
||||||
|
CustomLogAppender* = ref object of LogAppender
|
||||||
|
doLogMessage*: proc (msg: LogMessage) {.gcsafe.}
|
||||||
|
|
||||||
#[
|
#[
|
||||||
# TODO: need to think throudh thread-safe IO for file logging
|
# TODO: need to think throudh thread-safe IO for file logging
|
||||||
FileLogAppender* = ref object of LogAppender
|
FileLogAppender* = ref object of LogAppender
|
||||||
@ -75,6 +78,12 @@ method initThreadCopy*(cla: ConsoleLogAppender): LogAppender {.gcsafe.} =
|
|||||||
useStderr: cla.useStdErr)
|
useStderr: cla.useStdErr)
|
||||||
|
|
||||||
|
|
||||||
|
method initThreadCopy*(cla: CustomLogAppender): LogAppender {.gcsafe.} =
|
||||||
|
result = CustomLogAppender(
|
||||||
|
namespace: cla.namespace,
|
||||||
|
threshold: cla.threshold,
|
||||||
|
doLogMessage: cla.doLogMessage)
|
||||||
|
|
||||||
#[
|
#[
|
||||||
method initThreadCopy*(fla: FileLogAppender): LogAppender {.gcsafe.} =
|
method initThreadCopy*(fla: FileLogAppender): LogAppender {.gcsafe.} =
|
||||||
result = FileLogAppender(
|
result = FileLogAppender(
|
||||||
@ -165,6 +174,16 @@ func initConsoleLogAppender*(
|
|||||||
useStderr: useStdErr)
|
useStderr: useStdErr)
|
||||||
|
|
||||||
|
|
||||||
|
func initCustomLogAppender*(
|
||||||
|
namespace = "",
|
||||||
|
threshold = lvlAll,
|
||||||
|
doLogMessage: proc (msg: LogMessage) {.gcsafe.}): CustomLogAppender {.gcsafe.} =
|
||||||
|
result = CustomLogAppender(
|
||||||
|
namespace: namespace,
|
||||||
|
threshold: threshold,
|
||||||
|
doLogMessage: doLogMessage)
|
||||||
|
|
||||||
|
|
||||||
method appendLogMessage*(appender: LogAppender, msg: LogMessage): void {.base, gcsafe.} =
|
method appendLogMessage*(appender: LogAppender, msg: LogMessage): void {.base, gcsafe.} =
|
||||||
raise newException(CatchableError, "missing concrete implementation")
|
raise newException(CatchableError, "missing concrete implementation")
|
||||||
|
|
||||||
@ -181,6 +200,12 @@ method appendLogMessage*(cla: ConsoleLogAppender, msg: LogMessage): void {.gcsaf
|
|||||||
stdout.flushFile()
|
stdout.flushFile()
|
||||||
|
|
||||||
|
|
||||||
|
method appendLogMessage*(cla: CustomLogAppender, msg: LogMessage): void {.gcsafe.} =
|
||||||
|
if msg.level < cla.threshold: return
|
||||||
|
|
||||||
|
cla.doLogMessage(msg)
|
||||||
|
|
||||||
|
|
||||||
proc getLogger*(
|
proc getLogger*(
|
||||||
ls: LogService,
|
ls: LogService,
|
||||||
name: string,
|
name: string,
|
||||||
@ -201,16 +226,57 @@ proc getLogger*(
|
|||||||
else: return some(getLogger(ls.get, name, threshold))
|
else: return some(getLogger(ls.get, name, threshold))
|
||||||
|
|
||||||
|
|
||||||
|
proc setThreshold*(ls: LogService, name: string, threshold: Level) {.gcsafe.} =
|
||||||
|
## Set the logging threshold for a logger and reload the thread state. This
|
||||||
|
## will affect the logger's thread-local copy, so you don't need to call
|
||||||
|
## `reloadThreadState` to make the change effective for the current thread,
|
||||||
|
## but in a multi-threaded context other pre-existing threads will not see
|
||||||
|
## the change until they reload their state.
|
||||||
|
acquire(ls.lock)
|
||||||
|
var idx = -1
|
||||||
|
for i in 0 ..< ls.cfg.loggers.len:
|
||||||
|
if ls.cfg.loggers[i].name == name:
|
||||||
|
idx = i
|
||||||
|
break
|
||||||
|
if idx == -1:
|
||||||
|
ls.cfg.loggers.add(LoggerConfig(name: name, threshold: some(threshold)))
|
||||||
|
else:
|
||||||
|
ls.cfg.loggers[idx].threshold = some(threshold)
|
||||||
|
release(ls.lock)
|
||||||
|
reloadThreadState(ls)
|
||||||
|
|
||||||
|
|
||||||
proc addAppender*(ls: LogService, appender: LogAppender) {.gcsafe.} =
|
proc addAppender*(ls: LogService, appender: LogAppender) {.gcsafe.} =
|
||||||
|
## Add a log appender to the log service. This will affect the logger's
|
||||||
|
## thread-local copy, so you don't need to call `reloadThreadState` to make
|
||||||
|
## the change effective for the current thread, but in a multi-threaded
|
||||||
|
## context other pre-existing threads will not see the change until they
|
||||||
|
## reload their state.
|
||||||
acquire(ls.lock)
|
acquire(ls.lock)
|
||||||
ls.cfg.appenders.add(appender)
|
ls.cfg.appenders.add(appender)
|
||||||
release(ls.lock)
|
release(ls.lock)
|
||||||
|
reloadThreadState(ls)
|
||||||
|
|
||||||
|
|
||||||
|
proc clearAppenders*(ls: LogService) {.gcsafe.} =
|
||||||
|
## Clear all log appenders from the log service. This will affect the
|
||||||
|
## logger's thread-local copy, so you don't need to call `reloadThreadState`
|
||||||
|
## to make the change effective for the current thread, but in a multi-threaded
|
||||||
|
## context other pre-existing threads will not see the change until they
|
||||||
|
## reload their state.
|
||||||
|
acquire(ls.lock)
|
||||||
|
ls.cfg.appenders = @[]
|
||||||
|
release(ls.lock)
|
||||||
|
reloadThreadState(ls)
|
||||||
|
|
||||||
|
|
||||||
func `<`(a, b: LoggerConfig): bool = a.name < b.name
|
func `<`(a, b: LoggerConfig): bool = a.name < b.name
|
||||||
|
|
||||||
|
|
||||||
func getEffectiveLevel(ts: ThreadState, name: string): Level {.gcsafe.} =
|
func getEffectiveLevel(ts: ThreadState, name: string): Level {.gcsafe.} =
|
||||||
|
## Get the effective logging level for a logger. This is the most specific
|
||||||
|
## level that is set for the logger or any of its parents. The root logger
|
||||||
|
## is used as the default if no other level is set.
|
||||||
result = ts.cfg.rootLevel
|
result = ts.cfg.rootLevel
|
||||||
|
|
||||||
var namespaces = toSeq(values(ts.loggers))
|
var namespaces = toSeq(values(ts.loggers))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user