kutuluk / loglevel-plugin-remote

A loglevel plugin for sending browser logs to a server
MIT License
102 stars 36 forks source link

loglevel-plugin-remote

A loglevel plugin for sending browser logs to a server.

NPM versionBuild Status

Features

Installation

npm i loglevel-plugin-remote --save

API

This plugin is under active development and should be considered as an unstable. No guarantees regarding API stability are made. Backward compatibility is guaranteed only by path releases.

apply(loglevel, options)

This method applies the plugin to the loglevel.

Parameters

loglevel - the root logger, imported from loglevel package

options - an optional configuration object

const defaults = {
  url: '/logger',
  method: 'POST',
  headers: {},
  token: '',
  onUnauthorized: failedToken => {},
  timeout: 0,
  interval: 1000,
  level: 'trace',
  backoff: {
    multiplier: 2,
    jitter: 0.1,
    limit: 30000,
  },
  capacity: 500,
  stacktrace: {
    levels: ['trace', 'warn', 'error'],
    depth: 3,
    excess: 0,
  },
  timestamp: () => new Date().toISOString(),
  format: remote.plain,
};
const log = {
  message: 'Text',
  level: {
    label: 'info',
    value: 2,
  },
  logger: 'child',
  timestamp: '2017-05-29T12:53:46.000Z',
  stacktrace: '',
};

When the function returns a string, the logs will be sent as plain text. The default value is function remote.plain:

function plain(log) {
  return `[${log.timestamp}] ${log.level.label.toUpperCase()}${
    log.logger ? ` (${log.logger})` : ''
  }: ${log.message}${log.stacktrace ? `\n${log.stacktrace}` : ''}`;
}

Then when you call:

log.getLogger('child').info('Info message');
log.error('Error message');

the logs look like this:

[2017-05-29T12:53:46.000Z] INFO (child): Info message
[2017-05-29T12:53:46.001Z] ERROR: Error message
    at http://localhost/test.js:12:5

When the function returns an object, the logs will be sent in json format. You can use the preset function remote.json:

function json(log) {
  log.level = log.level.label;
  return log;
}

then the logs will look like this:

{
  "logs": [
    {
      "message": "Info message",
      "level": "info",
      "logger": "child",
      "timestamp": "2017-05-29T12:53:46.000Z",
      "stacktrace": ""
    },
    {
      "message": "Error message",
      "level": "error",
      "logger": "",
      "timestamp": "2017-05-29T12:53:46.001Z",
      "stacktrace": "    at http://localhost/test.js:12:5"
    }
  ]
}

You can include any values ​​in the log. For example:

import log from 'loglevel';
import remote from 'loglevel-plugin-remote';

const getCounter = () => {
  let count = 1;
  return () => count++;
};
const counter = getCounter();

const customPlain = log => `[${counter()}] ${log.message}`;

/*
const customJSON = log => ({
  msg: log.message,
  count: counter(),
});
*/

remote.apply(log, { format: customPlain });
// remote.apply(log, { format: customJSON });

log.enableAll();
log.info('Message one');
log.info('Message two');

customPlain:

[1] Message one
[2] Message two

customJSON:

{
  "logs": [
    {
      "msg": "Message one",
      "count": 1
    },
    {
      "msg": "Message two",
      "count": 2
    }
  ]
}

setToken(token)

This method only has an effect after a successful call to the apply method and is used to assign a new authentication token. If you pass the value undefined, the sending of logs will be suspended until the next setToken call, but the logs will still accumulate in the queue.

disable()

This method cancels the effect of the plugin.

Base usage

Browser directly

<script src="https://unpkg.com/loglevel/dist/loglevel.min.js"></script>
<script src="https://unpkg.com/loglevel-plugin-remote@^0.6/dist/loglevel-plugin-remote.min.js"></script>

<script>
  var logger = log.noConflict();
  var sender = remote.noConflict();
  sender.apply(logger);
  logger.warn('message');
</script>

ES6

import log from 'loglevel';
import remote from 'loglevel-plugin-remote';

remote.apply(log);
log.warn('message');

CommonJS

var log = require('loglevel');
var remote = require('loglevel-plugin-remote');

remote.apply(log);
log.warn('message');

AMD

define(['loglevel', 'loglevel-plugin-remote'], function(log, remote) {
  remote.apply(log);
  log.warn('message');
});

Example

Code

var log = require('loglevel');
var remote = require('loglevel-plugin-remote');

log.enableAll();

remote.apply(log);

log.info('Log levels:');
log.trace('trace message');
log.debug('debug message');
log.info('info message');
log.warn('warn message');
log.error('error message');

Output in a log server

[2017-05-29T12:53:46.000Z] INFO: Log levels:
[2017-05-29T12:53:46.000Z] TRACE: trace message
    at http://localhost/js/test.js:9:5
[2017-05-29T12:53:46.000Z] DEBUG: debug message
[2017-05-29T12:53:46.000Z] INFO: info message
[2017-05-29T12:53:46.000Z] WARN: warn message
    at http://localhost/js/test.js:12:5
[2017-05-29T12:53:46.000Z] ERROR: error message
    at http://localhost/js/test.js:13:5

Code

log.info('String interpolation: %% %t %s', 'one', 'two');
log.info('Number interpolation: %d %d %d %d', 16, 1e6, '16', '1e6');

Output in a log server

[2017-05-29T12:53:46.000Z] INFO: String interpolation: % %t one two
[2017-05-29T12:53:46.000Z] INFO: Number interpolation: 16 1000000 16 1000000

Code

log.info('Object interpolation:');

function Rectangle(width, height) {
  this.width = width;
  this.height = height;
}
var object = new Rectangle(10, 10);
log.info('%s, %d, %o, %j', object, object, object, object, object);

var date = new Date();
log.info('date: %o', date);

var error = new Error('My error');
log.info('error: %o', error);

var string = 'My string';
log.info('string: %o', string);

var number = 123;
log.info('number: %o', number);

var bool = true;
log.info('boolean: %o', bool);

var array = [1, 2, 3];
log.info('array: %o', array);

Output in a log server

[2017-05-29T12:53:46.000Z] INFO: Object interpolation:
[2017-05-29T12:53:46.000Z] INFO: [object Object], NaN, Rectangle{"height":10,"width":10}, {"height":10,"width":10} [object Object]
[2017-05-29T12:53:46.000Z] INFO: date: Date<"2017-06-04T13:16:01.455Z">
[2017-05-29T12:53:46.000Z] INFO: error: Error{}
[2017-05-29T12:53:46.000Z] INFO: string: String<"My string">
[2017-05-29T12:53:46.000Z] INFO: number: Number<123>
[2017-05-29T12:53:46.000Z] INFO: boolean: Boolean<true>
[2017-05-29T12:53:46.000Z] INFO: array: Array[1,2,3]

Multiple plugins

Code

var log = require('loglevel');
var remote = require('loglevel-plugin-remote');
var mock = require('loglevel-plugin-mock');

// To clean the loglevel-plugin-mock line in the stack trace:
// options = { stacktrace: { excess: 1 } }
remote.apply(log, { stacktrace: { excess: 1 } });
mock.apply(log);

var array = [1, 2, 3];
log.warn('array: %o', array);

Output in a log server

[2017-05-29T12:53:46.000Z] WARN: array: Array[1,2,3]
    at http://localhost/js/test.js:11:5