Skip to content

Commit d502eb0

Browse files
authored
feat(NODE-5169): Implement emergency logger (#3610)
1 parent 2a26de3 commit d502eb0

12 files changed

+1259
-88
lines changed

src/cmap/command_monitoring_events.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import type { Document, ObjectId } from '../bson';
2-
import { LEGACY_HELLO_COMMAND, LEGACY_HELLO_COMMAND_CAMEL_CASE } from '../constants';
2+
import {
3+
COMMAND_FAILED,
4+
COMMAND_STARTED,
5+
COMMAND_SUCCEEDED,
6+
LEGACY_HELLO_COMMAND,
7+
LEGACY_HELLO_COMMAND_CAMEL_CASE
8+
} from '../constants';
39
import { calculateDurationInMs, deepCopy } from '../utils';
410
import { Msg, WriteProtocolMessageType } from './commands';
511
import type { Connection } from './connection';
@@ -18,6 +24,8 @@ export class CommandStartedEvent {
1824
address: string;
1925
connectionId?: string | number;
2026
serviceId?: ObjectId;
27+
/** @internal */
28+
name = COMMAND_STARTED;
2129

2230
/**
2331
* Create a started event
@@ -65,6 +73,8 @@ export class CommandSucceededEvent {
6573
commandName: string;
6674
reply: unknown;
6775
serviceId?: ObjectId;
76+
/** @internal */
77+
name = COMMAND_SUCCEEDED;
6878

6979
/**
7080
* Create a succeeded event
@@ -113,6 +123,8 @@ export class CommandFailedEvent {
113123
commandName: string;
114124
failure: Error;
115125
serviceId?: ObjectId;
126+
/** @internal */
127+
name = COMMAND_FAILED;
116128

117129
/**
118130
* Create a failure event

src/cmap/connect.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ function makeConnection(options: MakeConnectionOptions, _callback: Callback<Stre
401401

402402
if ('authorizationError' in socket) {
403403
if (socket.authorizationError && rejectUnauthorized) {
404+
// TODO(NODE-5192): wrap this with a MongoError subclass
404405
return callback(socket.authorizationError);
405406
}
406407
}

src/cmap/connection_pool.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -641,7 +641,10 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
641641
}
642642
}
643643

644-
private destroyConnection(connection: Connection, reason: string) {
644+
private destroyConnection(
645+
connection: Connection,
646+
reason: 'error' | 'idle' | 'stale' | 'poolClosed'
647+
) {
645648
this.emit(
646649
ConnectionPool.CONNECTION_CLOSED,
647650
new ConnectionClosedEvent(this, connection, reason)
@@ -701,7 +704,13 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
701704
this[kPending]--;
702705
this.emit(
703706
ConnectionPool.CONNECTION_CLOSED,
704-
new ConnectionClosedEvent(this, { id: connectOptions.id, serviceId: undefined }, 'error')
707+
new ConnectionClosedEvent(
708+
this,
709+
{ id: connectOptions.id, serviceId: undefined },
710+
'error',
711+
// TODO(NODE-5192): Remove this cast
712+
err as MongoError
713+
)
705714
);
706715
if (err instanceof MongoNetworkError || err instanceof MongoServerError) {
707716
err.connectionGeneration = connectOptions.generation;
@@ -812,7 +821,7 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
812821
const error = this.closed ? new PoolClosedError(this) : new PoolClearedError(this);
813822
this.emit(
814823
ConnectionPool.CONNECTION_CHECK_OUT_FAILED,
815-
new ConnectionCheckOutFailedEvent(this, reason)
824+
new ConnectionCheckOutFailedEvent(this, reason, error)
816825
);
817826
if (waitQueueMember.timer) {
818827
clearTimeout(waitQueueMember.timer);
@@ -865,7 +874,8 @@ export class ConnectionPool extends TypedEventEmitter<ConnectionPoolEvents> {
865874
if (err) {
866875
this.emit(
867876
ConnectionPool.CONNECTION_CHECK_OUT_FAILED,
868-
new ConnectionCheckOutFailedEvent(this, 'connectionError')
877+
// TODO(NODE-5192): Remove this cast
878+
new ConnectionCheckOutFailedEvent(this, 'connectionError', err as MongoError)
869879
);
870880
} else if (connection) {
871881
this[kCheckedOut].add(connection);

src/cmap/connection_pool_events.ts

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
11
import type { ObjectId } from '../bson';
2-
import type { AnyError } from '../error';
2+
import {
3+
CONNECTION_CHECK_OUT_FAILED,
4+
CONNECTION_CHECK_OUT_STARTED,
5+
CONNECTION_CHECKED_IN,
6+
CONNECTION_CHECKED_OUT,
7+
CONNECTION_CLOSED,
8+
CONNECTION_CREATED,
9+
CONNECTION_POOL_CLEARED,
10+
CONNECTION_POOL_CLOSED,
11+
CONNECTION_POOL_CREATED,
12+
CONNECTION_POOL_READY,
13+
CONNECTION_READY
14+
} from '../constants';
15+
import type { MongoError } from '../error';
316
import type { Connection } from './connection';
417
import type { ConnectionPool, ConnectionPoolOptions } from './connection_pool';
518

@@ -8,11 +21,24 @@ import type { ConnectionPool, ConnectionPoolOptions } from './connection_pool';
821
* @public
922
* @category Event
1023
*/
11-
export class ConnectionPoolMonitoringEvent {
24+
export abstract class ConnectionPoolMonitoringEvent {
1225
/** A timestamp when the event was created */
1326
time: Date;
1427
/** The address (host/port pair) of the pool */
1528
address: string;
29+
/** @internal */
30+
abstract name:
31+
| typeof CONNECTION_CHECK_OUT_FAILED
32+
| typeof CONNECTION_CHECK_OUT_STARTED
33+
| typeof CONNECTION_CHECKED_IN
34+
| typeof CONNECTION_CHECKED_OUT
35+
| typeof CONNECTION_CLOSED
36+
| typeof CONNECTION_CREATED
37+
| typeof CONNECTION_POOL_CLEARED
38+
| typeof CONNECTION_POOL_CLOSED
39+
| typeof CONNECTION_POOL_CREATED
40+
| typeof CONNECTION_POOL_READY
41+
| typeof CONNECTION_READY;
1642

1743
/** @internal */
1844
constructor(pool: ConnectionPool) {
@@ -29,6 +55,8 @@ export class ConnectionPoolMonitoringEvent {
2955
export class ConnectionPoolCreatedEvent extends ConnectionPoolMonitoringEvent {
3056
/** The options used to create this connection pool */
3157
options?: ConnectionPoolOptions;
58+
/** @internal */
59+
name = CONNECTION_POOL_CREATED;
3260

3361
/** @internal */
3462
constructor(pool: ConnectionPool) {
@@ -43,6 +71,9 @@ export class ConnectionPoolCreatedEvent extends ConnectionPoolMonitoringEvent {
4371
* @category Event
4472
*/
4573
export class ConnectionPoolReadyEvent extends ConnectionPoolMonitoringEvent {
74+
/** @internal */
75+
name = CONNECTION_POOL_READY;
76+
4677
/** @internal */
4778
constructor(pool: ConnectionPool) {
4879
super(pool);
@@ -55,6 +86,9 @@ export class ConnectionPoolReadyEvent extends ConnectionPoolMonitoringEvent {
5586
* @category Event
5687
*/
5788
export class ConnectionPoolClosedEvent extends ConnectionPoolMonitoringEvent {
89+
/** @internal */
90+
name = CONNECTION_POOL_CLOSED;
91+
5892
/** @internal */
5993
constructor(pool: ConnectionPool) {
6094
super(pool);
@@ -69,6 +103,8 @@ export class ConnectionPoolClosedEvent extends ConnectionPoolMonitoringEvent {
69103
export class ConnectionCreatedEvent extends ConnectionPoolMonitoringEvent {
70104
/** A monotonically increasing, per-pool id for the newly created connection */
71105
connectionId: number | '<monitor>';
106+
/** @internal */
107+
name = CONNECTION_CREATED;
72108

73109
/** @internal */
74110
constructor(pool: ConnectionPool, connection: { id: number | '<monitor>' }) {
@@ -85,6 +121,8 @@ export class ConnectionCreatedEvent extends ConnectionPoolMonitoringEvent {
85121
export class ConnectionReadyEvent extends ConnectionPoolMonitoringEvent {
86122
/** The id of the connection */
87123
connectionId: number | '<monitor>';
124+
/** @internal */
125+
name = CONNECTION_READY;
88126

89127
/** @internal */
90128
constructor(pool: ConnectionPool, connection: Connection) {
@@ -104,17 +142,23 @@ export class ConnectionClosedEvent extends ConnectionPoolMonitoringEvent {
104142
/** The reason the connection was closed */
105143
reason: string;
106144
serviceId?: ObjectId;
145+
/** @internal */
146+
name = CONNECTION_CLOSED;
147+
/** @internal */
148+
error: MongoError | null;
107149

108150
/** @internal */
109151
constructor(
110152
pool: ConnectionPool,
111153
connection: Pick<Connection, 'id' | 'serviceId'>,
112-
reason: string
154+
reason: 'idle' | 'stale' | 'poolClosed' | 'error',
155+
error?: MongoError
113156
) {
114157
super(pool);
115158
this.connectionId = connection.id;
116-
this.reason = reason || 'unknown';
159+
this.reason = reason;
117160
this.serviceId = connection.serviceId;
161+
this.error = error ?? null;
118162
}
119163
}
120164

@@ -124,6 +168,9 @@ export class ConnectionClosedEvent extends ConnectionPoolMonitoringEvent {
124168
* @category Event
125169
*/
126170
export class ConnectionCheckOutStartedEvent extends ConnectionPoolMonitoringEvent {
171+
/** @internal */
172+
name = CONNECTION_CHECK_OUT_STARTED;
173+
127174
/** @internal */
128175
constructor(pool: ConnectionPool) {
129176
super(pool);
@@ -137,12 +184,21 @@ export class ConnectionCheckOutStartedEvent extends ConnectionPoolMonitoringEven
137184
*/
138185
export class ConnectionCheckOutFailedEvent extends ConnectionPoolMonitoringEvent {
139186
/** The reason the attempt to check out failed */
140-
reason: AnyError | string;
187+
reason: string;
188+
/** @internal */
189+
error?: MongoError;
190+
/** @internal */
191+
name = CONNECTION_CHECK_OUT_FAILED;
141192

142193
/** @internal */
143-
constructor(pool: ConnectionPool, reason: AnyError | string) {
194+
constructor(
195+
pool: ConnectionPool,
196+
reason: 'poolClosed' | 'timeout' | 'connectionError',
197+
error?: MongoError
198+
) {
144199
super(pool);
145200
this.reason = reason;
201+
this.error = error;
146202
}
147203
}
148204

@@ -154,6 +210,8 @@ export class ConnectionCheckOutFailedEvent extends ConnectionPoolMonitoringEvent
154210
export class ConnectionCheckedOutEvent extends ConnectionPoolMonitoringEvent {
155211
/** The id of the connection */
156212
connectionId: number | '<monitor>';
213+
/** @internal */
214+
name = CONNECTION_CHECKED_OUT;
157215

158216
/** @internal */
159217
constructor(pool: ConnectionPool, connection: Connection) {
@@ -170,6 +228,8 @@ export class ConnectionCheckedOutEvent extends ConnectionPoolMonitoringEvent {
170228
export class ConnectionCheckedInEvent extends ConnectionPoolMonitoringEvent {
171229
/** The id of the connection */
172230
connectionId: number | '<monitor>';
231+
/** @internal */
232+
name = CONNECTION_CHECKED_IN;
173233

174234
/** @internal */
175235
constructor(pool: ConnectionPool, connection: Connection) {
@@ -188,6 +248,8 @@ export class ConnectionPoolClearedEvent extends ConnectionPoolMonitoringEvent {
188248
serviceId?: ObjectId;
189249

190250
interruptInUseConnections?: boolean;
251+
/** @internal */
252+
name = CONNECTION_POOL_CLEARED;
191253

192254
/** @internal */
193255
constructor(

src/connection_string.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1280,5 +1280,6 @@ export const DEFAULT_OPTIONS = new CaseInsensitiveMap(
12801280
*/
12811281
export const FEATURE_FLAGS = new Set([
12821282
Symbol.for('@@mdb.skipPingOnConnect'),
1283-
Symbol.for('@@mdb.enableMongoLogger')
1283+
Symbol.for('@@mdb.enableMongoLogger'),
1284+
Symbol.for('@@mdb.internalLoggerConfig')
12841285
]);

src/constants.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,27 @@ export const SERVER_DESCRIPTION_CHANGED = 'serverDescriptionChanged' as const;
2323
export const TOPOLOGY_OPENING = 'topologyOpening' as const;
2424
export const TOPOLOGY_CLOSED = 'topologyClosed' as const;
2525
export const TOPOLOGY_DESCRIPTION_CHANGED = 'topologyDescriptionChanged' as const;
26+
/** @internal */
2627
export const CONNECTION_POOL_CREATED = 'connectionPoolCreated' as const;
28+
/** @internal */
2729
export const CONNECTION_POOL_CLOSED = 'connectionPoolClosed' as const;
30+
/** @internal */
2831
export const CONNECTION_POOL_CLEARED = 'connectionPoolCleared' as const;
32+
/** @internal */
2933
export const CONNECTION_POOL_READY = 'connectionPoolReady' as const;
34+
/** @internal */
3035
export const CONNECTION_CREATED = 'connectionCreated' as const;
36+
/** @internal */
3137
export const CONNECTION_READY = 'connectionReady' as const;
38+
/** @internal */
3239
export const CONNECTION_CLOSED = 'connectionClosed' as const;
40+
/** @internal */
3341
export const CONNECTION_CHECK_OUT_STARTED = 'connectionCheckOutStarted' as const;
42+
/** @internal */
3443
export const CONNECTION_CHECK_OUT_FAILED = 'connectionCheckOutFailed' as const;
44+
/** @internal */
3545
export const CONNECTION_CHECKED_OUT = 'connectionCheckedOut' as const;
46+
/** @internal */
3647
export const CONNECTION_CHECKED_IN = 'connectionCheckedIn' as const;
3748
export const CLUSTER_TIME_RECEIVED = 'clusterTimeReceived' as const;
3849
export const COMMAND_STARTED = 'commandStarted' as const;

src/index.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,20 @@ export type { ConnectionPoolMetrics } from './cmap/metrics';
248248
export type { StreamDescription, StreamDescriptionOptions } from './cmap/stream_description';
249249
export type { CompressorName } from './cmap/wire_protocol/compression';
250250
export type { CollectionOptions, CollectionPrivate, ModifyResult } from './collection';
251-
export type { MONGO_CLIENT_EVENTS } from './constants';
251+
export type {
252+
CONNECTION_CHECK_OUT_FAILED,
253+
CONNECTION_CHECK_OUT_STARTED,
254+
CONNECTION_CHECKED_IN,
255+
CONNECTION_CHECKED_OUT,
256+
CONNECTION_CLOSED,
257+
CONNECTION_CREATED,
258+
CONNECTION_POOL_CLEARED,
259+
CONNECTION_POOL_CLOSED,
260+
CONNECTION_POOL_CREATED,
261+
CONNECTION_POOL_READY,
262+
CONNECTION_READY,
263+
MONGO_CLIENT_EVENTS
264+
} from './constants';
252265
export type {
253266
AbstractCursorEvents,
254267
AbstractCursorOptions,
@@ -290,6 +303,11 @@ export type {
290303
WithSessionCallback
291304
} from './mongo_client';
292305
export type {
306+
Log,
307+
LogConvertible,
308+
Loggable,
309+
LoggableEvent,
310+
MongoDBLogWritable,
293311
MongoLoggableComponent,
294312
MongoLogger,
295313
MongoLoggerEnvOptions,

0 commit comments

Comments
 (0)