Logule 
Logule is a heavily configurable logging utility for nodejs. It is analogous to console.log
and can take multiple arguments, but additionally it prefixes the current time, the log level, and optionally, prefixed namespaces (with optional padding).
Shortcut methods for the log levels are available as (by default): log.error
, log.warn
, log.info
, log.debug
, log.trace
, log.zalgo
, and as a bonus, log.line
. These methods are additionally chainable.
It favours a combination of Dependency Injection and environment variable based
control to allow for both tree-based log level filtration (via DI),
and globally controllable log levels (via config files).
Usage
Basic usage:
var logule = require('logule');
logule
.error("this is an error message")
.warn("warning")
.info("info msg")
.debug("chained debug");

Namespaces
To add a namespace prefix, subclass logule with it:
log = logule.sub('BUILD');
log.trace("Trying to compile main.js");
log.error("Failed");
logule.info("Shutting down")

Multiple Namespaces
Pass in more strings to get more namespaces prefixed
var log = logule.sub('BUILD', 'COMPILE');
log.debug('log has two prefixes');
Namespace Padding
Call .pad(size)
on a logger instance to specify a fixed indentation level for each namespace.
log.pad(16);
log.warn('my namespaces are padded');
Messages will here begin (16 + delimiter_size)*num_namespaces
characters out.
Large namespaces (>specified size), will stand out from the crowd.
Line
An awesome feature inspired by nlogger - but using logule
semantics; logule.line()
reads the line and filename of the calling function
by directly inspecting the stack.
log = logule.sub('CRAZYDEBUG');
log.debug('dumping lines to console');
log.line('who called me?');
log.line('and now?');
```

## Passing log around
### Dependency Injection
#### Subclasses
A good use of `.sub()` involve inheriting based on namespaces, and linking
instances together.
````javascript
var log = logule.sub('BUILD');
var sublog = log.sub('COMPILE');
Here sublog
would provide same output as logule.sub('BUILD', 'COMPILE')
.
It is advantageous to do 'one namespace sub at a time', as then it is easier
to filter log output from large chunks of code at a time,
as well as maintaining a sensible log hierarchy.
A log.sub()
maintains all padding, suppressed log levels, its locked status,
and namespace properties set on the original log
instance. Therefore, it works as if there's
an implicit link between the sub and its parent.
Suppress
Suppressing logs from an instance is done in a very neat, propagating,
and non-breaking way. .suppress(methods...)
suppresses output
from specified methods, but still allows them to be called, and they still chain.
log.suppress('debug', 'info');
log.warn('works').info('suppressed').error('works').debug('suppressed');
All subclasses subsequently created from a suppressed instance,
will also be suppressed. To unsuppress, use .allow()
.
Allow
Allows modules down in the hierarchy to log things that have been suppressed
by supers. This only works if global log levels have not been enforced.
log.suppress('debug', 'info');
var l2 = log.sub('forModuleX');
l2.allow('debug');
l2.debug('works!')
Get Method
A debug module should only need log.debug
. You can save typing,
and enforce this behaviour by calling .get('debug')
on an instance,
to return the correctly bound instance method to pass down.
var dbg = log.get('debug');
dbg("works like log.debug - nothing else accessible through this var");
Note that if log
have called .suppress('debug')
earlier - or if it is a .sub()
of an instance that have called .suppress('debug')
, then you would only get
a suppressed function from .get('debug')
.
Tree Based Log Levels
By only using .sub()
instances inheriting from a single base instance,
you can implement tree based log levels at start time by calling
.suppress()
and .allow()
on the base instance - or any branch point
you would like.
var log = logule.sub('APP');
var modelsLog = log.sub('MODEL');
var eventsLog = modelsLog.sub('EVENT');
Tree based log levels is the safe, overridable version of log levels.
To strictly enforce suppression of certain levels, use environment variables.
Configuration
Since logule >= 0.7, rich configuration of colors, style, date formatting and global suppression of certain log levels is available. The default configuration file results in output looking like the older versions.
When starting a node script requiring logule, logule will search from the execution directory for a .logule
file. If that fails, it will keep searching one directory up until $HOME is hit.
If no config is found, or it is incomplete, the default one in this directory will be used, or merged with the found one respectively.
Config Ideas
Custom Prototype Log Methods
Config files can fully reconfigure/add new log methods with your own names. The prototype methods created will be directly taken from the level object in the config file, and these will log with the specified color and with the same (upper cased in print) level. Note that you can not remove the original methods (only suppress them) as to do so would break DI.
Note that line
which will additionally include the file and line of callsite when used, and zalgo
will have some idiosyncratic formatting.
Global Filtration
Set the suppress
flag to globally turn all listed log methods into chaining no-ops.
If most methods listed should be disabled, quickly list the exceptions under the allow
flag and set useAllow
to true
.
Verifying Logule Validity
When passing logule subs around, it might be useful for separate code to test
whether what is received is an appropriate Logule instance or not.
Unfortunately, instanceof testing against your installed logule will only work
when your code is not separated into modules.
Therefore, to support npm module style where there are possibly multiple installations
of logule spread around, the module can test that the one passed in,
has a version compatible with the module's own using a built in helper function.
var logule = require('logule');
function (injectedLogule) {
if (logule.verify(injectedLogule)) {
} else {
}
}
Note that single functions like logule.get('info')
will of course not pass this test.
If your API expects a single logger function, then
you should simply type test the input as a function.
Zalgo
H̸̡̪̯ͨ͊̽̅̾̎Ȩ̬̩̾͛ͪ̈́̀́͘ ̶̧̨̱̹̭̯ͧ̾ͬC̷̙̲̝͖ͭ̏ͥͮ͟Oͮ͏̮̪̝͍M̲̖͊̒ͪͩͬ̚̚͜Ȇ̴̟̟͙̞ͩ͌͝S̨̥̫͎̭ͯ̿̔̀ͅ
log.zalgo("all is lost");
Installation
$ npm install logule
Running tests
Install development dependencies
$ npm install
Run the tests
$ npm test
License
MIT-Licensed. See LICENSE file for details.