Skip to content

Commit

Permalink
feat(cli-repl): add configuration to set log retention days MONGOSH-1984
Browse files Browse the repository at this point in the history
  • Loading branch information
gagik authored Feb 7, 2025
1 parent 51bbd33 commit a9a2a51
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 2 deletions.
14 changes: 14 additions & 0 deletions packages/cli-repl/src/cli-repl.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ describe('CliRepl', function () {
'updateURL',
'disableLogging',
'logLocation',
'logRetentionDays',
] satisfies (keyof CliUserConfig)[]);
});

Expand Down Expand Up @@ -1443,6 +1444,19 @@ describe('CliRepl', function () {
)
);
});

it('can set log retention days', async function () {
const testRetentionDays = 123;
cliRepl.config.logRetentionDays = testRetentionDays;
await cliRepl.start(await testServer.connectionString(), {});

expect(await cliRepl.getConfig('logRetentionDays')).equals(
testRetentionDays
);
expect(cliRepl.logManager?._options.retentionDays).equals(
testRetentionDays
);
});
});

it('times out fast', async function () {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli-repl/src/cli-repl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ export class CliRepl implements MongoshIOProvider {
directory:
(await this.getConfig('logLocation')) ||
this.shellHomeDirectory.localPath('.'),
retentionDays: 30,
retentionDays: await this.getConfig('logRetentionDays'),
maxLogFileCount: +(
process.env.MONGOSH_TEST_ONLY_MAX_LOG_FILE_COUNT || 100
),
Expand Down
73 changes: 72 additions & 1 deletion packages/e2e-tests/test/e2e.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable no-control-regex */
import { expect } from 'chai';
import type { Db } from 'mongodb';
import { MongoClient } from 'mongodb';
import { MongoClient, ObjectId } from 'mongodb';

import { eventually } from '../../../testing/eventually';
import { TestShell } from './test-shell';
Expand Down Expand Up @@ -1676,6 +1676,77 @@ describe('e2e', function () {
});
});

/** Helper to visualize and compare the existence of files in a specific order.
* Returns a string comprised of: 1 if a given file exists, 0 otherwise. */
const getFilesState = async (paths: string[]) => {
return (
await Promise.all(
paths.map((path) =>
fs.stat(path).then(
() => 1,
() => 0
)
)
)
).join('');
};

describe('with custom log retention days', function () {
const customLogDir = useTmpdir();

it('should delete older files according to the setting', async function () {
const paths: string[] = [];
const today = Math.floor(Date.now() / 1000);
const tenDaysAgo = today - 10 * 24 * 60 * 60;
// Create 6 files older than 7 days
for (let i = 5; i >= 0; i--) {
const filename = path.join(
customLogDir.path,
ObjectId.createFromTime(tenDaysAgo - i).toHexString() + '_log'
);
await fs.writeFile(filename, '');
paths.push(filename);
}
// Create 4 files newer than 10 days
for (let i = 3; i >= 0; i--) {
const filename = path.join(
customLogDir.path,
ObjectId.createFromTime(today - i).toHexString() + '_log'
);
await fs.writeFile(filename, '');
paths.push(filename);
}

const retentionDays = 7;

const globalConfig = path.join(homedir, 'globalconfig.conf');
await fs.writeFile(
globalConfig,
`mongosh:\n logLocation: ${JSON.stringify(
customLogDir.path
)}\n logRetentionDays: ${retentionDays}`
);

expect(await getFilesState(paths)).equals('1111111111');

shell = this.startTestShell({
args: ['--nodb'],
env: {
...env,
MONGOSH_GLOBAL_CONFIG_FILE_FOR_TESTING: globalConfig,
},
forceTerminal: true,
});

await shell.waitForPrompt();

// Add the newly created log file
paths.push(path.join(customLogDir.path, `${shell.logId}_log`));
// Expect 6 files to be deleted and 5 to remain (including the new log file)
expect(await getFilesState(paths)).equals('00000011111');
});
});

it('creates a log file that keeps track of session events', async function () {
expect(await shell.executeLine('print(123 + 456)')).to.include('579');
const log = await readLogFile();
Expand Down
6 changes: 6 additions & 0 deletions packages/types/src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ describe('config validation', function () {
expect(await validate('historyLength', 0)).to.equal(null);
expect(await validate('historyLength', 1)).to.equal(null);
expect(await validate('historyLength', Infinity)).to.equal(null);
expect(await validate('logRetentionDays', 'foo')).to.equal(
'logRetentionDays must be a positive integer'
);
expect(await validate('logRetentionDays', -1)).to.equal(
'logRetentionDays must be a positive integer'
);
expect(await validate('showStackTraces', 'foo')).to.equal(
'showStackTraces must be a boolean'
);
Expand Down
2 changes: 2 additions & 0 deletions packages/types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,7 @@ export class CliUserConfig extends SnippetShellUserConfig {
updateURL = 'https://downloads.mongodb.com/compass/mongosh.json';
disableLogging = false;
logLocation: string | undefined = undefined;
logRetentionDays = 30;
}

export class CliUserConfigValidator extends SnippetShellUserConfigValidator {
Expand All @@ -531,6 +532,7 @@ export class CliUserConfigValidator extends SnippetShellUserConfigValidator {
return null;
case 'inspectDepth':
case 'historyLength':
case 'logRetentionDays':
if (typeof value !== 'number' || value < 0) {
return `${key} must be a positive integer`;
}
Expand Down

0 comments on commit a9a2a51

Please sign in to comment.