From bc519fdd51c66fa527e1d4999f245211f8aab1b5 Mon Sep 17 00:00:00 2001 From: Yury Benesh Date: Tue, 10 Jul 2012 00:30:02 +0300 Subject: [PATCH 1/5] Made logging.nim compile. --- devel/logging.nim | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/devel/logging.nim b/devel/logging.nim index 7ae4d7eee0..946837157f 100644 --- a/devel/logging.nim +++ b/devel/logging.nim @@ -18,6 +18,8 @@ ## ## +import strutils, os, times + type TLevel* = enum ## logging level lvlAll, ## all levels active @@ -25,11 +27,12 @@ type lvlInfo, ## info level (and any above) active lvlWarn, ## warn level (and any above) active lvlError, ## error level (and any above) active - lvlFatal ## fatal level (and any above) active + lvlFatal, ## fatal level (and any above) active + lvlNone const LevelNames*: array [TLevel, string] = [ - "DEBUG", "DEBUG", "INFO", "WARN", "ERROR", "FATAL" + "DEBUG", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "NONE" ] type @@ -44,7 +47,7 @@ type TRollingFileLogger* = object of TFileLogger ## logger that writes the ## message to a file - maxlines: int # maximum number of lines + maxLines: int # maximum number of lines lines: seq[string] method log*(L: ref TLogger, level: TLevel, @@ -102,7 +105,7 @@ proc newFileLogger*(filename = defaultFilename(), proc newRollingFileLogger*(filename = defaultFilename(), mode: TFileMode = fmAppend, levelThreshold = lvlNone, - maxLines = 1000): ref TFileLogger = + maxLines = 1000): ref TRollingFileLogger = new(result) result.levelThreshold = levelThreshold result.maxLines = maxLines @@ -112,34 +115,34 @@ var level* = lvlNone handlers*: seq[ref TLogger] = @[] -proc logLoop(level: TLevel, msg: string) = +proc logLoop(level: TLevel, frmt: string, args: openarray[string]) = for logger in items(handlers): if level >= logger.levelThreshold: - log(logger, level, msg) + log(logger, level, frmt, args) -template log*(level: TLevel, msg: string) = +template log*(level: TLevel, frmt: string, args: openarray[string]) = ## logs a message of the given level bind logLoop if level >= logging.Level: logLoop(level, frmt, args) -template debug*(msg: string) = +template debug*(frmt: string, args: openarray[string]) = ## logs a debug message - log(lvlDebug, msg) + log(lvlDebug, frmt, args) -template info*(msg: string) = +template info*(frmt: string, args: openarray[string]) = ## logs an info message - log(lvlInfo, msg) + log(lvlInfo, frmt, args) -template warn*(msg: string) = +template warn*(frmt: string, args: openarray[string]) = ## logs a warning message - log(lvlWarn, msg) + log(lvlWarn, frmt, args) -template error*(msg: string) = +template error*(frmt: string, args: openarray[string]) = ## logs an error message - log(lvlError, msg) + log(lvlError, frmt, args) -template fatal*(msg: string) = +template fatal*(frmt: string, args: openarray[string]) = ## logs a fatal error message - log(lvlFatal, msg) + log(lvlFatal, frmt, args) From c6fa27e8147894774c74a937db9d5598d8ecc165 Mon Sep 17 00:00:00 2001 From: Yury Benesh Date: Thu, 19 Jul 2012 23:42:08 +0300 Subject: [PATCH 2/5] Fixed template code with binding --- devel/logging.nim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/devel/logging.nim b/devel/logging.nim index 946837157f..04031e3dee 100644 --- a/devel/logging.nim +++ b/devel/logging.nim @@ -123,6 +123,9 @@ proc logLoop(level: TLevel, frmt: string, args: openarray[string]) = template log*(level: TLevel, frmt: string, args: openarray[string]) = ## logs a message of the given level bind logLoop + bind `%` + bind logging.Level + if level >= logging.Level: logLoop(level, frmt, args) From 969d141ef99a409a20db262a98d2f52f854e9661 Mon Sep 17 00:00:00 2001 From: Yury Benesh Date: Thu, 26 Jul 2012 23:52:47 +0300 Subject: [PATCH 3/5] Comments to logging --- devel/logging.nim | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/devel/logging.nim b/devel/logging.nim index 04031e3dee..1ef8048de5 100644 --- a/devel/logging.nim +++ b/devel/logging.nim @@ -44,7 +44,8 @@ type TFileLogger* = object of TLogger ## logger that writes the messages to a file f: TFile - + + # TODO: implement rolling log TRollingFileLogger* = object of TFileLogger ## logger that writes the ## message to a file maxLines: int # maximum number of lines @@ -58,11 +59,11 @@ method log*(L: ref TLogger, level: TLevel, method log*(L: ref TConsoleLogger, level: TLevel, frmt: string, args: openArray[string]) = - Writeln(stdout, LevelNames[level], " ", frmt % args) + Writeln(stdout, LevelNames[level], " ", frmt % args) method log*(L: ref TFileLogger, level: TLevel, frmt: string, args: openArray[string]) = - Writeln(L.f, LevelNames[level], " ", frmt % args) + Writeln(L.f, LevelNames[level], " ", frmt % args) proc defaultFilename*(): string = ## returns the default filename for a logger @@ -112,8 +113,8 @@ proc newRollingFileLogger*(filename = defaultFilename(), result.f = open(filename, mode) var - level* = lvlNone - handlers*: seq[ref TLogger] = @[] + level* = lvlAll ## global log filter + handlers*: seq[ref TLogger] = @[] ## handlers with their own log levels proc logLoop(level: TLevel, frmt: string, args: openarray[string]) = for logger in items(handlers): From 3580f029612ed9713e00c58133aa1f30f4eabe97 Mon Sep 17 00:00:00 2001 From: Yury Benesh Date: Sun, 29 Jul 2012 20:03:01 +0300 Subject: [PATCH 4/5] Rolling file logger changes. WIP. --- devel/logging.nim | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/devel/logging.nim b/devel/logging.nim index 1ef8048de5..9ae36b4dac 100644 --- a/devel/logging.nim +++ b/devel/logging.nim @@ -50,6 +50,8 @@ type ## message to a file maxLines: int # maximum number of lines lines: seq[string] + curLine : int + method log*(L: ref TLogger, level: TLevel, frmt: string, args: openArray[string]) = @@ -98,19 +100,40 @@ proc substituteLog*(frmt: string): string = proc newFileLogger*(filename = defaultFilename(), mode: TFileMode = fmAppend, - levelThreshold = lvlNone): ref TFileLogger = + levelThreshold = lvlAll): ref TFileLogger = new(result) result.levelThreshold = levelThreshold result.f = open(filename, mode) +# ------ + proc newRollingFileLogger*(filename = defaultFilename(), - mode: TFileMode = fmAppend, - levelThreshold = lvlNone, + mode: TFileMode = fmReadWrite, + levelThreshold = lvlAll, maxLines = 1000): ref TRollingFileLogger = new(result) result.levelThreshold = levelThreshold result.maxLines = maxLines result.f = open(filename, mode) + result.curLine = 0 + if mode in {fmReadWrite, fmReadWriteExisting}: + readLogLines(result) + +proc readLogLines(logger : ref TRollingFileLogger) = + f.readLine # TODO read all lines, update curLine + + +method log*(L: ref TRollingFileLogger, level: TLevel, + frmt: string, args: openArray[string]) = + # TODO + # if more than maxlines, then set cursor to zero + # otherwise add new line + # update line in the lines + # increment cursor + # store lines into file + Writeln(L.f, LevelNames[level], " ", frmt % args) + +# -------- var level* = lvlAll ## global log filter From 3f200d3e23ebf973570582bc48caf2cf769d4415 Mon Sep 17 00:00:00 2001 From: Yury Benesh Date: Wed, 1 Aug 2012 22:12:14 +0300 Subject: [PATCH 5/5] Added default format for logging. --- devel/logging.nim | 93 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 29 deletions(-) diff --git a/devel/logging.nim b/devel/logging.nim index 9ae36b4dac..57b34ce5e0 100644 --- a/devel/logging.nim +++ b/devel/logging.nim @@ -35,42 +35,31 @@ const "DEBUG", "DEBUG", "INFO", "WARN", "ERROR", "FATAL", "NONE" ] + defaultFmtStr = "" ## default string between log level and message per logger + verboseFmtStr = "$date $time " + type TLogger* = object of TObject ## abstract logger; the base type of all loggers levelThreshold*: TLevel ## only messages of level >= levelThreshold ## should be processed + fmtStr: string ## = defaultFmtStr by default, see substituteLog for $date etc. + TConsoleLogger* = object of TLogger ## logger that writes the messages to the ## console TFileLogger* = object of TLogger ## logger that writes the messages to a file f: TFile - # TODO: implement rolling log + # TODO: implement rolling log, will produce filename.1, filename.2 etc. TRollingFileLogger* = object of TFileLogger ## logger that writes the ## message to a file - maxLines: int # maximum number of lines - lines: seq[string] + maxLines: int # maximum number of lines curLine : int + baseName: string # initial filename + logFiles: int # how many log files already created, e.g. basename.1, basename.2... + -method log*(L: ref TLogger, level: TLevel, - frmt: string, args: openArray[string]) = - ## override this method in custom loggers. Default implementation does - ## nothing. - nil - -method log*(L: ref TConsoleLogger, level: TLevel, - frmt: string, args: openArray[string]) = - Writeln(stdout, LevelNames[level], " ", frmt % args) - -method log*(L: ref TFileLogger, level: TLevel, - frmt: string, args: openArray[string]) = - Writeln(L.f, LevelNames[level], " ", frmt % args) - -proc defaultFilename*(): string = - ## returns the default filename for a logger - var (path, name, ext) = splitFile(getAppFilename()) - result = changeFileExt(path / name & "_" & getDateStr(), "log") proc substituteLog*(frmt: string): string = ## converts $date to the current date @@ -96,41 +85,75 @@ proc substituteLog*(frmt: string): string = of "app": result.add(app) of "appdir": result.add(app.splitFile.dir) of "appname": result.add(app.splitFile.name) + + + +method log*(L: ref TLogger, level: TLevel, + frmt: string, args: openArray[string]) = + ## override this method in custom loggers. Default implementation does + ## nothing. + nil + +method log*(L: ref TConsoleLogger, level: TLevel, + frmt: string, args: openArray[string]) = + Writeln(stdout, LevelNames[level], " ", substituteLog(L.fmtStr), frmt % args) + +method log*(L: ref TFileLogger, level: TLevel, + frmt: string, args: openArray[string]) = + Writeln(L.f, LevelNames[level], " ", substituteLog(L.fmtStr), frmt % args) + +proc defaultFilename*(): string = + ## returns the default filename for a logger + var (path, name, ext) = splitFile(getAppFilename()) + result = changeFileExt(path / name & "_" & getDateStr(), "log") + + +proc newConsoleLogger*(levelThreshold = lvlAll) : ref TConsoleLogger = + new result + result.fmtStr = defaultFmtStr + result.levelThreshold = levelThreshold + proc newFileLogger*(filename = defaultFilename(), mode: TFileMode = fmAppend, levelThreshold = lvlAll): ref TFileLogger = new(result) result.levelThreshold = levelThreshold result.f = open(filename, mode) + result.fmtStr = defaultFmtStr # ------ +proc readLogLines(logger : ref TRollingFileLogger) = nil + #f.readLine # TODO read all lines, update curLine + + proc newRollingFileLogger*(filename = defaultFilename(), mode: TFileMode = fmReadWrite, levelThreshold = lvlAll, maxLines = 1000): ref TRollingFileLogger = new(result) result.levelThreshold = levelThreshold + result.fmtStr = defaultFmtStr result.maxLines = maxLines result.f = open(filename, mode) result.curLine = 0 - if mode in {fmReadWrite, fmReadWriteExisting}: - readLogLines(result) + + # TODO count all number files + # count lines in existing filename file + # if >= maxLines then rename to next numbered file and create new file + + #if mode in {fmReadWrite, fmReadWriteExisting}: + # readLogLines(result) -proc readLogLines(logger : ref TRollingFileLogger) = - f.readLine # TODO read all lines, update curLine method log*(L: ref TRollingFileLogger, level: TLevel, frmt: string, args: openArray[string]) = # TODO # if more than maxlines, then set cursor to zero - # otherwise add new line - # update line in the lines - # increment cursor - # store lines into file + Writeln(L.f, LevelNames[level], " ", frmt % args) # -------- @@ -173,3 +196,15 @@ template fatal*(frmt: string, args: openarray[string]) = ## logs a fatal error message log(lvlFatal, frmt, args) + +# -------------- + +when isMainModule: + var L = newConsoleLogger() + var fL = newFileLogger("test.log") + fL.fmtStr = verboseFmtStr + handlers.add(L) + handlers.add(fL) + info("hello", []) + +