Skip to content

Commit b340d79

Browse files
authored
feat(logging): add configuration to disable logging MONGOSH-1988 (#2325)
1 parent 5e313d8 commit b340d79

17 files changed

+1536
-975
lines changed

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cli-repl/src/cli-repl.spec.ts

Lines changed: 82 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
import {
1919
expect,
2020
fakeTTYProps,
21-
readReplLogfile,
21+
readReplLogFile,
2222
tick,
2323
useTmpdir,
2424
waitBus,
@@ -31,6 +31,9 @@ import { CliRepl } from './cli-repl';
3131
import { CliReplErrors } from './error-codes';
3232
import type { DevtoolsConnectOptions } from '@mongosh/service-provider-node-driver';
3333
import type { AddressInfo } from 'net';
34+
import sinon from 'sinon';
35+
import type { CliUserConfig } from '@mongosh/types';
36+
import { MongoLogWriter, MongoLogManager } from 'mongodb-log-writer';
3437
const { EJSON } = bson;
3538

3639
const delay = promisify(setTimeout);
@@ -53,7 +56,7 @@ describe('CliRepl', function () {
5356
async function log(): Promise<any[]> {
5457
if (!cliRepl.logWriter?.logFilePath) return [];
5558
await cliRepl.logWriter.flush(); // Ensure any pending data is written first
56-
return readReplLogfile(cliRepl.logWriter.logFilePath);
59+
return readReplLogFile(cliRepl.logWriter.logFilePath);
5760
}
5861

5962
async function startWithExpectedImmediateExit(
@@ -235,6 +238,27 @@ describe('CliRepl', function () {
235238
});
236239
});
237240

241+
it('does not write to log syntax errors if logging is disabled', async function () {
242+
expect(
243+
(await log()).filter((entry) =>
244+
entry.attr?.stack?.startsWith('SyntaxError:')
245+
)
246+
).to.have.lengthOf(0);
247+
input.write('config.set("disableLogging", true)\n');
248+
await waitEval(cliRepl.bus);
249+
expect(output).includes('Setting "disableLogging" has been changed');
250+
251+
input.write('<cat>\n');
252+
await waitBus(cliRepl.bus, 'mongosh:error');
253+
await eventually(async () => {
254+
expect(
255+
(await log()).filter((entry) =>
256+
entry.attr?.stack?.startsWith('SyntaxError:')
257+
)
258+
).to.have.lengthOf(0);
259+
});
260+
});
261+
238262
it('writes JS errors to the log file', async function () {
239263
input.write('throw new Error("plain js error")\n');
240264
await waitBus(cliRepl.bus, 'mongosh:error');
@@ -297,7 +321,8 @@ describe('CliRepl', function () {
297321
'oidcTrustedEndpoints',
298322
'browser',
299323
'updateURL',
300-
]);
324+
'disableLogging',
325+
] satisfies (keyof CliUserConfig)[]);
301326
});
302327

303328
it('fails when trying to overwrite mongosh-owned config settings', async function () {
@@ -453,12 +478,14 @@ describe('CliRepl', function () {
453478
cliRepl = new CliRepl(cliReplOptions);
454479
await cliRepl.start('', {});
455480
await fs.stat(newerlogfile);
456-
try {
457-
await fs.stat(oldlogfile);
458-
expect.fail('missed exception');
459-
} catch (err: any) {
460-
expect(err.code).to.equal('ENOENT');
461-
}
481+
await eventually(async () => {
482+
try {
483+
await fs.stat(oldlogfile);
484+
expect.fail('missed exception');
485+
} catch (err: any) {
486+
expect(err.code).to.equal('ENOENT');
487+
}
488+
});
462489
});
463490

464491
it('verifies the Node.js version', async function () {
@@ -1309,7 +1336,6 @@ describe('CliRepl', function () {
13091336
hasCollectionNames: true,
13101337
hasDatabaseNames: true,
13111338
});
1312-
13131339
context('analytics integration', function () {
13141340
context('with network connectivity', function () {
13151341
let srv: http.Server;
@@ -1333,6 +1359,7 @@ describe('CliRepl', function () {
13331359
.on('data', (chunk) => {
13341360
body += chunk;
13351361
})
1362+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
13361363
.on('end', async () => {
13371364
requests.push({ req, body });
13381365
totalEventsTracked += JSON.parse(body).batch.length;
@@ -1343,7 +1370,7 @@ describe('CliRepl', function () {
13431370
})
13441371
.listen(0);
13451372
await once(srv, 'listening');
1346-
host = `http://localhost:${(srv.address() as any).port}`;
1373+
host = `http://localhost:${(srv.address() as AddressInfo).port}`;
13471374
cliReplOptions.analyticsOptions = {
13481375
host,
13491376
apiKey: '🔑',
@@ -1357,6 +1384,48 @@ describe('CliRepl', function () {
13571384
srv.close();
13581385
await once(srv, 'close');
13591386
setTelemetryDelay(0);
1387+
sinon.restore();
1388+
});
1389+
1390+
context('logging configuration', function () {
1391+
it('logging is enabled by default and event is called', async function () {
1392+
const onLogInitialized = sinon.stub();
1393+
cliRepl.bus.on('mongosh:log-initialized', onLogInitialized);
1394+
1395+
await cliRepl.start(await testServer.connectionString(), {});
1396+
1397+
expect(await cliRepl.getConfig('disableLogging')).is.false;
1398+
1399+
expect(onLogInitialized).calledOnce;
1400+
expect(cliRepl.logWriter).is.instanceOf(MongoLogWriter);
1401+
});
1402+
1403+
it('does not initialize logging when it is disabled', async function () {
1404+
cliRepl.config.disableLogging = true;
1405+
const onLogInitialized = sinon.stub();
1406+
cliRepl.bus.on('mongosh:log-initialized', onLogInitialized);
1407+
1408+
await cliRepl.start(await testServer.connectionString(), {});
1409+
1410+
expect(await cliRepl.getConfig('disableLogging')).is.true;
1411+
expect(onLogInitialized).not.called;
1412+
1413+
expect(cliRepl.logWriter).is.undefined;
1414+
});
1415+
1416+
it('logs cleanup errors', async function () {
1417+
sinon
1418+
.stub(MongoLogManager.prototype, 'cleanupOldLogFiles')
1419+
.rejects(new Error('Method not implemented'));
1420+
await cliRepl.start(await testServer.connectionString(), {});
1421+
expect(
1422+
(await log()).filter(
1423+
(entry) =>
1424+
entry.ctx === 'log' &&
1425+
entry.msg === 'Error: Method not implemented'
1426+
)
1427+
).to.have.lengthOf(1);
1428+
});
13601429
});
13611430

13621431
it('times out fast', async function () {
@@ -1507,11 +1576,11 @@ describe('CliRepl', function () {
15071576

15081577
it('includes a statement about flushed telemetry in the log', async function () {
15091578
await cliRepl.start(await testServer.connectionString(), {});
1510-
const { logFilePath } = cliRepl.logWriter!;
1579+
const { logFilePath } = cliRepl.logWriter as MongoLogWriter;
15111580
input.write('db.hello()\n');
15121581
input.write('exit\n');
15131582
await waitBus(cliRepl.bus, 'mongosh:closed');
1514-
const flushEntry = (await readReplLogfile(logFilePath)).find(
1583+
const flushEntry = (await readReplLogFile(logFilePath)).find(
15151584
(entry: any) => entry.id === 1_000_000_045
15161585
);
15171586
expect(flushEntry.attr.flushError).to.equal(null);

0 commit comments

Comments
 (0)