Skip to content

Commit

Permalink
2.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
nomilous committed Oct 30, 2016
1 parent 701fa70 commit 62c1769
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 37 deletions.
75 changes: 62 additions & 13 deletions README.md
Expand Up @@ -14,45 +14,94 @@ A logger.
const VertexLogger = require('vertex-logger');

const logger = new VertexLogger({
parent: 'rootName',
name: 'name1',
level: 'info' // off fatal error warn info debug
root: 'root',
name: 'name',
level: 'info' // off fatal error warn info debug trace
});

logger.level = 'debug'; // reset level

logger.info('interpo%s st%s', 'lated', 'ring');
// if stdout is TTY:
// [ info] (rootName/name1) interpolated string (201ms)
// [ info] (root/name) interpolated string (201ms)
// if not:
// 2016-10-21 14:11:31.471 [ info] (rootName/name) interpolated string (201ms)
// 2016-10-21 14:11:31.471 [ info] (root/name) interpolated string (201ms)

logger.fatal(); // to stderr
logger.error(); // to stderr
logger.warn(); // to stdout
logger.info(); // to stdout
logger.debug(); // to stdout
logger.trace(); // to stdout

logger.error("couldn't", new Error('Why'));
// [error] (rootName/name1) couldn't (1231ms)
// [error] (root/name) couldn't (1231ms)
// Error: Why
// at repl:1:25
// at sigintHandlersWrap (vm.js:22:35)
// at sigintHandlersWrap (vm.js:96:12)
// ...
```

#### A tree of loggers...

...can be built for context.

```javascript
let appLogger = new VertexLogger({
root: 'app-name',
name: 'application'
});

// create new logger from existing logger
logger2 = logger.createLogger({name: 'name2'});
let serviceLogger = appLogger.createLogger({
name: 'service-name'
});

logger2.info('message');
// [ info] (rootName/name2) message (0ms)
let componentLogger = serviceLogger.createLogger({
name: 'component-name'
});

//
// Log messages only display 'root/name' and not 'root/parent/parent/name'
//
// Note:
// name2 is actually at rootName/name1/name2 but the logger does not currently
// show the full path.
// eg.

componentLogger.info('message');
// [ info] (app-name/component-name) message (0ms)
```

#### Loglevel functors...

...can be passed as loglevel to target specific components.

```javascript
let logger = new VertexLogger({
root: 'app-name',
name: 'application',

level: (info) => {
if (info.name == 'specific-component') return 'trace';
// defaults to 'info'
}
});

// The level functor is inherited into the tree of loggers
// - it overrides log levels passed as string on createLogger() child
// - if does not override loglevels passed as functions on createLogger() child


// Level by functor can also be directly assigned

logger.level = (info) => {
if (info.ancestors.indexOf('service-name') >= 0) return 'off';
if (info.ancestors.pop() == 'specific-parent') return 'off';
return 'trace';
}
```

#### Todo

```javascript
parentLogger.levelAll == 'off' || fn; // applied to all children
```

61 changes: 46 additions & 15 deletions lib/VertexLogger.js
Expand Up @@ -42,46 +42,77 @@ let last = new Date();

class VertexLogger {

constructor(config = {}) {
constructor(config = {}, parent) {
Object.defineProperty(this, '_parent', {
value: config.parent || 'parent',
writable: true
value: parent
});
Object.defineProperty(this, '_root', {
value: config.parent || 'parent',
writable: true
value: parent instanceof VertexLogger ? parent._root : config.root || 'root'
});
Object.defineProperty(this, '_name', {
value: config.name || 'name',
writable: true
value: config.name || 'name'
});
Object.defineProperty(this, '_ancestors', {
value: parent instanceof VertexLogger
? parent._ancestors.map(name => {return name}).concat(parent._name)
: [this._root]
});
Object.defineProperty(this, '_level', {
value: null,
value: parent instanceof VertexLogger ? parent._level : 4,
writable: true
});
Object.defineProperty(this, '_levelFn', {
value: parent instanceof VertexLogger ? parent._levelFn : null,
writable: true
});


Object.defineProperty(this, 'level', {
get: () => {
return LEVELS[this._level];
},
set: (level) => {
let levelNo = LEVELS.indexOf(level);
let levelNo;
if (typeof level == 'function') {
levelNo = LEVELS.indexOf(
level({
name: this._name,
ancestors: this._ancestors.map(name => {return name})
}) || 'info'
);
} else {
levelNo = LEVELS.indexOf(level);
}

if (levelNo < 0) {
throw new Error('Not one of levels ' + LEVELS);
}
this._level = levelNo;
},
});

this.level = config.level || 'info';
// assigned level function overrides inherited one
if (typeof config.level == 'function') {
this._levelFn = config.level;
this.level = this._levelFn;
return;
}

// inherited level function overrides level string
if (this._levelFn) {
config.level = this._levelFn;
this.level = this._levelFn;
return;
}

// assign from string
if (typeof config.level == 'string') {
this.level = config.level;
}
}

createLogger(config = {}) {
config.parent = this._name;
if (!config.level) config.level = this.level;
let logger = new VertexLogger(config);
logger._root = this._root;
return logger;
return new VertexLogger(config, this);
}

fatal(string, ...args) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -3,7 +3,7 @@
"engines": {
"node": "^6.0.0"
},
"version": "2.1.0",
"version": "2.2.0",
"description": "A logger.",
"main": "index.js",
"scripts": {
Expand Down
110 changes: 102 additions & 8 deletions test/func-VertexLogger.js
Expand Up @@ -9,8 +9,7 @@ describe(filename, () => {
it('defaults name and level', done => {

let logger = new VertexLogger();
expect(logger._root).to.be('parent');
expect(logger._parent).to.be('parent');
expect(logger._root).to.be('root');
expect(logger._name).to.be('name');
expect(logger._level).to.be(VertexLogger.LEVEL_INFO);
expect(logger.level).to.be('info');
Expand All @@ -20,8 +19,8 @@ describe(filename, () => {

it('uses configured name and level', done => {

let logger = new VertexLogger({parent: 'a', name: 'x', level: 'debug'});
expect(logger._parent).to.be('a');
let logger = new VertexLogger({root: 'a', name: 'x', level: 'debug'});
expect(logger._root).to.be('a');
expect(logger._name).to.be('x');
expect(logger._level).to.be(VertexLogger.LEVEL_DEBUG);
done();
Expand Down Expand Up @@ -70,23 +69,118 @@ describe(filename, () => {

});

it('can create a new logger from an existing one which inherits the level and parent', done => {
it('can create a new logger from existing, inherits level and ancestors', done => {

let log1 = new VertexLogger({parent: 'a', name: 'one', level: 'fatal'});
let log1 = new VertexLogger({root: 'a', name: 'one', level: 'fatal'});
let log2 = log1.createLogger({name: 'two'});

expect(log1._parent).to.be('a');
expect(log1._root).to.be('a');
expect(log1._ancestors).to.eql(['a']);
expect(log1._name).to.be('one');
expect(log1._level).to.be(VertexLogger.LEVEL_FATAL);

expect(log2._root).to.be('a');
expect(log2._parent).to.be('one');
expect(log2._ancestors).to.eql(['a', 'one']);
expect(log2._name).to.be('two');
expect(log2._level).to.be(VertexLogger.LEVEL_FATAL);
expect(log2.level).to.be('fatal');
done();

});


it('can set the level by function', done => {

let log = new VertexLogger({name: 'test', level: (info) => {
if (info.name == 'test') return 'fatal';
return 'info';
}});

expect(log._level).to.be(VertexLogger.LEVEL_FATAL);
done();

});


it('provices ancestry in level function', done => {

let log = new VertexLogger({root: 'ROOT', name: 'grandparent'});
log = log.createLogger({name: 'parent'});
log.createLogger({name: 'me', level: (info) => {

expect(info.ancestors).to.eql(['ROOT', 'grandparent', 'parent']);
done();

}});

});


it('can reassign the level by function', done => {

let log = new VertexLogger({name: 'test'});
expect(log._level).to.be(VertexLogger.LEVEL_INFO);

log.level = () => {return 'fatal'};

expect(log.level).to.equal('fatal');

done();

});


it('inherits parent level function', done => {

let log = new VertexLogger({name: 'one', level: () => {return 'fatal'}});

let log2 = log.createLogger({name: 'two'});
expect(log2.level).to.equal('fatal');
done();

});


it('inherits parent level function after parent reassignment (?)', done => {

let log = new VertexLogger({name: 'one', level: () => {return 'fatal'}});
log.level = 'info';
expect(log.level).to.equal('info');

let log2 = log.createLogger({name: 'two'});
expect(log2.level).to.equal('fatal');
done();

});


it('inherited level function overrides string', done => {

let log = new VertexLogger({name: 'one', level: () => {return 'fatal'}});
log.level = 'info';
expect(log.level).to.equal('info');

let log2 = log.createLogger({name: 'two', level: 'info'});
expect(log2.level).to.equal('fatal');
done();

});


it('assigned level function overrides inherited', done => {

let log = new VertexLogger({name: 'one', level: () => {return 'fatal'}});
log.level = 'info';
expect(log.level).to.equal('info');

let log2 = log.createLogger({name: 'two', level: () => {return 'off'}});
expect(log2.level).to.equal('off');
done();


});


it('keeps absolute root', done => {

let log = new VertexLogger({parent: 'ROOT', name: 'name1'});
Expand Down

0 comments on commit 62c1769

Please sign in to comment.