@@ -18,7 +18,7 @@ import {
18
18
import {
19
19
expect ,
20
20
fakeTTYProps ,
21
- readReplLogfile ,
21
+ readReplLogFile ,
22
22
tick ,
23
23
useTmpdir ,
24
24
waitBus ,
@@ -31,6 +31,9 @@ import { CliRepl } from './cli-repl';
31
31
import { CliReplErrors } from './error-codes' ;
32
32
import type { DevtoolsConnectOptions } from '@mongosh/service-provider-node-driver' ;
33
33
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' ;
34
37
const { EJSON } = bson ;
35
38
36
39
const delay = promisify ( setTimeout ) ;
@@ -53,7 +56,7 @@ describe('CliRepl', function () {
53
56
async function log ( ) : Promise < any [ ] > {
54
57
if ( ! cliRepl . logWriter ?. logFilePath ) return [ ] ;
55
58
await cliRepl . logWriter . flush ( ) ; // Ensure any pending data is written first
56
- return readReplLogfile ( cliRepl . logWriter . logFilePath ) ;
59
+ return readReplLogFile ( cliRepl . logWriter . logFilePath ) ;
57
60
}
58
61
59
62
async function startWithExpectedImmediateExit (
@@ -235,6 +238,27 @@ describe('CliRepl', function () {
235
238
} ) ;
236
239
} ) ;
237
240
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
+
238
262
it ( 'writes JS errors to the log file' , async function ( ) {
239
263
input . write ( 'throw new Error("plain js error")\n' ) ;
240
264
await waitBus ( cliRepl . bus , 'mongosh:error' ) ;
@@ -297,7 +321,8 @@ describe('CliRepl', function () {
297
321
'oidcTrustedEndpoints' ,
298
322
'browser' ,
299
323
'updateURL' ,
300
- ] ) ;
324
+ 'disableLogging' ,
325
+ ] satisfies ( keyof CliUserConfig ) [ ] ) ;
301
326
} ) ;
302
327
303
328
it ( 'fails when trying to overwrite mongosh-owned config settings' , async function ( ) {
@@ -453,12 +478,14 @@ describe('CliRepl', function () {
453
478
cliRepl = new CliRepl ( cliReplOptions ) ;
454
479
await cliRepl . start ( '' , { } ) ;
455
480
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
+ } ) ;
462
489
} ) ;
463
490
464
491
it ( 'verifies the Node.js version' , async function ( ) {
@@ -1309,7 +1336,6 @@ describe('CliRepl', function () {
1309
1336
hasCollectionNames : true ,
1310
1337
hasDatabaseNames : true ,
1311
1338
} ) ;
1312
-
1313
1339
context ( 'analytics integration' , function ( ) {
1314
1340
context ( 'with network connectivity' , function ( ) {
1315
1341
let srv : http . Server ;
@@ -1333,6 +1359,7 @@ describe('CliRepl', function () {
1333
1359
. on ( 'data' , ( chunk ) => {
1334
1360
body += chunk ;
1335
1361
} )
1362
+ // eslint-disable-next-line @typescript-eslint/no-misused-promises
1336
1363
. on ( 'end' , async ( ) => {
1337
1364
requests . push ( { req, body } ) ;
1338
1365
totalEventsTracked += JSON . parse ( body ) . batch . length ;
@@ -1343,7 +1370,7 @@ describe('CliRepl', function () {
1343
1370
} )
1344
1371
. listen ( 0 ) ;
1345
1372
await once ( srv , 'listening' ) ;
1346
- host = `http://localhost:${ ( srv . address ( ) as any ) . port } ` ;
1373
+ host = `http://localhost:${ ( srv . address ( ) as AddressInfo ) . port } ` ;
1347
1374
cliReplOptions . analyticsOptions = {
1348
1375
host,
1349
1376
apiKey : '🔑' ,
@@ -1357,6 +1384,48 @@ describe('CliRepl', function () {
1357
1384
srv . close ( ) ;
1358
1385
await once ( srv , 'close' ) ;
1359
1386
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
+ } ) ;
1360
1429
} ) ;
1361
1430
1362
1431
it ( 'times out fast' , async function ( ) {
@@ -1507,11 +1576,11 @@ describe('CliRepl', function () {
1507
1576
1508
1577
it ( 'includes a statement about flushed telemetry in the log' , async function ( ) {
1509
1578
await cliRepl . start ( await testServer . connectionString ( ) , { } ) ;
1510
- const { logFilePath } = cliRepl . logWriter ! ;
1579
+ const { logFilePath } = cliRepl . logWriter as MongoLogWriter ;
1511
1580
input . write ( 'db.hello()\n' ) ;
1512
1581
input . write ( 'exit\n' ) ;
1513
1582
await waitBus ( cliRepl . bus , 'mongosh:closed' ) ;
1514
- const flushEntry = ( await readReplLogfile ( logFilePath ) ) . find (
1583
+ const flushEntry = ( await readReplLogFile ( logFilePath ) ) . find (
1515
1584
( entry : any ) => entry . id === 1_000_000_045
1516
1585
) ;
1517
1586
expect ( flushEntry . attr . flushError ) . to . equal ( null ) ;
0 commit comments