diff --git a/package.json b/package.json index b8e7f6d8eb..46468126c4 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "@salesforce/schemas": "^1.0.1", "@salesforce/ts-types": "^1.5.20", "@types/graceful-fs": "^4.1.5", - "@types/jsforce": "^1.9.38", + "@types/jsforce": "^1.9.41", "@types/mkdirp": "^1.0.1", "archiver": "^5.3.0", "debug": "^3.1.0", diff --git a/src/logger.ts b/src/logger.ts index 2dc7968fd9..84a8188ddb 100644 --- a/src/logger.ts +++ b/src/logger.ts @@ -10,7 +10,7 @@ import * as path from 'path'; import { Writable } from 'stream'; // @ts-ignore import * as Bunyan from '@salesforce/bunyan'; -import { parseJson, parseJsonMap } from '@salesforce/kit'; +import { Env, parseJson, parseJsonMap } from '@salesforce/kit'; import { Dictionary, ensure, @@ -219,6 +219,21 @@ export class Logger { // The sfdx root logger singleton private static rootLogger?: Logger; + /** + * The default rotation period for logs. Example '1d' will rotate logs daily (at midnight). + * See 'period' docs here: https://github.com/forcedotcom/node-bunyan#stream-type-rotating-file + */ + + public readonly logRotationPeriod = new Env().getString('SFDX_LOG_ROTATION_PERIOD') || '1d'; + + /** + * The number of backup rotated log files to keep. + * Example: '3' will have the base sfdx.log file, and the past 3 (period) log files. + * See 'count' docs here: https://github.com/forcedotcom/node-bunyan#stream-type-rotating-file + */ + + public readonly logRotationCount = new Env().getNumber('SFDX_LOG_ROTATION_COUNT') || 2; + /** * Whether debug is enabled for this Logger. */ @@ -416,14 +431,14 @@ export class Logger { !this.bunyan.streams.find( // No bunyan typings // eslint-disable-next-line @typescript-eslint/no-explicit-any - (stream: any) => stream.type === 'file' && stream.path === logFile + (stream: any) => stream.type === 'rotating-file' && stream.path === logFile ) ) { - // TODO: rotating-file - // https://github.com/trentm/node-bunyan#stream-type-rotating-file this.addStream({ - type: 'file', + type: 'rotating-file', path: logFile, + period: this.logRotationPeriod, + count: this.logRotationCount, level: this.bunyan.level() as number, }); } @@ -458,14 +473,14 @@ export class Logger { !this.bunyan.streams.find( // No bunyan typings // eslint-disable-next-line @typescript-eslint/no-explicit-any - (stream: any) => stream.type === 'file' && stream.path === logFile + (stream: any) => stream.type === 'rotating-file' && stream.path === logFile ) ) { - // TODO: rotating-file - // https://github.com/trentm/node-bunyan#stream-type-rotating-file this.addStream({ - type: 'file', + type: 'rotating-file', path: logFile, + period: this.logRotationPeriod, + count: this.logRotationCount, level: this.bunyan.level() as number, }); } diff --git a/test/unit/loggerTest.ts b/test/unit/loggerTest.ts index 1068018c35..854da97b79 100644 --- a/test/unit/loggerTest.ts +++ b/test/unit/loggerTest.ts @@ -20,6 +20,8 @@ const $$ = testSetup(); describe('Logger', () => { const sfdxEnv = process.env.SFDX_ENV; + const logRotationPeriodBackup = process.env.SFDX_LOG_ROTATION_PERIOD; + const logRotationCountBackup = process.env.SFDX_LOG_ROTATION_COUNT; beforeEach(async () => { process.env.SFDX_ENV = 'test'; @@ -32,7 +34,9 @@ describe('Logger', () => { afterEach(() => { Logger.destroyRoot(); - process.env.SFDX_ENV = sfdxEnv; + if (sfdxEnv) process.env.SFDX_ENV = sfdxEnv; + if (logRotationPeriodBackup) process.env.SFDX_LOG_ROTATION_PERIOD = logRotationPeriodBackup; + if (logRotationCountBackup) process.env.SFDX_LOG_ROTATION_COUNT = logRotationCountBackup; }); describe('constructor', () => { @@ -114,11 +118,25 @@ describe('Logger', () => { expect(utilMkdirpStub.called).to.be.false; expect(utilWriteFileStub.called).to.be.false; const addStreamArgs = addStreamStub.firstCall.args[0]; - expect(addStreamArgs).to.have.property('type', 'file'); + expect(addStreamArgs).to.have.property('type', 'rotating-file'); expect(addStreamArgs).to.have.property('path', testLogFile); expect(addStreamArgs).to.have.property('level', logger.getLevel()); }); + it('should allow log rotation count and period overrides', async () => { + process.env.SFDX_LOG_ROTATION_PERIOD = '1w'; + process.env.SFDX_LOG_ROTATION_COUNT = '3'; + + utilAccessStub.returns(Promise.resolve({})); + const logger = new Logger('testing-env-vars'); + const addStreamStub = $$.SANDBOX.stub(logger, 'addStream'); + await logger.addLogFileStream(testLogFile); + + const addStreamArgs = addStreamStub.firstCall.args[0]; + expect(addStreamArgs).to.have.property('period', '1w'); + expect(addStreamArgs).to.have.property('count', 3); + }); + it('should create a new log file and all directories if nonexistent', async () => { utilAccessStub.throws(); const logger = new Logger('testLogger'); diff --git a/yarn.lock b/yarn.lock index f6199f81f1..bc1e16d86e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -750,10 +750,10 @@ resolved "https://registry.yarnpkg.com/@types/jsen/-/jsen-0.0.19.tgz#f6f7ed4b390a88a52e8ac965945a761cbd9c83e9" integrity sha512-0XpFleNckrCh6X240Zelb91R7I9REYIx6VFTbxWCn/ontOreJe0+/HYTXyPSDOYKbx6s/Uo44UQjSAulk6jAjw== -"@types/jsforce@^1.9.38": - version "1.9.38" - resolved "https://registry.yarnpkg.com/@types/jsforce/-/jsforce-1.9.38.tgz#7c4b491d29e8becb9dcdd58c60472becce223139" - integrity sha512-+Iwf5jlDiK8z+zI2LAi4mzln8++5lETv2YofFEATu+dNkrP8LACB76lz2tPsXDx/a+5uW8HQhbwL/SyqIic0cg== +"@types/jsforce@^1.9.41": + version "1.9.41" + resolved "https://registry.yarnpkg.com/@types/jsforce/-/jsforce-1.9.41.tgz#08b31a0d04e14fd5f8a232196e16bc742e22bbed" + integrity sha512-J0dReK6EPGR98b4fAowqqQqFXH4DGtPxY2lLrZGcuCthrHYkYNrKnfGf2xM1jwiBC5CGdSEDmWEDwRwwmX25tA== dependencies: "@types/node" "*"