Code Monkey home page Code Monkey logo

log-n-roll's Introduction

log-n-roll

Tiny 1kb logger with slim api and ability of limitless extension.

NPM versionBuild Status

  • Tiny: weighs about one kilobyte gzipped
  • Pluggable: one built-in plugin for pretty formatting and limitless possibilities for extension

Note

This packege is Proof-of-Concept and should be considered as an unstable. Nevertheless, the basic idea has already been proved. Release coming soon.

Install

This project uses node and npm. Go check them out if you don't have them locally installed.

$ npm install log-n-roll

Then with a module bundler like rollup or webpack, use as you would anything else:

// using ES6 modules
import log from 'log-n-roll';

// using CommonJS modules
var log = require('log-n-roll');

The UMD build is also available on unpkg:

<script src="https://unpkg.com/log-n-roll/dist/log-n-roll.umd.js"></script>

You can find the library on window.log.

Usage

const log = require('log-n-roll');

log.trace('Trace shows stacktrace');

// Using the built-in plugin
log.use(log.prefixer);
log.trace('Using any number of plugins adds to the stacktrace only one extra line');

log.info("By default, the level of the default logger is 'trace'. All messages are displayed");

// Loading the processor
let two = 2;
for (let i = 0; i < 1000000; i++) {
  two *= two;
  two = Math.sqrt(two);
}

log.debug('Debug shows the time difference from the last call of any logger method');
log.info('Placeholders are supported. Two = %s', two);
log.warn('Warn message');
log.error('Error message');

// Getting the named logger and setting its level to 'warn'
const child = log('child', 'warn');
child.info('Messages below the level of the logger are ignored');

child.level = 'info';
child.info('The level of the logger can be changed at any time');

child().info(
  'Default logger can be obtained from any logger: child() %s== log() %s== log',
  child() === log() ? '=' : '!',
  log() === log ? '=' : '!',
);

child('any').info(
  'Any logger can be obtained from any logger: child("any") %s== log("any")',
  child('any') === log('any') ? '=' : '!',
);

log('any').debug('Any logger has extended the level from the default logger');
child('any').info('Any logger has extended the plugins props from the default logger');

Output:

Trace: Trace shows stacktrace
    at Object.<anonymous> (C:\Users\u36\Dropbox\kutuluk\log-n-roll\examples\basic.js:3:5)
    ...
Trace: 17:42:21.579 [trace] default : Using any number of plugins adds to the stacktrace only one extra line
    at Function.trace (C:\Users\u36\Dropbox\kutuluk\log-n-roll\dist\log-n-roll.js:1:730)
    at Object.<anonymous> (C:\Users\u36\Dropbox\kutuluk\log-n-roll\examples\basic.js:7:5)
    ...
17:42:21.579 [ info] default : By default, the level of the default logger is 'trace'. All messages are displayed
       +54ms [debug] default : Debug shows the time difference from the last call of any logger method
17:42:21.634 [ info] default : Placeholders are supported. Two = 2
17:42:21.635 [ warn] default : Warn message
17:42:21.635 [error] default : Error message
17:42:21.636 [ info]   child : The level of the logger can be changed at any time
17:42:21.636 [ info] default : Default logger can be obtained from any logger: child() === log() === log
17:42:21.637 [ info]     any : Any logger can be obtained from any logger: child("any") === log("any")
        +0ms [debug]     any : Any logger has extended the level from the default logger
17:42:21.637 [ info]     any : Any logger has extended the plugins props from the default logger

Plugins

The resulted examples of plugins are simplified. Despite the fact that they are workable, it is not recommended to use in production.

log-stacktrace.js

function getStackTrace() {
  try {
    throw new Error();
  } catch (trace) {
    return trace.stack;
  }
}

module.exports = (logger, props) => {
  // Return noop plugin if stacktrace support is absent
  if (!getStackTrace()) {
    return () => {};
  }

  props = Object.assign(
    {
      levels: ['trace', 'warn', 'error'],
      depth: 3,
    },
    props,
  );

  return (state) => {
    if (!props.levels.some(level => level === state.label)) {
      return;
    }

    let stacktrace = getStackTrace();

    const lines = stacktrace.split('\n');
    lines.splice(0, 4);
    const { depth } = props;
    if (depth && lines.length !== depth + 1) {
      const shrink = lines.splice(0, depth);
      stacktrace = shrink.join('\n');
      if (lines.length) stacktrace += `\n    and ${lines.length} more`;
    } else {
      stacktrace = lines.join('\n');
    }

    state.stacktrace = stacktrace;
  };
};

log-meta.js

module.exports = (logger, props) => (state) => {
  const meta = Object.assign({}, props);

  const { args } = state;

  if (args.length && typeof args[0] === 'object') {
    Object.assign(meta, args.shift());
  }

  state.meta = meta;
};

log-message.js

const { format } = require('util');

module.exports = () => (state) => {
  state.message = format(...state.args);
};

log-json.js

module.exports = (logger, props) => {
  const fields = Object.keys(props);

  return (state) => {
    const json = {};

    fields.forEach((name) => {
      json[name] = typeof props[name] === 'function'
        ? props[name](state)
        : state[props[name]] || state[name];
    });

    state.json = JSON.stringify(json, null, '\t');
  };
};

to-file.js

const fs = require('fs');

module.exports = (logger, props) => {
  props = Object.assign(
    {
      file: 'app.log',
      fields: ['message', 'stacktrace'],
      separator: '\n',
      eol: '\n',
      roll: true,
    },
    props,
  );

  return (state) => {
    const fields = props.fields.map(field => state[field]).filter(field => field);

    fs.appendFileSync(props.file, fields.join(props.separator) + props.eol);

    state.roll = props.roll;
  };
};

An example of using these plugins

plugins.js

const log = require('../dist/log-n-roll');

const stacktrace = require('../examples/plugins/log-stacktrace');
const meta = require('../examples/plugins/log-meta');
const message = require('../examples/plugins/log-message');
const json = require('../examples/plugins/log-json');

const toFile = require('../examples/plugins/to-file');

log.use(stacktrace).use(meta, { source: 'plagins.js' }).use(log.prefixer).use(message)
  .use(json, {
    message: 'message',
    timestamp: state => new Date(state.timestamp).toISOString(),
    level: 'label',
    logger: 'logger',
    meta: 'meta',
    stacktrace: state => (state.stacktrace ? state.stacktrace.split('\n') : []),
  });

log.info({ tag: 'message1' }, 'Hello, %s', 'console!');

log.use(toFile, { file: 'my.log' });

log.info({ tag: 'message2' }, 'Hello, %s', 'file!');

const child = log('child')
  .use(toFile, {
    fields: ['json'],
    eol: ',\n',
    roll: false,
  })
  .use(meta, { format: 'json' })
  .unuse(log.prefixer);

child.trace({ tag: 'message3' }, 'Goodbye, %s', 'console!');

Console output:

17:45:35.926 [ info] default : Hello, console!
17:45:35.926 [ info] default : Hello, file!

my.log:

17:45:35.926 [ info] default : Hello, file!
{
	"message": "Goodbye, console!",
	"timestamp": "2018-02-13T13:45:35.941Z",
	"level": "trace",
	"logger": "child",
	"meta": {
		"source": "plugins.js",
		"format": "json",
		"tag": "message3"
	},
	"stacktrace": [
		"    at Object.<anonymous> (C:\\Users\\u36\\Dropbox\\kutuluk\\log-n-roll\\examples\\plugins.js:35:7)",
		"    at Module._compile (module.js:635:30)",
		"    at Object.Module._extensions..js (module.js:646:10)",
		"    and 4 more"
	]
},

log-n-roll's People

Contributors

kutuluk avatar marc136 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.