diff --git a/src/debug.js b/src/debug.js index c1fad6bd..7d3c0d57 100644 --- a/src/debug.js +++ b/src/debug.js @@ -160,6 +160,37 @@ function createDebug(namespace) { return section; }; + debug.time = function () { + var args = [].slice.call(arguments); + if (args.length < 2) { + throw new Error('debug.time() takes at least a debug string and a function'); + } + + var fn = args.pop(); + if (typeof fn !== 'function') { + throw new Error('the last argument to debug.time() must be a function'); + } + + var isPromise = false; + var section = debug.begin.apply(debug, args); + try { + var result = fn(); + + if (typeof Promise === 'function' && result instanceof Promise) { // eslint-disable-line no-undef + isPromise = true; + result.then(function () { + section.end(); + }); + } + + return result; + } finally { + if (!isPromise) { + section.end(); + } + } + }; + // env-specific initialization logic for debug instances if ('function' === typeof exports.init) { exports.init(debug); diff --git a/test/debug_spec.js b/test/debug_spec.js index 52b1177f..5608b983 100644 --- a/test/debug_spec.js +++ b/test/debug_spec.js @@ -82,6 +82,63 @@ describe('debug', function () { expect(log.log).to.have.been.calledThrice; }); + + it('times a critical function', function () { + log.log = sinon.spy(); + + var result = log.time('a critical function', function () { + log('hello from inside'); + return 1234; + }); + + expect(result).to.equal(1234); + expect(log.log).to.have.been.calledThrice; + }); + + if (typeof Promise !== 'undefined') { + it('times a critical asynchronous function', function (cb) { + log.log = sinon.spy(); + + log.time('a critical function', function () { + return new Promise(function (resolve) { + log('hello from the inside'); + resolve(1234); + }); + }).then(function (result) { + expect(result).to.equal(1234); + expect(log.log).to.have.been.calledThrice; + cb(); + }).catch(cb); + }); + } + + it('should throw if there aren\'t enough arguments', function () { + log.log = sinon.stub(); + + expect(function () { + log.time(); + }).to.throw('debug.time() takes at least a debug string and a function'); + + expect(function () { + log.time('hello'); + }).to.throw('debug.time() takes at least a debug string and a function'); + + expect(function () { + log.time(function () {}); + }).to.throw('debug.time() takes at least a debug string and a function'); + }); + + it('should throw if last argument isn\'t a function', function () { + log.log = sinon.stub(); + + expect(function () { + log.time('hello', 1234); + }).to.throw('the last argument to debug.time() must be a function'); + + expect(function () { + log.time('hello', function () {}, 1235); + }).to.throw('the last argument to debug.time() must be a function'); + }); }); }); });