@windsor/logger

1.1.1 • Public • Published

Logger

The purpose of this project is to provide a logging library with the following properties:

  • Most of the logging process is automated
    • Logging entrance and exit of specific functions with mLog.logFunc([level])
    • Logging entrance and exit of every function in a file with mLog.logFile([level])
  • Logs can be left in development code but compiled out in production
  • Log statements are abstracted from a specific library
    • In the options users may specify how pecific types of log statements should be compiled. Right now by default this for is electron-log but any log function may be used.
    • This allows for seamless changes to an entire logging system.
    • This allows for arbitrarily complex activities to happen during logging as almost any function can be specified as a logging function (restrictions noted below in the Specifying Logging Functions section)

The options file

Right now in the options file a user can specify two things:

  • The level of logs that should be compiled, called level
  • The function that should be used for logging for each level, called logFns Example:
module.exports = {
  level: "VERBOSE",
  logFns: {
    error: "log.error",
    warn: "log.warn",
    info: "log.info",
    verbose: "log.verbose",
    debug: "log.debug",
    silly: "log.silly"
  }
};

Levels

The ordering of logs is as follows error < warn < info < verbose < debug < silly. In the above example the level is verbose. This means that any logs less than or equal to verbose will be compiled into their specified logging functions, while other logs will be compiled out.

mLog.error("e");
mLog.warn("w");
mLog.info("i");
mLog.verbose("v");
mLog.debug("d");
mLog.silly("s");

Compiles to

log.error("e");
log.warn("w");
log.info("i");
log.verbose("v");

Given the above config

mLog.[level]

This consists of six commands: mLog.error, mLog.warn, mLog.info, mLog.verbose, mLog.debug, mLog.silly . Each take a single string argument, and during compilation they will be converted into the corrresponding function that has been specified in the options of the plugin, or electron-log if no logging function is specified

Specifying logging functions

The options object looks for an element named logFns which is a map of level to string where the string is the function you want to call. Example:

logFns: {
  error: "log.error",
  warn: "console.log",
  info: "log.info",
  verbose: "some.custom.function",
  debug: "which.takes.a",
  silly: "string"
}
//mLog.debug("hello world") --> which.takes.a("hello world");

The function passed in must take a single string as an argument. A more complex function can be used by wrapping it in a fuction which takes a single string. For Example:

const wrapFileWrite = str => {
  fs.writeFile("/tmp/test", str, err => {
    err && console.log(err);
  });
}

For now, anywhere a mLog statement is used there must also be an import for any functions specified for that level. So in the above example where ever mLog.error is used there must also be some definition of the function log.error . A simple way to get around this is to store log functions globally and set the log functions accordingly for example

global.log = require('electron-log').default;

And then in the options for the plugin

  logFns: {
    error: "global.log.error",
    warn: "global.log.warn",
    info: "global.log.info",
    verbose: "global.log.verbose",
    debug: "global.log.debug",
    silly: "global.log.silly"
  }

At this point individual imports are no longer necessary.

mLog.logFunc([level], ?suggestedName)

This is a single function into which a level is passed, and into which a suggestedName may be passed. This statement may compile into one of several things:

  • When placed outside of a function, this statement does nothing and will be compiiled out
  • When placed inside of a function
    • If the level specified in the plugins options is 'higher' than the level passed then nothing happens
    • If the statement is not the first line in a functino then nothing happens
    • Else the first (most nested) function in which the statement is contained is wrapped with log statements such that every call to the function will result in an enter an exit statement of the form: [Enter/Exit] funcName: fileName

As with the mLog.[level] statements, the function specified in the options which corresponds to level is used to log the entrance and exit, but unlike the mLog.[level] statements, the message is predecided (This is done so that logs can be parsed effectively to provide more detailed reports).

If no suggestedName is provided then the name will be inferred which can be successfully done in all cases where the name of the function does not depend on runtime information. If a suggestedName is provided then that is taken to be the name of the function instead. If there is no suggsted name and the name of the funciton can not be inferred then the log statements will take the form: [Enter/Exit] <Anon>: fileName

Details on how function entrance and exit is logged

A function of the the form:

const f = (a,b,c) => {
  const d = a + b;
  const f = d + c + 2;
  return f + d;
}

Will compile to

const f = (a,b,c) => {
  function _() {
    const d = a + b;
    const f = d + c + 2;
    return f + d;
  }

  logSpecifiedInConfig("Enter f: filename");

  const rtn = _();

  logSpecifiedInConfig("Exit f: filename");

  return rtn;
}

mLog.logFile([level])

This is a function that iterates through all the 'top level' functions and does one of several things

  • If the level specified is lower than the level in the plugins options nothing is done
  • If the funciton has a mLog.logFunc call inside it already this function does nothing
  • Else the function is wrapped as if it had a mLog.logFunc([level]) call inside of it

What does 'top level' function mean

Right now this means that the function is not inside another function, and the function is not inside a class. Soon users will be able to specify in the config which 'barriers' should not be crossed when searching for functions into a file so that every function can be logged recursively, or only a restricted subset of functions will be logged.

/@windsor/logger/

    Package Sidebar

    Install

    npm i @windsor/logger

    Weekly Downloads

    0

    Version

    1.1.1

    License

    GPLv3

    Unpacked Size

    242 kB

    Total Files

    64

    Last publish

    Collaborators

    • atfaust2
    • pranaygp