Skip to content

Commit

Permalink
1.1.0: Support configuration via localStorage
Browse files Browse the repository at this point in the history
  • Loading branch information
Download committed Dec 23, 2017
1 parent 2332d9e commit 2cfa962
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 60 deletions.
104 changes: 67 additions & 37 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# ulog <sub><sup>v1.0.3</sup></sub>
# ulog <sub><sup>v1.1.0</sup></sub>
### Microscopically small universal logging library

[![npm](https://img.shields.io/npm/v/ulog.svg)](https://npmjs.com/package/ulog)
Expand All @@ -9,16 +9,18 @@

<sup><sub><sup><sub>.</sub></sup></sub></sup>

![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
Expand Down Expand Up @@ -53,7 +55,7 @@ define(['ulog'], function(ulog){

### Script tag
```html
<script src="https://cdn.rawgit.com/download/ulog/1.0.3/ulog.min.js"></script>
<script src="https://cdn.rawgit.com/download/ulog/1.1.0/ulog.min.js"></script>
```

## Logging methods
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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:
Expand All @@ -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):
Expand All @@ -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();
Expand All @@ -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.
5 changes: 5 additions & 0 deletions browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
18 changes: 8 additions & 10 deletions ulog.js
Original file line number Diff line number Diff line change
@@ -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){
Expand All @@ -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,]+/);
Expand Down Expand Up @@ -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)}
}
Expand All @@ -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
2 changes: 1 addition & 1 deletion ulog.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file removed ulog.min.js.zip
Binary file not shown.
5 changes: 4 additions & 1 deletion ulog.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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')
Expand Down
23 changes: 13 additions & 10 deletions ulog.umd.js
Original file line number Diff line number Diff line change
Expand Up @@ -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){
Expand All @@ -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,]+/);
Expand Down Expand Up @@ -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)}
}
Expand All @@ -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
)
}
}
Expand All @@ -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
Expand Down

0 comments on commit 2cfa962

Please sign in to comment.