npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@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])
  • 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.