Allow users to set log flushing rules (#20817)

* Add flushThreshold to std/logging loggers

* Remove duplicate field

* Add -d:nimFlushAllLogs for changing default flush behavior globally

* Add changelog entry for log flushing change

* Flush all log levels by default in Nim v2
This commit is contained in:
Matt Haggard
2022-11-14 10:00:45 -05:00
committed by GitHub
parent d901d3b8c5
commit 1daf43fb14
2 changed files with 38 additions and 17 deletions

View File

@@ -100,6 +100,8 @@
This warning will become an error in future versions! Use a `cast` operation
like `cast[cstring](x)` instead.
- `logging` will default to flushing all log level messages. To get the legacy behaviour of only flushing Error and Fatal messages, use `-d:nimV1LogFlushBehavior`.
## Standard library additions and changes
[//]: # "Changes:"
@@ -119,6 +121,7 @@
- `std/oids` now uses `int64` to store time internally (before it was int32).
- `std/uri.Uri` dollar `$` improved, precalculates the `string` result length from the `Uri`.
- `std/uri.Uri.isIpv6` is now exported.
- `std/logging.ConsoleLogger` and `FileLogger` now have a `flushThreshold` attribute to set what log message levels are automatically flushed. For Nim v1 use `-d:nimFlushAllLogs` to automatically flush all message levels. Flushing all logs is the default behavior for Nim v2.
- `std/net.IpAddress` dollar `$` improved, uses a fixed capacity for the `string` result based from the `IpAddressFamily`.

View File

@@ -47,9 +47,8 @@
##
## .. warning::
## For loggers that log to a console or to files, only error and fatal
## messages will cause their output buffers to be flushed immediately.
## Use the `flushFile proc <syncio.html#flushFile,File>`_ to flush the buffer
## manually if needed.
## messages will cause their output buffers to be flushed immediately by default.
## set ``flushThreshold`` when creating the logger to change this.
##
## Handlers
## --------
@@ -200,6 +199,15 @@ const
## If a different format string is preferred, refer to the
## `documentation about format strings<#basic-usage-format-strings>`_
## for more information, including a list of available variables.
defaultFlushThreshold = when NimMajor >= 2:
when defined(nimV1LogFlushBehavior): lvlError else: lvlAll
else:
when defined(nimFlushAllLogs): lvlAll else: lvlError
## The threshold above which log messages to file-like loggers
## are automatically flushed.
##
## By default, only error and fatal messages are logged,
## but defining ``-d:nimFlushAllLogs`` will make all levels be flushed
type
Logger* = ref object of RootObj
@@ -228,6 +236,8 @@ type
## * `FileLogger<#FileLogger>`_
## * `RollingFileLogger<#RollingFileLogger>`_
useStderr*: bool ## If true, writes to stderr; otherwise, writes to stdout
flushThreshold*: Level ## Only messages that are at or above this
## threshold will be flushed immediately
when not defined(js):
type
@@ -243,6 +253,8 @@ when not defined(js):
## * `ConsoleLogger<#ConsoleLogger>`_
## * `RollingFileLogger<#RollingFileLogger>`_
file*: File ## The wrapped file
flushThreshold*: Level ## Only messages that are at or above this
## threshold will be flushed immediately
RollingFileLogger* = ref object of FileLogger
## A logger that writes log messages to a file while performing log
@@ -348,8 +360,8 @@ method log*(logger: ConsoleLogger, level: Level, args: varargs[string, `$`]) =
## `setLogFilter proc<#setLogFilter,Level>`_.
##
## **Note:** Only error and fatal messages will cause the output buffer
## to be flushed immediately. Use the `flushFile proc
## <syncio.html#flushFile,File>`_ to flush the buffer manually if needed.
## to be flushed immediately by default. Set ``flushThreshold`` when creating
## the logger to change this.
##
## See also:
## * `log method<#log.e,FileLogger,Level,varargs[string,]>`_
@@ -380,12 +392,12 @@ method log*(logger: ConsoleLogger, level: Level, args: varargs[string, `$`]) =
if logger.useStderr:
handle = stderr
writeLine(handle, ln)
if level in {lvlError, lvlFatal}: flushFile(handle)
if level >= logger.flushThreshold: flushFile(handle)
except IOError:
discard
proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr,
useStderr = false): ConsoleLogger =
useStderr = false, flushThreshold = defaultFlushThreshold): ConsoleLogger =
## Creates a new `ConsoleLogger<#ConsoleLogger>`_.
##
## By default, log messages are written to ``stdout``. If ``useStderr`` is
@@ -409,6 +421,7 @@ proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr,
new result
result.fmtStr = fmtStr
result.levelThreshold = levelThreshold
result.flushThreshold = flushThreshold
result.useStderr = useStderr
when not defined(js):
@@ -424,8 +437,8 @@ when not defined(js):
##
## **Notes:**
## * Only error and fatal messages will cause the output buffer
## to be flushed immediately. Use the `flushFile proc
## <syncio.html#flushFile,File>`_ to flush the buffer manually if needed.
## to be flushed immediately by default. Set ``flushThreshold`` when creating
## the logger to change this.
## * This method is not available for the JavaScript backend.
##
## See also:
@@ -443,7 +456,7 @@ when not defined(js):
## fileLog.log(lvlError, "error code is: ", 404)
if level >= logging.level and level >= logger.levelThreshold:
writeLine(logger.file, substituteLog(logger.fmtStr, level, args))
if level in {lvlError, lvlFatal}: flushFile(logger.file)
if level >= logger.flushThreshold: flushFile(logger.file)
proc defaultFilename*(): string =
## Returns the filename that is used by default when naming log files.
@@ -454,7 +467,8 @@ when not defined(js):
proc newFileLogger*(file: File,
levelThreshold = lvlAll,
fmtStr = defaultFmtStr): FileLogger =
fmtStr = defaultFmtStr,
flushThreshold = defaultFlushThreshold): FileLogger =
## Creates a new `FileLogger<#FileLogger>`_ that uses the given file handle.
##
## **Note:** This proc is not available for the JavaScript backend.
@@ -478,13 +492,15 @@ when not defined(js):
new(result)
result.file = file
result.levelThreshold = levelThreshold
result.flushThreshold = flushThreshold
result.fmtStr = fmtStr
proc newFileLogger*(filename = defaultFilename(),
mode: FileMode = fmAppend,
levelThreshold = lvlAll,
fmtStr = defaultFmtStr,
bufSize: int = -1): FileLogger =
bufSize: int = -1,
flushThreshold = defaultFlushThreshold): FileLogger =
## Creates a new `FileLogger<#FileLogger>`_ that logs to a file with the
## given filename.
##
@@ -508,7 +524,7 @@ when not defined(js):
## var formatLog = newFileLogger("formatted.log", fmtStr=verboseFmtStr)
## var errorLog = newFileLogger("errors.log", levelThreshold=lvlError)
let file = open(filename, mode, bufSize = bufSize)
newFileLogger(file, levelThreshold, fmtStr)
newFileLogger(file, levelThreshold, fmtStr, flushThreshold)
# ------
@@ -540,7 +556,8 @@ when not defined(js):
levelThreshold = lvlAll,
fmtStr = defaultFmtStr,
maxLines: Positive = 1000,
bufSize: int = -1): RollingFileLogger =
bufSize: int = -1,
flushThreshold = defaultFlushThreshold): RollingFileLogger =
## Creates a new `RollingFileLogger<#RollingFileLogger>`_.
##
## Once the current log file being written to contains ``maxLines`` lines,
@@ -576,6 +593,7 @@ when not defined(js):
result.curLine = 0
result.baseName = filename
result.baseMode = mode
result.flushThreshold = flushThreshold
result.logFiles = countFiles(filename)
@@ -602,8 +620,8 @@ when not defined(js):
##
## **Notes:**
## * Only error and fatal messages will cause the output buffer
## to be flushed immediately. Use the `flushFile proc
## <syncio.html#flushFile,File>`_ to flush the buffer manually if needed.
## to be flushed immediately by default. Set ``flushThreshold`` when creating
## the logger to change this.
## * This method is not available for the JavaScript backend.
##
## See also:
@@ -629,7 +647,7 @@ when not defined(js):
bufSize = logger.bufSize)
writeLine(logger.file, substituteLog(logger.fmtStr, level, args))
if level in {lvlError, lvlFatal}: flushFile(logger.file)
if level >= logger.flushThreshold: flushFile(logger.file)
logger.curLine.inc
# --------