2 Commits
0.1.0 ... 0.3.0

Author SHA1 Message Date
c0f818ef30 setLevelForNamespace now instantiates the namespace if necessary
- Hide initLoggingNamespace. getLoggerForNamespace should be used
  instead.
- setLevelForNamespace now calls getLoggerForNamespace to ensure the
  namespace exists when a caller tries to set the logging level.
  Previously it was possible to call setLevelForNamespace before the
  namespace was initialized, meaning that the setting had no effect.
  This is especially problematic for cases where a library is using
  namespaced logging with the filter set to a high level by default.
  The code using that library may want to enable debug logs, and is
  likely to call setLevelForNamespace in initialization code that runs
  prior to the library code which instantiates the namespace.
2022-11-03 15:03:48 -05:00
8245cfbdf7 Use a table for thread-global cache, hierarchical logging namespaces. 2022-06-04 21:48:25 -05:00
2 changed files with 34 additions and 11 deletions

View File

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

View File

@ -1,6 +1,6 @@
import logging, sequtils, strutils
import std/[logging, options, sequtils, strutils, tables]
export logging.Level
export logging
type
LoggingNamespace* = ref object
@ -8,22 +8,45 @@ type
level*: Level
msgPrefix*: string
var knownNamespaces {.threadvar.}: seq[LoggingNamespace]
var knownNamespacesInst {.threadvar.}: TableRef[string, LoggingNamespace]
proc initLoggingNamespace*(name: string, level = lvlInfo, msgPrefix: string): LoggingNamespace =
template knownNamespaces(): TableRef[string, LoggingNamespace] =
if knownNamespacesInst == nil:
knownNamespacesInst = newTable[string, LoggingNamespace]()
knownNamespacesInst
proc initLoggingNamespace(name: string, level = lvlInfo, msgPrefix: string): LoggingNamespace =
result = LoggingNamespace(
name: name,
level: level,
msgPrefix: msgPrefix)
knownNamespaces.add(result)
knownNamespaces[name] = result
proc initLoggingNamespace*(name: string, level = lvlInfo): LoggingNamespace =
return initLoggingNamespace(name, level, name & ": ")
proc getLoggerForNamespace*(
namespace: string,
level = lvlInfo,
msgPrefix: Option[string] = none[string]()
): LoggingNamespace =
## Get a LogginNamesapce for the given namespace. The first time this is
## called for a given name space a new logger will be created. In that case,
## the optional `level` and `msgPrefix` will be used to configure the logger.
## In all other cases, these paratmers are ignored and the existing namespace
## instance is returned
proc setLevelForNamespace*(namespace: string, lvl: Level) =
let found = knownNamespaces.filterIt(it.name == namespace)
for ns in found: ns.level = lvl
if knownNamespaces.hasKey(namespace): return knownNamespaces[namespace]
else:
if msgPrefix.isSome:
return initLoggingNamespace(namespace, level, msgPrefix.get)
else:
return initLoggingNamespace(namespace, level, namespace)
proc setLevelForNamespace*(namespace: string, lvl: Level, recursive = false) =
if recursive:
for k, v in knownNamespaces.pairs:
if k.startsWith(namespace):
v.level = lvl
else: getLoggerForNamespace(namespace).level = lvl
proc name*(ns: LoggingNamespace): string = ns.name
proc log*(ns: LoggingNamespace, level: Level, args: varargs[string, `$`]) =