diff --git a/README.md b/README.md index adad204..2492d6b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ulog v1.0.3 +# ulog v1.1.0 ### Microscopically small universal logging library [![npm](https://img.shields.io/npm/v/ulog.svg)](https://npmjs.com/package/ulog) @@ -9,16 +9,18 @@ . -![logo](https://cdn.rawgit.com/download/ulog/0.1.0/ulog.png) +![logo](https://cdn.rawgit.com/download/ulog/1.0.0/ulog.png) -Ulog builds on the experience gained building and using [Picolog](https://npmjs.com/package/picolog), -possibly the smallest universal logging library on NPM that supports levels, and adds some features -from [debug](https://npmjs.com/package/debug) that I missed. Even with these extra features, ulog is -still **very** small, weighing in just over 1 kB minified and gzipped. +Ulog builds on the experience gained building and using +[Picolog](https://npmjs.com/package/picolog), possibly the smallest +universal logging library on NPM that supports levels, and adds some +features from [debug](https://npmjs.com/package/debug) that I missed. +Even with these extra features, ulog is still **very** small, weighing +in just over 1 kB minified and gzipped. ## Download -* [ulog.umd.js](https://cdn.rawgit.com/download/ulog/1.0.3/ulog.umd.js) (~3kB, source) -* [ulog.min.js](https://cdn.rawgit.com/download/ulog/1.0.3/ulog.min.js) (~2kB, minified) +* [ulog.umd.js](https://cdn.rawgit.com/download/ulog/1.1.0/ulog.umd.js) (~3kB, source) +* [ulog.min.js](https://cdn.rawgit.com/download/ulog/1.1.0/ulog.min.js) (~2kB, minified) ## Install ```sh @@ -53,7 +55,7 @@ define(['ulog'], function(ulog){ ### Script tag ```html - + ``` ## Logging methods @@ -66,8 +68,8 @@ log.log('This logs a LOG message') log.debug('This logs a DEBUG message') log.trace('This logs a TRACE message') ``` -ulog does **not** mess with your stacktrace or line numbers. Line numbers shown in the console -will be from your code, not from some wrapper function.. +ulog does **not** mess with your stacktrace or line numbers. Line numbers shown +in the console will be from your code, not from some wrapper function.. ## Logging levels ulog defines 6 logging levels, which correspond with the available logging methods: @@ -95,23 +97,25 @@ log.level = log.NONE log.error('Logging is completely disabled.') ``` - ## Default log level -I've found that it makes sense to have different default log levels in the browser -and in Node. In Node, logging is often the only UI we have available and we (the devs) -are the only ones that will see that logging. In the browser, we have an alternative -UI (the webpage itself), so logging will be less useful for normal users. +I've found that it makes sense to have different default log levels in +the browser and in Node. In Node, logging is often the only UI we have +available and we (the devs) are the only ones that will see that logging. +In the browser, we have an alternative UI (the webpage itself), so +logging will be less useful for normal users. ### In Node -In Node, the log level defaults to `log.INFO`. This allows you to use INFO, WARN and ERROR -when informing the user of stuff that happened. With Picolog I found I had to resort -to logging informational messages at WARN because I wanted them to be visible with the -default settings and this did not feel right. +In Node, the log level defaults to `log.INFO`. This allows you to use +INFO, WARN and ERROR when informing the user of stuff that happened. +With Picolog I found I had to resort to logging informational messages +at WARN because I wanted them to be visible with the default settings +and this did not feel right. ### In the browser -In the browser the log level defaults to `log.WARN`. This means INFO messages will be excluded, -but for most users these messages won't be relevant anyway and we can easily change the -log level in the browser using a query parameter in the URL (see next section). +In the browser the log level defaults to `log.WARN`. This means INFO +messages will be excluded, but for most users these messages won't be +relevant anyway and we can easily change the log level in the browser +using a query parameter in the URL or localStorage (see next section). ## Changing the log level Changing the log level can be done in two ways: @@ -134,8 +138,9 @@ log.level = ulog.DEBUG ``` ### Changing the log level via a startup parameter -We can set the initial global log level with a startup parameter. In Node we use -an environment variable, whereas in the browser we use a querystring parameter in the url. +We can set the initial global log level with a startup parameter. In +Node we use an environment variable, whereas in the browser we use a +querystring parameter in the url or a key in localStorage. #### Environment variable Set the environment variable `LOG` to the desired log level. @@ -156,6 +161,16 @@ Add the parameter `log` to the querystring of the page: Both the uppercase and lowercase names of the log levels work, as well as their numerical value. +#### localStorage key +Add the key `log` to the localStorage of the page: +```js +localStorage.setItem('log', 'info') +``` +then refresh the page. + +Both the uppercase and lowercase names of the log levels work, +as well as their numerical value. + ## Debug mode In addition to setting the global log level and setting the log levels of individual loggers, you can also enable debug mode for a group of loggers. @@ -193,7 +208,8 @@ ulog.enabled('app') // false ``` ### Enabling debug mode via a startup parameter We can enable debug mode for some loggers using a startup parameter. On Node -we use environment variables and on the browser we use querystring parameters. +we use environment variables and on the browser we use querystring parameters +or localStorage keys. #### Environment variable Set the environment variable `DEBUG` to the string with logger names: @@ -211,6 +227,13 @@ Add the parameter `debug` to the querystring of the page: `http://www.example.com/?`**`debug=my-module`** +#### localStorage key +Add the key `debug` to the localStorage of the page: +```js +localStorage.setItem('debug', 'my-module') +``` +then refresh the page. + ## Using ulog as a polyfill ulog supports all functions in the [NodeJS Console API](https://nodejs.org/api/console.html), so you should be able to use it as a polyfill in environments where there is no `console` available (e.g. Nashorn): @@ -220,12 +243,19 @@ global.console = log; console.info('Nashorn can do logging to!'); ``` +## assert does not throw +ulog patches the [different behavior](https://github.com/jasnell/node/blob/master/doc/api/console.md#consoleassertvalue-message-args) +of `console.assert` in Node compared to browsers. +In ulog, `assert` behaves just like in the browsers and never throws. + ## Performance considerations -The logging methods on the `log` object that correspond to a log level which is higher than the -currently set level, are replaced by no-op methods. As such, you generally don't have to worry -about the performance overhead of leaving the log statements in the production code. There is -one exception to this rule though. If preparing the message itself is a costly operation, you -may want to surround the log code with an `if (log.level >= myLevel)` statement: +The logging methods on the `log` object that correspond to a log +level which is higher than the currently set level, are replaced +by no-op methods. As such, you generally don't have to worry about +the performance overhead of leaving the log statements in the +production code. There is one exception to this rule though. If +preparing the message itself is a costly operation, you may want +to surround the log code with an `if (log.level >= myLevel)` statement: ```js if (log.level >= log.INFO) { var message = doLotsOfWorkToGenerateLogMessage(); @@ -234,18 +264,18 @@ if (log.level >= log.INFO) { ``` ## Issues -Add an issue in this project's [issue tracker](https://github.com/download/ulog/issues) +Add an issue in the [issue tracker](https://github.com/download/ulog/issues) to let me know of any problems you find, or questions you may have. ## Credits Credits go to: -* Felix Geisendörfer from [debuggable.com](http://debuggable.com/) for kindly giving up - the `ulog` namespace on NPM. Thanks Felix! -* TJ Holowaychuk for creating [debug](https://github.com/visionmedia/debug), which was - a great inspiration for ulog. +* Felix Geisendörfer from [debuggable.com](http://debuggable.com/) for kindly + giving up the `ulog` namespace on NPM. Thanks Felix! +* TJ Holowaychuk for creating [debug](https://github.com/visionmedia/debug), + which was a great inspiration for ulog. ## Copyright -Copyright 2016 by [Stijn de Witt](http://StijnDeWitt.com). Some rights reserved. +Copyright 2017 by [Stijn de Witt](http://StijnDeWitt.com). Some rights reserved. ## License Licensed under the [Creative Commons Attribution 4.0 International (CC-BY-4.0)](https://creativecommons.org/licenses/by/4.0/) Open Source license. diff --git a/browser.js b/browser.js index 8e43068..2a63fc8 100644 --- a/browser.js +++ b/browser.js @@ -3,6 +3,11 @@ var qs = location.search.substring(1), args = qs && qs.split('&'), lvl, dbg, i, m +try { + lvl = localStorage.getItem('log') + dbg = localStorage.getItem('debug') +} catch(e) {} + for (i=0; m=args && args[i] && args[i].split('='); i++) { m[0] == 'log' ? lvl = m[1] : 0 m[0] == 'debug' ? dbg = m[1] : 0 diff --git a/package.json b/package.json index 6c1e10a..2bbebca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ulog", - "version": "1.0.3", + "version": "1.1.0", "description": "Microscopically small universal logging library", "main": "node.js", "browser": "browser.js", diff --git a/ulog.js b/ulog.js index 83f88ae..80417f3 100644 --- a/ulog.js +++ b/ulog.js @@ -1,6 +1,6 @@ // ulog - microscopically small universal logging library -// © 2016 by Stijn de Witt, some rights reserved +// © 2017 by Stijn de Witt, some rights reserved // License: CC-BY-4.0 function log(name){ @@ -9,7 +9,7 @@ function log(name){ : (log.debug ? log : enhance(log)) } -log.ulog = {version:'1.0.3'} +log.ulog = {version:'1.1.0'} log.enable = function(str) { var i, split = (str || '').split(/[\s,]+/); @@ -53,10 +53,12 @@ function enhance(o, parent, level) { } }) patch(o, parent) - o.dir = bnd('dir') || nop + o.dir = bnd('dir') || nop + o.table = bnd('table') || nop o.time = bnd('time') || nop o.timeEnd = bnd('timeEnd') || nop - o.assert = function(){ + // makes Node behave like browsers + o.assert = typeof window == 'object' && bnd('assert') || function(){ var a=[].concat.apply([], arguments), ok=a.shift() if (!ok) {o.error.apply(o, a)} } @@ -71,16 +73,12 @@ function patch(o) { : ( bnd(name) || (typeof print == 'function' && print) || - function(){ - if (log.con()) { - patch(o) - o[name].apply(o, arguments) - } - } + nop ) } } function bnd(n,c){return (c = log.con()) && (c[n]||c.log).bind(c)} function nop(){} + module.exports = log diff --git a/ulog.min.js b/ulog.min.js index 94b736a..7eaf05f 100644 --- a/ulog.min.js +++ b/ulog.min.js @@ -1 +1 @@ -!function(e,n,t){"function"==typeof define&&define.amd?define(n,[],t):"object"==typeof module&&module.exports?module.exports=t():e[n]=t()}(this,"ulog",function(){"use strict";function e(t){return t?s[t]?s[t]:s[t]=n({name:t},e):e.debug?e:n(e)}function n(e,n,i){e.NONE=0;for(var u in a)e[u]=a[u];return Object.defineProperty(e,"level",{get:function(){return void 0!==i?i:n&&n.level},set:function(o){if(void 0===o&&n)i=void 0;else{var r=o&&(Number(o)!==Number(o)?e[o.toUpperCase()]:Number(o));r>=0&&r<=6&&(i=r)}if(t(e),!n)for(mod in s)t(s[mod])}}),t(e,n),e.dir=o("dir")||r,e.time=o("time")||r,e.timeEnd=o("timeEnd")||r,e.assert=function(){var n=[].concat.apply([],arguments);n.shift()||e.error.apply(e,n)},e}function t(n){for(var i,u=Math.max(n.name&&e.enabled(n.name)&&n.DEBUG||n.level,n.level),f=0;i=c[f];f++)n[i]=u<=f?r:o(i)||"function"==typeof print&&print||function(){e.con()&&(t(n),n[i].apply(n,arguments))}}function o(n,t){return(t=e.con())&&(t[n]||t.log).bind(t)}function r(){}e.ulog={version:"1.0.3"},e.enable=function(e){var n,o=(e||"").split(/[\s,]+/);for(n=0;n=0&&r<=6&&(i=r)}if(t(e),!n)for(mod in s)t(s[mod])}}),t(e),e.dir=o("dir")||r,e.table=o("table")||r,e.time=o("time")||r,e.timeEnd=o("timeEnd")||r,e.assert="object"==typeof window&&o("assert")||function(){var n=[].concat.apply([],arguments);n.shift()||e.error.apply(e,n)},e}function t(n){for(var t,i=Math.max(n.name&&e.enabled(n.name)&&n.DEBUG||n.level,n.level),l=0;t=c[l];l++)n[t]=i<=l?r:o(t)||"function"==typeof print&&print||r}function o(n,t){return(t=e.con())&&(t[n]||t.log).bind(t)}function r(){}e.ulog={version:"1.1.0"},e.enable=function(e){var n,o=(e||"").split(/[\s,]+/);for(n=0;n