log.js
function LLog(opts) {
    var options = opts || {},
        level = defaultLevel,
        stdout;
    if (typeof opts === 'object' && opts != null) {
        level = opts.level || level;
        stdout = opts.stdout;
    } else {
        if (typeof opts !== 'undefined') {
            level = opts;
        }
        if (arguments.length > 1) {
            stdout = arguments[1];
        }
    }
    this.level = handleLevel(level) || level;
    if (stdout) {
        this.stdout = stdout;
    } else if (typeof process !== 'undefined' && process.stdout && typeof LLOG_SKIP_USING_PROCESS === 'undefined') {
        //LLOG_SKIP_USING_PROCESS is defined in tests
        this.stdout = process.stdout;
    } else {
        this.stdout = {
            write: function(string) {
                //trim ending \n or spaces before logging
                console.log(string.replace(/\s+$/, ''));
            }
        };
    }
    this.displayTimestamp = options.displayTimestamp === true;
}
function LLog(opts) {
    var options = opts || {},
        level = defaultLevel,
        stdout;
    if (typeof opts === 'object' && opts != null) {
        level = opts.level || level;
        stdout = opts.stdout;
    } else {
        if (typeof opts !== 'undefined') {
            level = opts;
        }
        if (arguments.length > 1) {
            stdout = arguments[1];
        }
    }
    this.level = handleLevel(level) || level;
    if (stdout) {
        this.stdout = stdout;
    } else if (typeof process !== 'undefined' && process.stdout && typeof LLOG_SKIP_USING_PROCESS === 'undefined') {
        //LLOG_SKIP_USING_PROCESS is defined in tests
        this.stdout = process.stdout;
    } else {
        this.stdout = {
            write: function(string) {
                //trim ending \n or spaces before logging
                console.log(string.replace(/\s+$/, ''));
            }
        };
    }
    this.displayTimestamp = options.displayTimestamp === true;
}
old format: LLog(level, stdout)