GithubHelp home page GithubHelp logo

pimterry / loglevel Goto Github PK

View Code? Open in Web Editor NEW
2.5K 40.0 169.0 530 KB

:ledger: Minimal lightweight logging for JavaScript, adding reliable log level methods to wrap any available console.log methods

License: MIT License

JavaScript 99.48% HTML 0.20% TypeScript 0.32%
javascript logging lightweight loglevel stack-traces setlevel

loglevel's Introduction

loglevel NPM version NPM downloads Build Status

Don't debug with logs alone - check out HTTP Toolkit: beautiful, powerful & open-source tools for building, testing & debugging HTTP(S)

Minimal lightweight simple logging for JavaScript (browsers, node.js or elsewhere). loglevel extends console.log() & friends with level-based logging and filtering, with none of console's downsides.

Test it out live in your browser console at https://pimterry.github.io/loglevel/demo/index.html

Loglevel is a barebones reliable everyday logging library. It does not do fancy things, it does not let you reconfigure appenders or add complex log filtering rules or boil tea (more's the pity), but it does have the all core functionality that you actually use:

Features

Simple

  • Log things at a given level (trace/debug/info/warn/error) to the console object (as seen in all modern browsers & node.js).
  • Filter logging by level (all the above or 'silent'), so you can disable all but error logging in production, and then run log.setLevel("trace") in your console to turn it all back on for a furious debugging session.
  • Single file, no dependencies, weighs in at 1.4 KB minified and gzipped.

Effective

  • Log methods gracefully fall back to simpler console logging methods if more specific ones aren't available: so calls to log.debug() go to console.debug() if possible, or console.log() if not.
  • Logging calls still succeed even if there's no console object at all, so your site doesn't break when people visit with old browsers that don't support the console object (here's looking at you, IE) and similar.
  • This then comes together giving a consistent reliable API that works in every JavaScript environment with a console available, and never breaks anything anywhere else.

Convenient

  • Log output keeps line numbers: most JS logging frameworks call console.log methods through wrapper functions, clobbering your stacktrace and making the extra info many browsers provide useless. We'll have none of that thanks.
  • It works with all the standard JavaScript loading systems out of the box (CommonJS, AMD, or just as a global).
  • Logging is filtered to "warn" level by default, to keep your live site clean in normal usage (or you can trivially re-enable everything with an initial log.enableAll() call).
  • Magically handles situations where console logging is not initially available (IE8/9), and automatically enables logging as soon as it does become available (when developer console is opened).
  • TypeScript type definitions included, so no need for extra @types packages.
  • Extensible, to add other log redirection, filtering, or formatting functionality, while keeping all the above (except you will clobber your stacktrace, see “Plugins” below).

Downloading loglevel

If you're using NPM, you can just run npm install loglevel.

Alternatively, loglevel is also available via Bower (bower install loglevel), as a Webjar, or an Atmosphere package (for Meteor)

Alternatively if you just want to grab the file yourself, you can download either the current stable production version or the development version directly, or reference it remotely on unpkg at https://unpkg.com/loglevel/dist/loglevel.min.js (this will redirect to a latest version, use the resulting redirected URL if you want to pin that version).

Finally, if you want to tweak loglevel to your own needs or you immediately need the cutting-edge version, clone this repo and see Developing & Contributing below for build instructions.

Setting it up

loglevel supports AMD (e.g. RequireJS), CommonJS (e.g. Node.js) and direct usage (e.g. loading globally with a <script> tag) loading methods. You should be able to do nearly anything, and then skip to the next section anyway and have it work. Just in case, though, here's some specific examples that definitely do the right thing:

CommonsJS (e.g. Node)

var log = require('loglevel');
log.warn("unreasonably simple");

AMD (e.g. RequireJS)

define(['loglevel'], function(log) {
   log.warn("dangerously convenient");
});

Directly in your web page

<script src="loglevel.min.js"></script>
<script>
log.warn("too easy");
</script>

As an ES6 module

loglevel is written as a UMD module, with a single object exported. Unfortunately, ES6 module loaders & transpilers don't all handle this the same way. Some will treat the object as the default export, while others use it as the root exported object. In addition, loglevel includes a default property on the root object, designed to help handle this difference. Nonetheless, there are two possible syntaxes that might work for you:

For most tools, using the default import is the most convenient and flexible option:

import log from 'loglevel';
log.warn("module-tastic");

For some tools though, it might better to wildcard import the whole object:

import * as log from 'loglevel';
log.warn("module-tastic");

There's no major difference, unless you're using TypeScript & building a loglevel plugin (in that case, see #149). In general though, just use whichever suits your environment, and everything should work out fine.

With noConflict()

If you're using another JavaScript library that exposes a log global, you can run into conflicts with loglevel. Similarly to jQuery, you can solve this by putting loglevel into no-conflict mode immediately after it is loaded onto the page. This resets the log global to its value before loglevel was loaded (typically undefined), and returns the loglevel object, which you can then bind to another name yourself.

For example:

<script src="loglevel.min.js"></script>
<script>
var logging = log.noConflict();

logging.warn("still pretty easy");
</script>

TypeScript

loglevel includes its own type definitions, assuming you're using a modern module environment (e.g. Node.JS, webpack, etc), you should be able to use the ES6 syntax above, and everything will work immediately. If not, file a bug!

If you really want to use LogLevel as a global however, but from TypeScript, you'll need to declare it as such first. To do that:

  • Create a loglevel.d.ts file

  • Ensure that file is included in your build (e.g. add it to include in your tsconfig, pass it on the command line, or use ///<reference path="./loglevel.d.ts" />)

  • In that file, add:

    import * as log from 'loglevel';
    export as namespace log;
    export = log;

Documentation

Methods

The loglevel API is extremely minimal. All methods are available on the root loglevel object, which we suggest you name log (this is the default if you import it globally, and is what's set up in the above examples). The API consists of:

Logging Methods

5 actual logging methods, ordered and available as:

  • log.trace(msg)
  • log.debug(msg)
  • log.info(msg)
  • log.warn(msg)
  • log.error(msg)

log.log(msg) is also available, as an alias for log.debug(msg), to improve compatibility with console, and make migration easier.

Exact output formatting of these will depend on the console available in the current context of your application. For example, many environments will include a full stack trace with all trace() calls, and icons or similar to highlight other calls.

These methods should never fail in any environment, even if no console object is currently available, and should always fall back to an available log method even if the specific method called (e.g. warn) isn't available.

Be aware that this means that these methods won't always produce exactly the output you expect in every environment; loglevel only guarantees that these methods will never explode on you, and that it will call the most relevant method it can find, with your argument. For example, log.trace(msg) in Firefox before version 64 prints the stacktrace by itself, and doesn't include your message (see #84).

log.setLevel(level, [persist])

This disables all logging below the given level, so that after a log.setLevel("warn") call log.warn("something") or log.error("something") will output messages, but log.info("something") will not.

This can take either a log level name or 'silent' (which disables everything) in one of a few forms:

  • As a log level from the internal levels list, e.g. log.levels.SILENTfor type safety
  • As a string, like 'error' (case-insensitive) ← for a reasonable practical balance
  • As a numeric index from 0 (trace) to 5 (silent) ← deliciously terse, and more easily programmable (...although, why?)

Where possible, the log level will be persisted. LocalStorage will be used if available, falling back to cookies if not. If neither is available in the current environment (e.g. in Node), or if you pass false as the optional 'persist' second argument, persistence will be skipped.

If log.setLevel() is called when a console object is not available (in IE 8 or 9 before the developer tools have been opened, for example) logging will remain silent until the console becomes available, and then begin logging at the requested level.

log.setDefaultLevel(level)

This sets the current log level only if one has not been persisted and can’t be loaded. This is useful when initializing modules or scripts; if a developer or user has previously called setLevel(), this won’t alter their settings. For example, your application might use setDefaultLevel("error") set the log level to error in a production environment, but when debugging an issue, you might call setLevel("trace") on the console to see all the logs. If that error setting was set using setDefaultLevel(), it will still stay as trace on subsequent page loads and refreshes instead of resetting to error.

The level argument takes the same values that you might pass to setLevel(). Levels set using setDefaultLevel() never persist to subsequent page loads.

log.resetLevel()

This resets the current log level to the logger's default level (if no explicit default was set, then it resets it to the root logger's level, or to WARN) and clears the persisted level if one was previously persisted.

log.enableAll() and log.disableAll()

These enable or disable all log messages, and are equivalent to log.setLevel("trace") and log.setLevel("silent"), respectively.

log.getLevel()

Returns the current logging level, as a number from 0 (trace) to 5 (silent)

It's very unlikely you'll need to use this for normal application logging; it's provided partly to help plugin development, and partly to let you optimize logging code as below, where debug data is only generated if the level is set such that it'll actually be logged. This probably doesn't affect you, unless you've run profiling on your code and you have hard numbers telling you that your log data generation is a real performance problem.

if (log.getLevel() <= log.levels.DEBUG) {
  var logData = runExpensiveDataGeneration();
  log.debug(logData);
}

This notably isn't the right solution to avoid the cost of string concatenation in your logging. Firstly, it's very unlikely that string concatenation in your logging is really an important performance problem. Even if you do genuinely have hard metrics showing that it is, though, the better solution that wrapping your log statements in this is to use multiple arguments, as below. The underlying console API will automatically concatenate these for you if logging is enabled, and if it isn't then all log methods are no-ops, and no concatenation will be done at all.

// Prints 'My concatenated log message'
log.debug("My", "concatenated", "log message");

log.getLogger(loggerName)

This gets you a new logger object that works exactly like the root log object, but can have its level and logging methods set independently. All loggers must have a name (which is a non-empty string, or a Symbol). Calling getLogger() multiple times with the same name will return an identical logger object.

In large applications, it can be incredibly useful to turn logging on and off for particular modules as you are working with them. Using the getLogger() method lets you create a separate logger for each part of your application with its own logging level.

Likewise, for small, independent modules, using a named logger instead of the default root logger allows developers using your module to selectively turn on deep, trace-level logging when trying to debug problems, while logging only errors or silencing logging altogether under normal circumstances.

Example usage (using CommonJS modules, but you could do the same with any module system):

// In module-one.js:
var log = require("loglevel").getLogger("module-one");
function doSomethingAmazing() {
  log.debug("Amazing message from module one.");
}

// In module-two.js:
var log = require("loglevel").getLogger("module-two");
function doSomethingSpecial() {
  log.debug("Special message from module two.");
}

// In your main application module:
var log = require("loglevel");
var moduleOne = require("module-one");
var moduleTwo = require("module-two");
log.getLogger("module-two").setLevel("TRACE");

moduleOne.doSomethingAmazing();
moduleTwo.doSomethingSpecial();
// logs "Special message from module two."
// (but nothing from module one.)

Loggers returned by getLogger() support all the same properties and methods as the default root logger, excepting noConflict() and the getLogger() method itself.

Like the root logger, other loggers can have their logging level saved. If a logger’s level has not been saved, it will inherit the root logger’s level when it is first created. If the root logger’s level changes later, the new level will not affect other loggers that have already been created. Loggers with Symbol names (rather than string names) will always be considered unique instances, and will never have their logging level saved or restored.

Likewise, loggers inherit the root logger’s methodFactory. After creation, each logger can have its methodFactory independently set. See the plugins section below for more about methodFactory.

log.getLoggers()

This will return the dictionary of all loggers created with getLogger(), keyed by their names.

log.rebuild()

Ensure the various logging methods (log.info(), log.warn(), etc.) behave as expected given the currently set logging level and methodFactory. It will also rebuild all child loggers of the logger this was called on.

This is mostly useful for plugin development. When you call log.setLevel() or log.setDefaultLevel(), the logger is rebuilt automatically. However, if you change the logger’s methodFactory, you should use this to rebuild all the logging methods with your new factory.

It is also useful if you change the level of the root logger and want it to affect child loggers that you’ve already created (and have not called someChildLogger.setLevel() or someChildLogger.setDefaultLevel() on). For example:

var childLogger1 = log.getLogger("child1");
childLogger1.getLevel();  // WARN (inherited from the root logger)

var childLogger2 = log.getLogger("child2");
childLogger2.setDefaultLevel("TRACE");
childLogger2.getLevel();  // TRACE

log.setLevel("ERROR");

// At this point, the child loggers have not changed:
childLogger1.getLevel();  // WARN
childLogger2.getLevel();  // TRACE

// To update them:
log.rebuild();
childLogger1.getLevel();  // ERROR (still inheriting from root logger)
childLogger2.getLevel();  // TRACE (no longer inheriting because `.setDefaultLevel() was called`)

Plugins

Existing plugins

loglevel-plugin-prefix - plugin for loglevel message prefixing.

loglevel-plugin-remote - plugin for sending loglevel messages to a remote log server.

loglevel-serverSend - Forward your log messages to a remote server.

loglevel-debug - Control logging from a DEBUG environmental variable (similar to the classic Debug module).

Writing plugins

Loglevel provides a simple, reliable, minimal base for console logging that works everywhere. This means it doesn't include lots of fancy functionality that might be useful in some cases, such as log formatting and redirection (e.g. also sending log messages to a server over AJAX)

Including that would increase the size and complexity of the library, but more importantly would remove stacktrace information. Currently log methods are either disabled, or enabled with directly bound versions of the console.log methods (where possible). This means your browser shows the log message as coming from your code at the call to log.info("message!") not from within loglevel, since it really calls the bound console method directly, without indirection. The indirection required to dynamically format, further filter, or redirect log messages would stop this.

There's clearly enough enthusiasm for this even at that cost that loglevel now includes a plugin API. To use it, redefine log.methodFactory(methodName, logLevel, loggerName) with a function of your own. This will be called for each enabled method each time the level is set (including initially), and should return a function to be used for the given log method methodName, at the given configured (not actual) level logLevel, for a logger with the given name loggerName. If you'd like to retain all the reliability and features of loglevel, we recommended that you wrap the initially provided value of log.methodFactory.

For example, a plugin to prefix all log messages with "Newsflash: " would look like:

var originalFactory = log.methodFactory;
log.methodFactory = function (methodName, logLevel, loggerName) {
    var rawMethod = originalFactory(methodName, logLevel, loggerName);

    return function (message) {
        rawMethod("Newsflash: " + message);
    };
};
log.rebuild(); // Be sure to call the rebuild method in order to apply plugin.

(The above supports only a single string log.warn("...") argument for clarity, but it's easy to extend to a fuller variadic version.)

If you develop and release a plugin, please get in contact! I'd be happy to reference it here for future users. Some consistency is helpful; naming your plugin 'loglevel-PLUGINNAME' (e.g. loglevel-newsflash) is preferred, as is giving it the 'loglevel-plugin' keyword in your package.json.

Developing & Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality.

Builds can be run with npm: run npm run dist to build a distributable version of the project (in dist/), or npm test to just run the tests and linting. During development you can run npm run watch and it will monitor source files, and rerun the tests and linting as appropriate when they're changed.

Also, please don't manually edit files in the dist/ subdirectory as they are generated via Grunt. You'll find source code in the lib/ subdirectory!

Release process

To do a release of loglevel:

  • Update the version number in package.json and bower.json.
  • Run npm run dist to build a distributable version in dist/.
  • Update the release history in this file (below).
  • Commit the built code, tagging it with the version number and a brief message about the release.
  • Push to Github.
  • Run npm publish . to publish to NPM.

Release History

v0.1.0 - First working release with apparent compatibility with everything tested

v0.2.0 - Updated release with various tweaks and polish and real proper documentation attached

v0.3.0 - Some bugfixes (#12, #14), cookie-based log level persistence, doc tweaks, support for Bower and JamJS

v0.3.1 - Fixed incorrect text in release build banner, various other minor tweaks

v0.4.0 - Use LocalStorage for level persistence if available, compatibility improvements for IE, improved error messages, multi-environment tests

v0.5.0 - Fix for Modernizr+IE8 issues, improved setLevel error handling, support for auto-activation of desired logging when console eventually turns up in IE8

v0.6.0 - Handle logging in Safari private browsing mode (#33), fix TRACE level persistence bug (#35), plus various minor tweaks

v1.0.0 - Official stable release! Fixed a bug with localStorage in Android webviews, improved CommonJS detection, and added noConflict().

v1.1.0 - Added support for including loglevel with preprocessing and .apply() (#50), and fixed QUnit dep version which made tests potentially unstable.

v1.2.0 - New plugin API! Plus various bits of refactoring and tidy up, nicely simplifying things and trimming the size down.

v1.3.0 - Make persistence optional in setLevel(), plus lots of documentation updates and other small tweaks

v1.3.1 - With the new optional persistence, stop unnecessarily persisting the initially set default level (WARN)

v1.4.0 - Add getLevel(), setDefaultLevel() and getLogger() functionality for more fine-grained log level control

v1.4.1 - Reorder UMD (#92) to improve bundling tool compatibility

v1.5.0 - Fix log.debug (#111) after V8 changes deprecating console.debug, check for window upfront (#104), and add .log alias for .debug (#64)

v1.5.1 - Fix bug (#112) in level-persistence cookie fallback, which failed if it wasn't the first cookie present

v1.6.0 - Add a name property to loggers and add log.getLoggers() (#114), and recommend unpkg as CDN instead of CDNJS.

v1.6.1 - Various small documentation & test updates

v1.6.2 - Include TypeScript type definitions in the package itself

v1.6.3 - Avoid TypeScript type conflicts with other global log types (e.g. core-js)

v1.6.4 - Ensure package.json's "main" is a fully qualified path, to fix webpack issues

v1.6.5 - Ensure the provided message is included when calling trace() in IE11

v1.6.6 - Fix bugs in v1.6.5, which caused issues in node.js & IE < 9

v1.6.7 - Fix a bug in environments with window defined but no window.navigator

v1.6.8 - Update TypeScript type definitions to include log.log().

v1.7.0 - Add support for Symbol-named loggers, and a .default property to help with ES6 module usage.

v1.7.1 - Update TypeScript types to support Symbol-named loggers.

v1.8.0 - Add resetLevel() method to clear persisted levels & reset to defaults

v1.8.1 - Fix incorrect type definitions for MethodFactory

v1.9.0 - Added rebuild() method, overhaul dev & test setup, and fix some bugs (notably around cookies) en route

v1.9.1 - Fix a bug introduced in 1.9.0 that broke setLevel() in some ESM-focused runtime environments

loglevel for enterprise

Available as part of the Tidelift Subscription.

The maintainers of loglevel and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.

License

Copyright (c) 2013 Tim Perry Licensed under the MIT license. See LICENSE-MIT for full license text.

loglevel's People

Contributors

0xflotus avatar binhqx avatar bitdeli-chef avatar bladeski avatar bxd201 avatar byk avatar cederberg avatar ericboucher avatar frederickfogerty avatar giannif avatar grizio avatar illandril avatar iwilsonv avatar kutuluk avatar madarche avatar maihde avatar medhajjej11 avatar mje-nz avatar mr0grog avatar nordstrand avatar phated avatar pimterry avatar smallhadroncollider avatar th-kjohnson avatar timgates42 avatar tityron avatar xmedeko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

loglevel's Issues

logger doesn't work in IE 8

Hey,

we wanted to use your implementation to log error messages in our webapps. Unfortunaltelly IE 8 doesn't log any messages. If I open IE Dev Tools, it adds the console to the main scope.

None the less it seems like your lib thinks there is no console object available.

I tried to open Dev Tools and reload the page, but no luck.

Here's a little snippet:

<html>

<head>
    <script src="loglevel.js"></script>
    <script>
        (function(w){
            log.setLevel(0);
            log.error(w,"too easy");
        }(this));
    </script>
</head>
</html>

Find a way to automatically test with IE developer tools etc open

Current tests do a sanity check to ensure that nothing explodes when the console is used normally. This needs to be extended to ensure that it also works after the developer console has been opened, if possible, since things like the IE dev console add a console object to the global env once they've been opened.

Custom logger methods (created with factory) are not muted when SILENT level is set

In this case:

var logger = log.noConflict();

logger.log = logger.methodFactory('log', logger.levels.DEBUG);
logger.setLevel(app.config.debug === true ? logger.levels.TRACE : logger.levels.SILENT);

Calling logger.log('Something') will output data even if app.config.debug === true because in setLevel() you're calling replaceLoggingMethods() which iterates only logMethods and that array is not updated when calling methodFactory(). In other words: every method created with factory will always output data to console.

For now I use:

logger.log = app.config.debug === true ? logger.methodFactory('log', logger.levels.DEBUG) : function() {};

But it's not proper solution.

Record of log

Is there any way to send the error message simultaneously to a variable for generating a bug report?

Redirection of log messages

I don't know if it is outside the scope of this library, but I would like to use loglevel to redirect log messages of a level to, say, an error reporting endpoint.

Something like:

require(['loglevel'], function(log) {
  log.setLevel("warn");
  log.redirect( function(message) {
    var report = new XMLHttpRequest();
    report.open("post", "/endpoint");
    report.send(message);
  });

  log.error("foobar");
});

Get some hard numbers on exactly how far back browser support & testing goes

The tests currently check loglevel works in everything from IE6+/FF3.6+/every Chrome I can find/current android/current iDevice/current Opera/current Safari/current Node. It'd be good to check how far further back compatibility goes though, and have that visible upfront.

Main constraints is the test suite, which uses a Jasmine runner that breaks in FF<3.6 & IE <9, at least. Loglevel otherwise is ES3 compatible, plus console, and is very very cautious about how it uses the console to make it work regardless.

Add support for formatters and args

Having support for formatters and args (similar to console.log) would be nice.

For example;

  MyLogger = new log2();
  MyLogger.formatter = function(level, msg, args) {
      var ts = new Date().toLocaleTimeString();
      if (args) {
        msg = msg + " " + args.join(" ");
      }
      return sprintf("[JS] [%s] [%s] %s", ts, level, msg);
  }
  MyLogger.trace("lol", 2, 3, 4);
  MyLogger.debug("lol", 2, 3, 4);
  MyLogger.info("lol", 2, 3, 4);
  MyLogger.warn("lol", 2, 3, 4);
  MyLogger.error("lol", 2, 3, 4);

This results in;

[JS] [18:11:06] [trace] lol                                               all.min.js:6079
trace all.min.js:6079
(anonymous function)                                                      all.min.js:6115
j all.min.js:2
k.fireWith all.min.js:2
m.extend.ready all.min.js:2
J all.min.js:2
[JS] [18:11:06] [debug] lol 2 3 4                                         all.min.js:6085
[JS] [18:11:06] [info] lol 2 3 4                                          all.min.js:6091
[JS] [18:11:06] [warn] lol 2 3 4                                          all.min.js:6097
[JS] [18:11:06] [error] lol 2 3 4 

I was able to achieve this with a wrapper, but it'd be nice to have something similar in the core;


  var log2 = function() {
    this.formatter = function(level, msg, args) {
      if (args) {
        msg = msg + " " + args.join(" ");
      }
      return msg;
    }

    this.trace = function(msg) {
      var fmsg = this.formatter('trace', msg);
      log.trace(fmsg);
    }

    this.debug = function(msg) {
      args = Array.prototype.slice.call(arguments, 1);
      var fmsg = this.formatter('debug', msg, args);
      log.debug(fmsg);
    }

    this.info = function(msg) {
      args = Array.prototype.slice.call(arguments, 1);
      var fmsg = this.formatter('info', msg, args);
      log.info(fmsg);
    }

    this.warn = function(msg) {
      args = Array.prototype.slice.call(arguments, 1);
      var fmsg = this.formatter('warn', msg, args);
      log.warn(fmsg);
    }

    this.error = function(msg) {
      args = Array.prototype.slice.call(arguments, 1);
      var fmsg = this.formatter('error', msg, args);
      log.error(fmsg);
    }
  }

Happy to send a PR with a real patch if something like this would get accepted.

I've only tested this in browser btw.

Supporting multiple loggers

Hey,

In large projects it is extremely useful to have the flexibility of defining different log levels for different modules / subsystems / files / objects, especially during debugging or bug chasing, in order to only see debug and trace log levels for a specific object / module. I have already implemented something like that in our wrapped loglevel meteor package:

https://github.com/practicalmeteor/meteor-loglevel

It also gave me the flexibility to define log prefixes that maintain line numbers (pushing the prefix as the first argument to apply), which, I suspect, is one of the more asked for features.

Will you accept a PR that allows to create new loglevel() objects? Regarding persistence, the constructor can receive an options object that include a namespace string that will be used to load the log level for that namespace. It can also accept a prefix option and even a map of custom log levels to console log methods.

Missing 'log' method to serve as a drop-in replacement for 'console'

I'd like to replace all console.* calls to loglevel.* calls but I discovered that there is no log method which is widely used with console. The info method does not fit well because the browser console highlights the info message with an icon making these messages somewhat more specific than default logging.

Any chance adding log?

New NPM release?

Hey - love the library!

I'd like to take advantage of the new setDefaultLevel() method -- any chance we can get a new release on npm soon with that functionality?

Thanks 👍

Add option to choose whether requirejs is used or not

I'll admit this is a bit of an edge case:

We have a JavaScript library which we're loading on our clients sites. We don't control our clients sites, but do control ours (of course).

We recently added loglevel to our library to help with diagnosing issues, and found that it works great (thx!), except on one client who uses RequireJS. Our workaround was to therefore strip out the bit of loglevel that adds requirejs, amd and so forth. Our log level now starts:

!function(a,b){a.log=b()}(this ....

Instead of:

 !function(a,b){"object"==typeof module&&module.exports&&"function"==typeof require?module.exports=b():"function"==typeof define&&"object"==typeof define.amd?define(b):a.log=b()}(this ....

It would therefore be useful for us to disable the "load via RequireJS/AMD/etc" feature (in favour of loading 'normally') via a flag or something. Open to suggestions!

Thanks!

Plugin functionality not working

I've tried copying the 'Newsflash' example to this jsbin - http://jsbin.com/cupig/1/edit?html,js,console,output and it doesn't seem to be working.

var originalFactory = log.methodFactory;
log.methodFactory = function (methodName, logLevel) {

    console.log(methodName, ':', logLevel);
    var rawMethod = originalFactory(methodName, level);

    return function (message) {
        rawMethod("Newsflash: " + message);
    };
};

var msg = "Horray!";
log.setLevel("info");

log.trace(msg);
log.debug(msg);
log.info(msg);
log.warn(msg);
log.error(msg);

From what I can tell, the methodFactory is not being called at all.

Get current logging level.

For some operations it is good to know the current logging level.

For example, if you do string concatenation in your logging statements that are in sections of code that get called a lot, Javascript does the relatively-expensive string concatenation even if the current logging level won't actually output the string.

I think something like log.getLevel() would be useful so you could do the expensive operation only when needed.

loglevel doesn't play nice with modernizr on ie8

modernizr introduces the bind method to Function.prototype in IE8 which then throws errors when loglevel library is loaded. this seems to happen because in IE8 methods like console.log and console.error have types object (i.e. "typeof console.log === 'object' and typeof console.log !== 'function').

Add tests for library setup

#14 is a bug in loglevel loading when it's used globally. The integration tests should be extended as smoke tests for each import method to catch stuff like this.

Improve the methodFactory API (stop exposing the field directly, and make it easier to use)

It would be better to set the method factory with a setMethodFactory() method or similar that sets the method factory and automatically rebuilds all the methods when set, rather than just having the public property currently exposed.

This should mean that:

a) people don't need to remember to set the level after changing the method factory to apply their changes

b) the API is clearer, and there's no suggestion that people should ever be calling method factory themselves (see #80 (comment))

Note that this would be a backward compatibility breaking change: we should think about whether we can easily deprecate .methodFactory but support both for a little while, or whether that's going to be enough hassle that we should just drop it and jump to 2.0 (I suspect the latter, but the former would be nice).

Add A Hook For Logging to the Server

I think this library looks great. We just want something where everytime you get a certain level of errors we POST those to the server. Any suggestions on how to do that? Maybe we can put it in an eventEmitter and say something like.

loglevel.on("critical", function() {
   // i do my own AJAX logic
});

I'm happy to work on a pull request to support that functionality

Ability to set level only if one is not persisted

In environments where a logging level has been explicitly set and persisted (usually a developer’s browser), it’d be nice to be able to leave the logging level alone, while otherwise giving a default logging level to use if one hasn’t been persisted. The only way to accomplish this right now is to explicitly peek into local storage or cookies to see if a value is set, which isn’t very nice.

I’m thinking this could either be a third argument to setLevel or, probably clearer, a separate method, e.g. setDefaultLevel.

Should be able to redirect logging through custom external logging mechanisms

See #29 (comment)

Loglevel is not going to gain appender-style functionality, with pluggable redirectors or similar because that's quite heavyweight and there are other big heavyweight logging projects which already do that (e.g. http://log4javascript.org/).

The current log method setup does internally use replaceLoggingMethods(logMethodFactory) though, with different factories depending on whether all logging is silent/fallback from missing consoles is required/log methods should be built bound to the console and with a little bit of tweaking it should be possible to add an API (something like log.setLogMethodFactory(f)), to which you can pass a function similar to those currently given to replaceLoggingMethods(). That would be a very small change to loglevel itself, to just expose optional override functionality, but allow people to implement their own appender functionality attached to loglevel if required.

It is really necessary to create and destroy methods?

Hi

I notice that you create and destroy the methods on the fly. Or something like.
The thing is that doing this prevents me from being able to do something like this:

APP.logger.log = log.info.bind(log);

Meaning I am able to abstract your library just in case we need to switch it later.

This works, buts looks unnecessary:

function info(msg) {
    log.info(msg);  
}

APP.logger.log = info;

Thanks

console.group?

Really great utility. Well done. I wonder if there are any plans to support the group method?

loglevel cannot be used with qunit

I have a JavaScript project where I wish to use loglevel without AMD or RequireJS. It works fine until I attempt to run my QUnit tests. The first problem is that QUnit declares it's own global log() method, the second is that QUnit also declares a global module object so loglevel goes into the RequireJS initialization path, finally when Qunit is loading <script> elements the window element is still undefined.

I've worked around both by modifying loglevel to explicitly rename the log and bind it to window...but this is definitely not a general solution that will work for others. Thoughts?

Plugin example from readme doesn't work

Hi, thank you for your project.

Maybe I'm missing something but I cannot get your example plugin from readme working. It should add prefix for each log level, but at the end it does nothing. Here jsfiddle

Doesn't work in latest Chrome

Any interest in stubbing/passingthrough other console methods?

I'd like to use a single consistent API to call other methods like console.time or console.table But I don't want those methods to fail in old browsers, and I don't want to litter my code with checks to see what's supported everywhere. So I'm interested in adding something like this (from Ben Alman's debug lib). If not here, I'll just fork loglevel and add it for just me :)

// Pass these methods through to the console if they exist, otherwise just
// fail gracefully. These methods are provided for convenience.
pass_methods = 'assert clear count dir dirxml exception group groupCollapsed groupEnd profile profileEnd table time timeEnd trace'.split(' '),
idx = pass_methods.length,

while (--idx >= 0) {
  (function (method) {

      // Generate pass-through methods. These methods will be called, if they
      // exist, as long as the logging level is non-zero.
      that[method] = function () {
          log_level !== 0 && con && con[method]
            && con[method].apply(con, arguments);
      }

  })(pass_methods[idx]);
}

Thoughts?

Add Prefix

Hi,

Could it be possible to get prefix keywording implemented ?
for example:

log.info("Hello World"); //Output "Hello World"
log.setPrefix("MyPrefix");
log.info("Hello World"); //Output "[MyPrefix]Hello World"

Thanks

PS: @pimterry Great Job!

Quick correction for browser

Too small for a pull request. To work in the browser this line has to be changed:

# currently
this.name = definition()

# should be
this[name] = definition();

Thanks for the library. Exactly what I was looking for!

ReferenceError when using directly in web page

When using v0.1.0 directly in my web page, I'm receiving "ReferenceError: log is not defined". I changed line 10 from:

this.name = definition();

to:

this[name] = definition();

and it worked.

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.