Skip to content

Commit

Permalink
fix: make caching options to fix a memory leak when using disposable …
Browse files Browse the repository at this point in the history
…loggers
  • Loading branch information
0xfede committed Jul 31, 2019
1 parent 495c2cc commit 0298612
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 69 deletions.
114 changes: 63 additions & 51 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,78 +12,90 @@ export interface Logger {
}

const __namespaces: {
[ns:string]: boolean
[ns: string]: boolean;
} = {};
const __loggers: {
[ns:string]: Logger;
[ns: string]: Logger;
} = {};

export function getLogger(ns: string, context?: string): Logger {
let cacheKey = context ? `${ns}@@${context}` : ns;
function createLogger(ns: string, context?: string): Logger {
let d = context
? function(label: string): IDebugger {
let origDebugger: IDebugger = debug(label);
let wrappedDebugger: IDebugger = <IDebugger>function(formatter: string, ...args: any[]) {
origDebugger(`${context} ${formatter}`, ...args);
};
wrappedDebugger.enabled = origDebugger.enabled;
wrappedDebugger.namespace = origDebugger.namespace;
Object.defineProperty(wrappedDebugger, 'log', {
get: () => origDebugger.log,
set: v => (origDebugger.log = v)
});
return wrappedDebugger;
}
: debug;

let out: Logger = {
log: d(ns + ':log'),
info: d(ns + ':info'),
warn: d(ns + ':warn'),
error: d(ns + ':error'),
debug: d(ns + ':debug'),
trace: d(ns + ':trace')
};

if (!__loggers[cacheKey]) {
__namespaces[ns] = true;
let d = context ? function(label:string): IDebugger {
let origDebugger:IDebugger = debug(label);
let wrappedDebugger:IDebugger = <IDebugger>function(formatter: string, ...args: any[]) {
origDebugger(`${context} ${formatter}`, ...args);
};
wrappedDebugger.enabled = origDebugger.enabled;
wrappedDebugger.namespace = origDebugger.namespace;
Object.defineProperty(wrappedDebugger, 'log', {
get: () => origDebugger.log,
set: v => origDebugger.log = v
});
return wrappedDebugger;
} : debug;
if (typeof window === 'object' && typeof window.console === 'object') {
try {
out.log.log = window.console.log.bind(window.console);
out.info.log = window.console.info.bind(window.console);
out.warn.log = window.console.warn.bind(window.console);
out.error.log = window.console.error.bind(window.console);
out.debug.log = (window.console.debug ? window.console.debug : window.console.log).bind(window.console);
out.trace.log = (window.console.trace ? window.console.trace : window.console.log).bind(window.console);
} catch (e) {}
}
return out;
}

let out:Logger = {
log: d(ns + ':log'),
info: d(ns + ':info'),
warn: d(ns + ':warn'),
error: d(ns + ':error'),
debug: d(ns + ':debug'),
trace: d(ns + ':trace')
};
export function getLogger(ns: string, context?: string, cache?: boolean): Logger {
let out: Logger;
if (cache === false) {
out = createLogger(ns, context);
} else {
let cacheKey = context ? `${ns}@@${context}` : ns;

if (typeof window === 'object' && typeof window.console === 'object') {
try {
out.log.log = window.console.log.bind(window.console);
out.info.log = window.console.info.bind(window.console);
out.warn.log = window.console.warn.bind(window.console);
out.error.log = window.console.error.bind(window.console);
out.debug.log = (window.console.debug ? window.console.debug : window.console.log).bind(window.console);
out.trace.log = (window.console.trace ? window.console.trace : window.console.log).bind(window.console);
} catch (e) {
}
if (!__loggers[cacheKey]) {
__namespaces[ns] = true;
__loggers[cacheKey] = createLogger(ns, context);
}

__loggers[cacheKey] = out;
out = __loggers[cacheKey];
}

return __loggers[cacheKey];
return out;
}

export function namespaces() {
return Object.keys(__namespaces);
}

export function cb(ns: string = ''): ((err: any, data?: any) => void) {
const l:Logger = getLogger(ns);
export function cb(ns: string = ''): (err: any, data?: any) => void {
const l: Logger = getLogger(ns);
return (err: any, data?: any) => {
if (err) {
l.error(err);
} else {
l.info(data);
}
}
};
}

export function promise(p:PromiseLike<any>, ns: string = ''): PromiseLike<any> {
const l:Logger = getLogger(ns);
return p.then(function(data) {
l.info(data);
}, function(err) {
l.error(err);
})
export function promise(p: PromiseLike<any>, ns: string = ''): PromiseLike<any> {
const l: Logger = getLogger(ns);
return p.then(
function(data) {
l.info(data);
},
function(err) {
l.error(err);
}
);
}
34 changes: 16 additions & 18 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,18 @@ chai.should();
chai.use(spies);

describe('debuggo', function() {

describe('getLogger', function() {

it('create a logger with no context', function() {
it('should create a logger with no context', function() {
let l = debuggo.getLogger('test-1');
l.log.should.be.a('function');
});

it('create a logger with a context', function() {
it('should create a logger with a context', function() {
let l = debuggo.getLogger('test-2', 'bbb');
l.info.should.be.a('function');
});

it('create cache loggers by namespace and context', function() {
it('should create cached loggers by namespace and context', function() {
let l1 = debuggo.getLogger('test-1');
let l2 = debuggo.getLogger('test-1');
let l3 = debuggo.getLogger('test-2', 'bbb');
Expand All @@ -33,7 +31,16 @@ describe('debuggo', function() {
l6.should.not.equal(l3);
});

it('use console.log to log when available', function() {
it('should create non cached loggers', function() {
let l1 = debuggo.getLogger('test-1', undefined, false);
let l2 = debuggo.getLogger('test-1', undefined, false);
let l3 = debuggo.getLogger('test-2', 'bbb', false);
let l4 = debuggo.getLogger('test-2', 'bbb', false);
l1.should.not.equal(l2);
l3.should.not.equal(l4);
});

it('should use console.log to log when available', function() {
let w = {
console: {
log: chai.spy(),
Expand All @@ -56,19 +63,15 @@ describe('debuggo', function() {
w.console.debug.should.have.been.called.once;
w.console.info.should.have.been.called.twice;
});

});

describe('namespaces', function() {

it('should return the namespaces', function() {
debuggo.namespaces().should.deep.equal(['test-1', 'test-2', 'test-3', 'test-4']);
})

});
});

describe('cb', function() {

it('should return a logging callback', function() {
let w = {
console: {
Expand All @@ -91,11 +94,9 @@ describe('debuggo', function() {
f2(null, 'data');
w.console.info.should.have.been.called.once;
});

});

describe('promise', function() {

it('should log a promise', function() {
let w = {
console: {
Expand All @@ -115,9 +116,6 @@ describe('debuggo', function() {
});
});
});
})

});
});


});
});

0 comments on commit 0298612

Please sign in to comment.