@windsor/logger
v1.1.1
Published
A system for automated and manual logging which can be compiled out
Downloads
4
Readme
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])
- Logging entrance and exit of specific functions with
- 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
, calledlogFns
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.