From 2cfa96262a44be9f426b422b8570ba3d9ca2b37f Mon Sep 17 00:00:00 2001 From: Stijn de Witt Date: Sat, 23 Dec 2017 19:58:53 +0100 Subject: [PATCH] 1.1.0: Support configuration via localStorage --- README.md | 104 +++++++++++++++++++++++++++++++----------------- browser.js | 5 +++ package.json | 2 +- ulog.js | 18 ++++----- ulog.min.js | 2 +- ulog.min.js.zip | Bin 1074 -> 0 bytes ulog.spec.js | 5 ++- ulog.umd.js | 23 ++++++----- 8 files changed, 99 insertions(+), 60 deletions(-) delete mode 100644 ulog.min.js.zip 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|PXG6o+`2jypPn@fHTdJRD zbHn`JjrY#}`!i+UCW)ZAt*-8W!z}%7-OAyxPjBVi%BOZNy7lAa$+b)(#akaluU4-M zTVnUR-GV3Ra`U-zf!}@1_Y}M$w$GM4!ZE4zxd3y@Q9cE+(??_cCZCGfb^h&=xf-@7 zC70x?70XQexG1$hi06TQ#N~#s`wh5OCi0s;Z0G&)L+k6u8~0We8SPbFI%{Qw`$Vz5 z^~djS-JQrDdhuYmSLTI&P0Jef0BehuD>*k7beC;s>vlJIQEA(Jg(Kh2bjG#QcNkM6 zYwo3V)~YQJ{PJYx76}K>(^h-VDJ%b(md0o)rv5;0#&Xv#dCAvS$7&Ng3snLi-ktKm z<;KU1i;u4IHEEu?zHO&ob7joDvZCh`^ePuFKfXA1R_CD?O5c_8XZ;dC+IQ;hvb&An z_|{L4+Oc-k24|sqo22&<*>4`)N^eu$H|0w3S-$03TK7(U-+8|)_TS_zK`W&$gNAe0 zO{XkwZ7td}YyXcg&njeIA38qsBUiPP=k&11pu2Yr=C1MyJD*~`dE-K^!oTi1y`i_< z17{fA*WRMgWuW|1(Oa&m*Win2!nN275_c@iEx#7^TxfT=D$^ggAYw*@cI+Yx~>iliF<~+Kr|vyo0q>#}p)3%>8Wvvd1Hmpd~BkDZKFad)yho7S5VwSB2noln?? zng4S%etP9O>?rGHTK@ee?@nKd?$iH&^X^X8dmeVQ`zCA1PyJP^@63LEXXD@56SlI8 zryQu7w|?*G{d-Q=@6Gq!9VfL;{mYai0fG-aQjE%!)>oV@uAH$x>~v_&{QA0mQAhZH z+&=m`_0NR;(fc~(KknmweEiSjS3gfz{$aV#Zn@9m{=?~uEf4$Uy zh27$Fd8c~F+iwN?OfS)Stq0Wam+SoG4e(}UvS+}RfmMK67z7l+BuaMXf(kM+NH91} k4qEU){1T&KevR#YBs##G6<7{1FfamPERfz0EEyOW05?(b8~^|S diff --git a/ulog.spec.js b/ulog.spec.js index 32c860f..50a619a 100644 --- a/ulog.spec.js +++ b/ulog.spec.js @@ -56,6 +56,10 @@ describe('log', function(){ expect(log.assert).to.be.a('function') }) + it('has a method `assert` that does not throw', function(){ + expect(function(){log.assert(false, 'assert does not throw')}).to.not.throw() + }) + it('has an additional logging method named `debug`', function(){ expect(log).to.have.a.property('debug') expect(log.debug).to.be.a('function') @@ -238,7 +242,6 @@ describe('log', function(){ testConsole.reset() }) - it('has a method `enabled`', function(){ expect(log).to.have.a.property('enabled') expect(log.enabled).to.be.a('function') diff --git a/ulog.umd.js b/ulog.umd.js index 1c28e45..846d354 100644 --- a/ulog.umd.js +++ b/ulog.umd.js @@ -5,7 +5,7 @@ })(this, 'ulog', function(){'use strict' // 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){ @@ -14,7 +14,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,]+/); @@ -58,10 +58,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)} } @@ -76,12 +78,7 @@ function patch(o) { : ( bnd(name) || (typeof print == 'function' && print) || - function(){ - if (log.con()) { - patch(o) - o[name].apply(o, arguments) - } - } + nop ) } } @@ -90,10 +87,16 @@ function bnd(n,c){return (c = log.con()) && (c[n]||c.log).bind(c)} function nop(){} + 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