Skip to content

Commit c6eff56

Browse files
nbbeekensyn-zhu
andauthored
fix(logger): replace PassThrough with Writable for log handling COMPASS-9736 (#7222)
* fix(logger): replace PassThrough with Writable for log handling CLOUDP-332732 * fix(logger): replace PassThrough with Writable for log handling CLOUDP-332732 * test: synchronous log call --------- Co-authored-by: Simon Zhu <[email protected]>
1 parent 02bf4bd commit c6eff56

File tree

5 files changed

+124
-13
lines changed

5 files changed

+124
-13
lines changed

packages/compass-connections/src/stores/connections-store-redux.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,6 +1635,17 @@ const connectWithOptions = (
16351635
);
16361636
}
16371637

1638+
// This is used for Data Explorer connection latency tracing
1639+
log.info(
1640+
mongoLogId(1_001_000_005),
1641+
'Compass Connection Attempt Started',
1642+
'Connection attempt started',
1643+
{
1644+
clusterName: connectionInfo.atlasMetadata?.clusterName,
1645+
connectionId: connectionInfo.id,
1646+
}
1647+
);
1648+
16381649
const connectionAttempt = createConnectionAttempt({
16391650
logger: log.unbound,
16401651
proxyOptions: proxyPreferenceToProxyOptions(
@@ -1655,6 +1666,16 @@ const connectWithOptions = (
16551666
// This is how connection attempt indicates that the connection was
16561667
// aborted
16571668
if (!dataService || connectionAttempt.isClosed()) {
1669+
// This is used for Data Explorer connection latency tracing
1670+
log.info(
1671+
mongoLogId(1_001_000_007),
1672+
'Compass Connection Attempt Cancelled',
1673+
'Connection attempt cancelled',
1674+
{
1675+
clusterName: connectionInfo.atlasMetadata?.clusterName,
1676+
connectionId: connectionInfo.id,
1677+
}
1678+
);
16581679
dispatch({
16591680
type: ActionTypes.ConnectionAttemptCancelled,
16601681
connectionId: connectionInfo.id,
@@ -1821,6 +1842,17 @@ const connectWithOptions = (
18211842
connectionInfo
18221843
);
18231844

1845+
// This is used for Data Explorer connection latency tracing
1846+
log.info(
1847+
mongoLogId(1_001_000_006),
1848+
'Compass Connection Attempt Succeeded',
1849+
'Connection attempt succeeded',
1850+
{
1851+
clusterName: connectionInfo.atlasMetadata?.clusterName,
1852+
connectionId: connectionInfo.id,
1853+
}
1854+
);
1855+
18241856
connectionProgress.openConnectionSucceededToast(connectionInfo);
18251857

18261858
// Emit before changing state because some plugins rely on this
@@ -1856,6 +1888,16 @@ const connectWithOptions = (
18561888
);
18571889
}
18581890
} catch (err) {
1891+
log.info(
1892+
mongoLogId(1_001_000_008),
1893+
'Compass Connection Attempt Failed',
1894+
'Connection attempt failed',
1895+
{
1896+
clusterName: connectionInfo.atlasMetadata?.clusterName,
1897+
connectionId: connectionInfo.id,
1898+
error: (err as Error).message,
1899+
}
1900+
);
18591901
dispatch(connectionAttemptError(connectionInfo, err));
18601902
} finally {
18611903
deviceAuthAbortController.abort();

packages/compass-web/src/logger.spec.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,25 @@ describe('useCompassWebLogger', function () {
5959
},
6060
]);
6161
});
62+
63+
it('should call onLog hook synchronously', function () {
64+
let callbackExecuted = false;
65+
const onLog = Sinon.stub().callsFake(() => {
66+
callbackExecuted = true;
67+
});
68+
69+
const {
70+
result: { current: logger },
71+
} = renderLoggerHook({ onLog });
72+
73+
// Callback should not have been called yet
74+
expect(callbackExecuted).to.be.false;
75+
76+
// Call the logger
77+
logger.log.info(mongoLogId(456), 'Test', 'sync test');
78+
79+
// Callback should have been called synchronously before this assertion
80+
expect(callbackExecuted).to.be.true;
81+
expect(onLog).to.have.been.calledOnce;
82+
});
6283
});

packages/compass-web/src/logger.tsx

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { Logger } from '@mongodb-js/compass-logging/provider';
22
import { MongoLogWriter } from 'mongodb-log-writer/mongo-log-writer';
3-
import { PassThrough } from 'stream';
3+
import type { Writable } from 'stream';
44
import { mongoLogId } from '@mongodb-js/compass-logging/provider';
55
import { useRef } from 'react';
66

@@ -62,13 +62,17 @@ export class CompassWebLogger implements Logger {
6262
};
6363
}
6464
) {
65-
const passThrough = new PassThrough({ objectMode: true });
66-
this.log = new MongoLogWriter('', '', passThrough).bindComponent(
67-
this.component
68-
);
69-
passThrough.on('data', (line) => {
70-
callbackRef.current.onLog?.(JSON.parse(line));
71-
});
65+
const target = {
66+
write(line: string, callback: () => void) {
67+
callbackRef.current.onLog?.(JSON.parse(line));
68+
callback();
69+
},
70+
end(callback: () => void) {
71+
callback();
72+
},
73+
} as Writable;
74+
75+
this.log = new MongoLogWriter('', '', target).bindComponent(this.component);
7276

7377
this.debug = createCompassWebDebugger(this.component, this.callbackRef);
7478
}

packages/data-service/src/data-service.spec.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,10 @@ describe('DataService', function () {
167167
{
168168
connectionString:
169169
'mongodb://iLoveJavascript?serverSelectionTimeoutMS=5',
170-
lookup: () => {
171-
throw new Error('test error');
172-
},
170+
lookup: () => ({
171+
wsURL: 'ws://localhost:12345/mongodb/atlas/websocket',
172+
clusterName: 'iLoveJavascript',
173+
}),
173174
},
174175
logCollector
175176
);

packages/data-service/src/data-service.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ import type {
5353
ClientEncryptionCreateDataKeyProviderOptions,
5454
SearchIndexDescription,
5555
ReadPreferenceMode,
56+
CommandStartedEvent,
57+
ConnectionCreatedEvent,
5658
} from 'mongodb';
5759
import { ReadPreference } from 'mongodb';
5860
import ConnectionStringUrl from 'mongodb-connection-string-url';
@@ -1604,10 +1606,12 @@ class DataServiceImpl extends WithLogContext implements DataService {
16041606
debug('connecting...');
16051607
this._isConnecting = true;
16061608

1609+
const clusterName = this._connectionOptions.lookup?.().clusterName;
16071610
this._logger.info(mongoLogId(1_001_000_014), 'Connecting Started', {
16081611
connectionId: this._id,
16091612
url: redactConnectionString(this._connectionOptions.connectionString),
16101613
csfle: this._csfleLogInformation(this._connectionOptions.fleOptions),
1614+
...(clusterName && { clusterName }),
16111615
});
16121616

16131617
try {
@@ -1628,6 +1632,7 @@ class DataServiceImpl extends WithLogContext implements DataService {
16281632
connectionId: this._id,
16291633
isWritable: this.isWritable(),
16301634
isMongos: this.isMongos(),
1635+
...(clusterName && { clusterName }),
16311636
};
16321637

16331638
this._logger.info(
@@ -1664,6 +1669,7 @@ class DataServiceImpl extends WithLogContext implements DataService {
16641669
error && typeof error === 'object' && 'message' in error
16651670
? error?.message
16661671
: 'unknown error',
1672+
...(clusterName && { clusterName }),
16671673
});
16681674
throw error;
16691675
} finally {
@@ -2474,6 +2480,18 @@ class DataServiceImpl extends WithLogContext implements DataService {
24742480

24752481
private _setupListeners(client: MongoClient): void {
24762482
if (client) {
2483+
client.on('connectionCreated', (evt: ConnectionCreatedEvent) => {
2484+
const { address, connectionId } = evt;
2485+
this._logger.info(
2486+
mongoLogId(1_001_000_027),
2487+
'Driver connection created',
2488+
{
2489+
address,
2490+
serverConnectionId: connectionId,
2491+
}
2492+
);
2493+
});
2494+
24772495
client.on(
24782496
'serverDescriptionChanged',
24792497
(evt: ServerDescriptionChangedEvent) => {
@@ -2595,13 +2613,30 @@ class DataServiceImpl extends WithLogContext implements DataService {
25952613
this._emitter.emit('serverHeartbeatFailed', evt);
25962614
});
25972615

2616+
client.on('commandStarted', (evt: CommandStartedEvent) => {
2617+
const { address, connectionId, requestId, commandName, databaseName } =
2618+
evt;
2619+
this._logger.debug(
2620+
mongoLogId(1_001_000_028),
2621+
'Driver command started',
2622+
{
2623+
address,
2624+
databaseName,
2625+
serverConnectionId: connectionId,
2626+
requestId,
2627+
commandName,
2628+
}
2629+
);
2630+
});
2631+
25982632
client.on('commandSucceeded', (evt: CommandSucceededEvent) => {
2599-
const { address, connectionId, duration, commandName } = evt;
2633+
const { address, connectionId, duration, requestId, commandName } = evt;
26002634
this._logger.debug(
26012635
mongoLogId(1_001_000_029),
26022636
'Driver command succeeded',
26032637
{
26042638
address,
2639+
requestId,
26052640
serverConnectionId: connectionId,
26062641
duration,
26072642
commandName,
@@ -2610,11 +2645,19 @@ class DataServiceImpl extends WithLogContext implements DataService {
26102645
});
26112646

26122647
client.on('commandFailed', (evt: CommandFailedEvent) => {
2613-
const { address, connectionId, duration, commandName, failure } = evt;
2648+
const {
2649+
address,
2650+
connectionId,
2651+
duration,
2652+
requestId,
2653+
commandName,
2654+
failure,
2655+
} = evt;
26142656
this._logger.debug(mongoLogId(1_001_000_030), 'Driver command failed', {
26152657
address,
26162658
serverConnectionId: connectionId,
26172659
duration,
2660+
requestId,
26182661
commandName,
26192662
failure: failure.message,
26202663
});

0 commit comments

Comments
 (0)