Ololog! BETA
- Platform-agnostic logging
- Colors / styles for terminals and Chrome DevTools (try online demo)
- Displays call locations
- Returns its argument (for easy debugging of functional expressions)
- Smart newline / indentation handling
- Formats
Error
instances as pretty stacktraces with source lines - Powerful object printer
- Pluggable architecture
Powered by
Importing
npm install ololog
log = require ('ololog')
Browser bundle
Exposes global ololog
and ansicolor
objects. Installs unsafe String extensions for ANSI styles. Not compressed.
<script src="https://rawgit.com/xpl/ololog/master/build/ololog.browser.js"></script>
<script>
log = ololog
log ('something'.red)
</script>
Basic usage
At first, it's similar to console.log
:
log ('foo', 'bar', 'baz') // foo bar baz
Configuration
It exposes a method called .configure
, which produces a new log
instance with the new settings applied (not mutating the original one), which can be saved and re-used subsequently:
const log = require ('ololog').configure ({ concat: { separator: '' }})
log ('foo', 'bar', 'baz') // foobarbaz
...or you can apply the configuration method ad-hoc:
log.configure ({ concat: { separator: '' }}) ('foo', 'bar', 'baz') // foobarbaz
You can read more about configure
here. Configuration engine is implemented as a separate external library, for everyone's use. Contributions are welcome.
Debugging of functional expressions
Ololog returns its first argument (a feature that console.log
doesn't have), and it greatly simplifies debugging of functional expressions, as you can simply wrap part of an expression to log
:
array.map (x => log (x) + 1)
It is far less ugly than with console.log
:
array.map (x => { console.log (x); return x + 1 })
ANSI styling
Backed by the ansicolor library, colored output is supported for the terminal environment and for the Chrome DevTools console. On other platforms, ANSI codes are safely stripped from the output, so they don't mess up anything.
Apply styling by calling the ansicolor
directly:
require ('ansicolor').nice // Importing
log (('foo'.dim.red + 'bar'.bgBrightCyan).underline)
...or by using the built-in shorthand methods (no need to import ansicolor
, but we lose the ability to colorize just a part of a string):
log.red ('red text')
log.bright.red.underline ('multiple styles combined')
See all the supported styling options here.
Smart newline handling
log.bright.magenta ('this is something:'.yellow, [ "595da547d9b22f23d8228643", "595da547d9b22f23d822863f", "595da547d9b22f23d8228641" ])
...and this is how it would look without special caring:
Can it handle more arguments?
log.bright (
'this is something:'.yellow, '[ "595da547d9b22f23d8228643",\n "595da547d9b22f23d822863f",\n "595da547d9b22f23d8228641" ]'.cyan,
'[ "595da547d9b22f23d8228643",\n "595da547d9b22f23d822863f",\n "595da547d9b22f23d8228641" ]'.green)
Smart object printing
All magic is provided by the external String.ify library. Read the docs to see all the available configuration options. There are plenty of them! Contributions are welcome.
let obj = { abc: 42, defgh: true, qwertyiop: 333, zap: '123457', long: ['foo', 'bar', 'baz', 'qux', 'lol', 'yup'] }
log (obj)
{ abc: 42,
defgh: true,
qwertyiop: 333,
zap: "123457",
long: [ "foo",
"bar",
"baz",
"qux",
"lol",
"yup" ] }
Disabling fancy formatting:
log.noPretty (obj) // or log.configure ({ stringify: { pretty: false } }) (obj)
{ abc: 42, defgh: true, qwertyiop: 333, zap: "123457", long: ["foo", "bar", "baz", "qux", "lol", "yup"] }
Changing max print depth / max array length:
log.maxDepth (1).maxArrayLength (100) (...) // or log.configure ({ stringify: { maxDepth: 1, maxArrayLength: 100 } })
log.unlimited (...) // disables limiting
Error
instances
Pretty printing This feature is implemented in the StackTracey library. See it's docs for more (you can configure the path shortening / library calls skipping).
const e = new Error ('dummy error') // issued somewhere in a Mocha test callback...
...
log.bright.red (e)
[EXCEPTION] dummy error
at it test.js:104 const e = new Error ('dummy error')
at it test.js:109 log.bright.red (e)
at callFn node_modules/mocha/lib/runnable.js:326 var result = fn.call(ctx);
at run node_modules/mocha/lib/runnable.js:319 callFn(this.fn);
at runTest node_modules/mocha/lib/runner.js:422 test.run(fn);
at node_modules/mocha/lib/runner.js:528 self.runTest(function(err) {
at next node_modules/mocha/lib/runner.js:342 return fn();
at node_modules/mocha/lib/runner.js:352 next(suites.pop());
at next node_modules/mocha/lib/runner.js:284 return fn();
at <anonymous> node_modules/mocha/lib/runner.js:320 next(0);
at runCallback timers.js:651
at tryOnImmediate timers.js:624
at processImmediate [as _immediat timers.js:596
Displaying call location
Have you ever encountered a situation where you need to quickly find in the code the place where the logging is called, but it's not so easy to do? With call location tags it's really easy. And it's enabled by default.
Disabling:
log.configure ({ locate: false }) (...)
Custom printer:
log.configure ({ locate: { print: ({ calleeShort, fileName, line }) => ... } }) (...)
Manually setting call location (see the StackTracey library, which serves the purpose):
log.configure ({ locate: { where: new StackTracey ().at (2) } }) (...)
Indentation
log.configure ({ indent: { level: 3 } }) ('foo\n', 'bar\n', 'baz') // foo
// bar
// baz
Shorthand method:
log.indent (2) ('foo\n', 'bar\n', 'baz')
Timestamping
Disabled by default. To enable:
log = log.configure ({ time: true })
With indentation:
log ('Lorem ipsum dolor sit amet\nconsectetur adipiscing elit..\n')
log.indent (2) ('Lorem ipsum dolor sit amet\nconsectetur adipiscing elit..\n')
With custom printer:
log.configure ({ time: { print: x => (String (x) + ' | ').bright.cyan }}) ('Lorem ipsum dolor sit amet\nconsectetur adipiscing elit..')
Backdating:
log.configure ({ time: { when: new Date ('2017-02-27T12:45:19.951Z') }}) (...)
Specifying additional semantics (errors, warnings, info messages)
You can add .error
call modifier, which tells Ololog to render with console.error
instead of console.log
:
log.error ('this goes to stderr')
log.bright.red.error ('bright red error!')
Under the hood it does the following:
log.configure ({ render: { consoleMethod: 'error' } }) ('this goes to stderr')
Other console
methods are supported as well:
log.info ('calls console.info')
log.warn ('calls console.warn')
Limiting max argument length
log.configure ({ trim: { max: 5 } }) ('1234567890', 'abcdefgh') // 1234… abcd…
Getting rendered text
The following will execute all stages before the 'render' (screen output) stage, returning its argument:
log.before ('render') ({ foo: 42 }) // '{ foo: 42 }'
Custom methods / aspect-oriented code injection
You can add your own shorthand methods, and you can also bind new code to the existing methods, executing it before, after or instead. See the pipez library, which provides all the fun.
log.methods ({
indent (level) { return this.configure ({ indent: { level: level }}) }
get red () { return this.configure ({ 'concat+': lines => lines.map (ansicolor.red) }) } // executes it after the 'concat'
get bright () { return this.configure ({ 'concat+': lines => lines.map (ansicolor.bright) }) }
})
log.indent (2).configure ({ time: true }).red.bright ('this is bold red message, indented by 2 and supplied with timestamp')