diff --git a/package-lock.json b/package-lock.json index f4da786..09cbbff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -384,19 +384,19 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true }, "supports-color": { diff --git a/src/Logger.spec.ts b/src/Logger.spec.ts index 1056834..23cb989 100644 --- a/src/Logger.spec.ts +++ b/src/Logger.spec.ts @@ -1,8 +1,9 @@ import { expect } from 'chai'; import type { LogLevel, LogMessage } from './Logger'; -import { Logger, LogLevelColor, LogLevelNumeric } from './Logger'; +import { Logger, LogLevelColor, LogLevelNumeric, chalk } from './Logger'; import { ConsoleTransport } from './transports/ConsoleTransport'; import { createSandbox } from 'sinon'; +import { Stopwatch } from './Stopwatch'; const sinon = createSandbox(); describe('Logger', () => { @@ -17,6 +18,8 @@ describe('Logger', () => { sinon.restore(); sinon.stub(Logger.prototype as any, 'getCurrentDate').returns(now); logger = new Logger(); + //disable chalk colors for this test + chalk.level = 0; }); afterEach(() => { @@ -509,6 +512,32 @@ describe('Logger', () => { }); }); + describe('timeStart', () => { + it('skips logging when logLevel is disabled', async () => { + const stub = sinon.stub(logger, 'write').callThrough(); + logger.logLevel = 'log'; + const stop = logger.timeStart('info', 'message'); + await sleep(10); + stop(); + expect(stub.called).to.be.false; + }); + + it('logs when logLevel is enabled', async () => { + sinon.stub(Stopwatch.prototype, 'getDurationText').callsFake(() => '10ms'); + const stub = sinon.stub(logger, 'write').callThrough(); + logger.logLevel = 'info'; + const stop = logger.timeStart('info', 'message'); + await sleep(10); + stop(); + expect( + stub.getCalls().map(x => x.args) + ).to.eql([ + ['info', 'message'], + ['info', 'message', `finished. (10ms)`] + ]); + }); + }); + describe('time', () => { it('calls action even if logLevel is wrong', () => { logger.logLevel = 'error'; @@ -555,3 +584,9 @@ describe('Logger', () => { }); }); }); + +async function sleep(ms: number) { + return new Promise(resolve => { + setTimeout(resolve, ms); + }); +} diff --git a/src/Logger.ts b/src/Logger.ts index 06b4cd1..cac4e94 100644 --- a/src/Logger.ts +++ b/src/Logger.ts @@ -291,6 +291,27 @@ export class Logger { this.write('error', ...messages); } + /** + * Writes to the log (if logLevel matches), and also provides a function that can be called to mark the end of a time. + */ + public timeStart(logLevel: LogLevel, ...messages: unknown[]) { + //call the log if loglevel is in range + if (this.isLogLevelEnabled(logLevel)) { + const stopwatch = new Stopwatch(); + + //write the initial log + this.write(logLevel, ...messages); + + stopwatch.start(); + + return (status = 'finished') => { + stopwatch.stop(); + this.write(logLevel, ...messages, `${status}. (${chalk.blue(stopwatch.getDurationText())})`); + }; + } + return noop; + } + /** * Writes to the log (if logLevel matches), and also times how long the action took to occur. * `action` is called regardless of logLevel, so this function can be used to nicely wrap diff --git a/tsconfig.json b/tsconfig.json index 9f741c5..3b49853 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,26 @@ { "compilerOptions": { - "module": "commonjs", - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "target": "es2018", - "declaration": true, + "noImplicitAny": false, + "target": "ES2017", + "module": "CommonJS", "sourceMap": true, + "rootDir": "src", "outDir": "dist", - "preserveConstEnums": true + "declaration": true, + "strict": true, + "strictNullChecks": false, + "forceConsistentCasingInFileNames": true, + "experimentalDecorators": true, + "preserveConstEnums": true, + "downlevelIteration": true, + "noUnusedLocals": true, + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "lib": [ + "es2017", + "es2019.array", + "dom" + ] }, "include": [ "src/**/*.ts" @@ -20,4 +32,4 @@ "ts-node": { "transpileOnly": true } -} \ No newline at end of file +}