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

loglevel-plugin-remote

v0.6.8

Published

A loglevel plugin for sending browser logs to a server

Downloads

38,839

Readme

loglevel-plugin-remote

A loglevel plugin for sending browser logs to a server.

NPM versionBuild Status

Features

  • Sends logs asynchronously with a specified frequency using only one request at a time.
  • Slows the frequency of sending after a fail and restores after success.
  • Supports Bearer authentication scheme.
  • Provides light string interpolation like console and node.js (%s, %d, %j, %o).
  • Provides the ability to add any values ​​to the logs and specify a custom format.
  • Single file, no dependencies, weighs in at 2.3KB minified and gzipped.

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,
};
  • url (string) - a URL of the server logging API

  • method (string) - a HTTP method of the server logging API

  • headers (object) - this is to support custom headers passed down to the post request. For example { 'my-header': 'myHeaderValue' }

  • token (string) - a token for Bearer authentication scheme (see RFC 6750), e.g. UUID or JWT. By default is ''. If you set the value to undefined, the sending of logs will be suspended until the setToken method is called, but the logs will still accumulate in the queue.

  • onUnauthorized (function) - this function will be called after the sending of logs is suspended due to an authentication error. A token that has not been authenticated will be passed to the function.

  • timeout (number) - a timeout in milliseconds (see XMLHttpRequest.timeout)

  • interval (number) - a time in milliseconds between sending messages. By default is 1000 (one second).

  • level (string) - a plugin specific level. The plugin level does not cancel the level of the logger. The highest level will be used to send messages. If the level of the logger is warn, and the level of the plugin is error, only messages with the error level will be sent to the server. By default is trace.

  • backoff (function|object) - a function used to increase the sending interval after each failed send. The function receives the duration of the previous suspend and returns the duration of the next suspend. Instead of the function backoff can be represented by an object with 3 properties: multiplier, jitter and limit. By default, it doubles the interval (multiplier=2) and adds 10% jitter (jitter=0.1). Having reached the value of 30 seconds (limit=30000), the interval increase stops. After successful sending, the interval will be reset to the initial value.

  • capacity (number) - the size of the queue in which messages are accumulated between sending. By default is 500. Overflow will delete the oldest messages. It is forbidden to set the value to 0 - in this case the default value will be used.

  • stacktrace (object) - object for configuring a stacktrace with the following properties:

    • levels (array) - lots of levels for which to add the stack trace. By default is trace, warn and error.
    • depth (number) - number of stack trace lines. By default is 3.
    • excess (number) - number of excess lines generated by following plugins (each plugin adds one line). This number of lines will be removed from the top of the stack trace. By default is 0.
  • timestamp (function) - a function that returns a timestamp. By default, it returns the time in the ISO format (see ISO 8601)

  • format (function) - this option defines the logs format. This function will generate a log, obtaining as a single argument a log object that looks like this:

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