morelogging

Logging library with support for async IO, multithreading, Journald.


Keywords
log, logging, library, systemd, journald, nim, nim-lang, syslog
License
LGPL-3.0
Install
nimble install morelogging

Documentation

Morelogging

A set of logging utilities for Nim.

badge CircleCI Appveyor release

Features:
  • ✓ File rotation

  • ✓ Compression

  • ✓ Templated log file name

  • ✓ Templated log messages

  • ✓ Threaded log buffering

  • ✓ Async log buffering

  • ✓ Logging, file rotation and compression do not block the caller

  • ❏ Do not crash the application on write failure (e.g. broken or full disk, permission errors) - switch to logging to stderr

  • ✓ Sensible defaults: log to "<appname>.<date>.log", daily log rotation

  • ❏ Rotate logfile on SIGHUP signal

  • ❏ Logging hierarchy

  • ✓ Log to systemd Journald. Support structured entries.

  • ❏ Structured logging and optional fields

  • ✓ Support Linux, OSX, Windows

  • ✓ Functional-tested

Installation
$ # install Nim using APT or from the upstream website
$ sudo apt-get install nim
$ # install nimble and then:
$ nimble install morelogging
Usage
import morelogging as log

let log = newAsyncFileLogger()
log.debug("debug")
log.info("info")
log.warn("warn")
log.error("error")
log.fatal("fatal")

Log message formatting

The following formatters are supported:

$date
$time
$datetime
$app
$appdir
$appname
$levelid
$levelname

Messages with level below level_threshold are ignored.

Async and threaded loggers

If buffer_size is positive, messages are buffered internally up to writeout_interval_ms

Messages with level >= flush_threshold are flushed out immediately.

proc newAsyncFileLogger*(
    filename_tpl = "$app.$y$MM$dd.log",
    flush_threshold = lvlError,
    fmtStr = "$datetime $levelname ",
    level_threshold = lvlAll,
    mode: FileMode = fmAppend,
    writeout_interval_ms = 100,
    buffer_size = 1_048_576
  ): AsyncFileLogger =

proc newThreadFileLogger*(
    filename_tpl = "$app.$y$MM$dd.log",
    fmtStr = "$datetime $levelname ",
    level_threshold = lvlAll,
    mode: FileMode = fmAppend,
    writeout_interval_ms = 100,
  ): ThreadFileLogger =

proc newThreadRotatingFileLogger*(
    compress = false,
    filename_tpl = "$app.$y$MM$dd.log",
    fmtStr = "$datetime $levelname ",
    level_threshold = lvlAll,
    mode: FileMode = fmAppend,
    rotate_interval = "1d",
    writeout_interval_ms = 100,
  ): ThreadRotatingFileLogger

Generating log file names dynamically

Filenames are generated from filename_tpl Default value: "$app.$y$MM$dd.log" The following formatters are supported:

$y         year
$MM        month
$dd        day
$hh        hour
$mm        minute
$ss        second
$hostname  hostname
$appname   application name

Systemd’s Journald logger

Journald supports logging user-defined key-value pairs and provides fast indexing.

Enable with -d:systemd

Usage:
let log = newJournaldLogger()
log.info("hello world", {"key_1": "value_1"})

Keys are converted to uppercase. They can contain underscores but not as the first character.

JournaldLogger will automatically add CODE_FILE, CODE_FUNC, CODE_LINE keys to show the filename, function and line number that generated the log message.

Note: '--stackTrace:on' and '--lineTrace:on' are required when building in release mode to enable this feature.

You can override them by passing the keys in uppercase with your own values.

Output example:
sudo journalctl -e -o json-pretty KEY_1=value_1 -n1 --no-pager
{
  "PRIORITY" : "5",
  "_TRANSPORT" : "journal",
  "_UID" : "1000",
  "_GID" : "1000",
  "MESSAGE" : "hello world",
  "KEY_1" : "value_1",
  "CODE_FUNC" : "myfunction",
  "CODE_FILE" : "mytest.nim",
  "CODE_LINE" : "24",
  < other lines redacted >
  < ... >
}