Skip to content

Commit 8a0b25d

Browse files
PR requested changes 2
1 parent 2c3b18a commit 8a0b25d

File tree

3 files changed

+67
-44
lines changed

3 files changed

+67
-44
lines changed

src/mongo_logger.ts

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type { Writable } from 'stream';
21
import { inspect } from 'util';
32

43
import { type Document, EJSON, type EJSONOptions, type ObjectId } from './bson';
@@ -44,7 +43,6 @@ import {
4443
TOPOLOGY_OPENING,
4544
WAITING_FOR_SUITABLE_SERVER
4645
} from './constants';
47-
import { MongoError } from './error';
4846
import type {
4947
ServerClosedEvent,
5048
ServerOpeningEvent,
@@ -193,7 +191,9 @@ export interface MongoLoggerOptions {
193191
/** Max length of embedded EJSON docs. Setting to 0 disables truncation. Defaults to 1000. */
194192
maxDocumentLength: number;
195193
/** Destination for log messages. */
196-
logDestination: Writable | MongoDBLogWritable;
194+
logDestination: MongoDBLogWritable;
195+
/** For internal check to see if error should stop logging. */
196+
logDestinationIsStdErr: boolean;
197197
}
198198

199199
/**
@@ -215,16 +215,14 @@ export function parseSeverityFromString(s?: string): SeverityLevel | null {
215215
}
216216

217217
/** @internal */
218-
export function createStdioLogger(
219-
stream: { write: NodeJS.WriteStream['write'] },
220-
streamName: 'stderr' | 'stdout'
221-
): MongoDBLogWritable {
218+
export function createStdioLogger(stream: {
219+
write: NodeJS.WriteStream['write'];
220+
}): MongoDBLogWritable {
222221
return {
223222
write: (log: Log): unknown => {
224223
stream.write(inspect(log, { compact: true, breakLength: Infinity }), 'utf-8');
225224
return;
226-
},
227-
streamName: streamName
225+
}
228226
};
229227
}
230228

@@ -241,26 +239,26 @@ export function createStdioLogger(
241239
function resolveLogPath(
242240
{ MONGODB_LOG_PATH }: MongoLoggerEnvOptions,
243241
{ mongodbLogPath }: MongoLoggerMongoClientOptions
244-
): MongoDBLogWritable {
242+
): { mongodbLogPath: MongoDBLogWritable; mongodbLogPathIsStdErr: boolean } {
245243
if (typeof mongodbLogPath === 'string' && /^stderr$/i.test(mongodbLogPath)) {
246-
return createStdioLogger(process.stderr, 'stderr');
244+
return { mongodbLogPath: createStdioLogger(process.stderr), mongodbLogPathIsStdErr: true };
247245
}
248246
if (typeof mongodbLogPath === 'string' && /^stdout$/i.test(mongodbLogPath)) {
249-
return createStdioLogger(process.stdout, 'stdout');
247+
return { mongodbLogPath: createStdioLogger(process.stdout), mongodbLogPathIsStdErr: false };
250248
}
251249

252250
if (typeof mongodbLogPath === 'object' && typeof mongodbLogPath?.write === 'function') {
253-
return mongodbLogPath;
251+
return { mongodbLogPath: mongodbLogPath, mongodbLogPathIsStdErr: false };
254252
}
255253

256254
if (MONGODB_LOG_PATH && /^stderr$/i.test(MONGODB_LOG_PATH)) {
257-
return createStdioLogger(process.stderr, 'stderr');
255+
return { mongodbLogPath: createStdioLogger(process.stderr), mongodbLogPathIsStdErr: true };
258256
}
259257
if (MONGODB_LOG_PATH && /^stdout$/i.test(MONGODB_LOG_PATH)) {
260-
return createStdioLogger(process.stdout, 'stdout');
258+
return { mongodbLogPath: createStdioLogger(process.stdout), mongodbLogPathIsStdErr: false };
261259
}
262260

263-
return createStdioLogger(process.stderr, 'stderr');
261+
return { mongodbLogPath: createStdioLogger(process.stderr), mongodbLogPathIsStdErr: true };
264262
}
265263

266264
function resolveSeverityConfiguration(
@@ -286,7 +284,6 @@ export interface Log extends Record<string, any> {
286284
/** @internal */
287285
export interface MongoDBLogWritable {
288286
write(log: Log): PromiseLike<unknown> | any;
289-
streamName?: string;
290287
}
291288

292289
function compareSeverity(s0: SeverityLevel, s1: SeverityLevel): 1 | 0 | -1 {
@@ -711,7 +708,8 @@ export function defaultLogTransform(
711708
export class MongoLogger {
712709
componentSeverities: Record<MongoLoggableComponent, SeverityLevel>;
713710
maxDocumentLength: number;
714-
logDestination: MongoDBLogWritable | Writable;
711+
logDestination: MongoDBLogWritable;
712+
logDestinationIsStdErr: boolean;
715713
pendingLog: PromiseLike<unknown> | unknown = null;
716714

717715
/**
@@ -744,6 +742,7 @@ export class MongoLogger {
744742
this.componentSeverities = options.componentSeverities;
745743
this.maxDocumentLength = options.maxDocumentLength;
746744
this.logDestination = options.logDestination;
745+
this.logDestinationIsStdErr = options.logDestinationIsStdErr;
747746
}
748747

749748
willLog(severity: SeverityLevel, component: MongoLoggableComponent): boolean {
@@ -758,10 +757,13 @@ export class MongoLogger {
758757

759758
private logWriteFailureHandler(error: Error) {
760759
try {
761-
if ((this.logDestination as any)?.streamName === 'stderr') {
762-
throw MongoError;
760+
if (this.logDestinationIsStdErr) {
761+
this.turnOffSeverities();
762+
this.clearPendingLog();
763+
return;
763764
}
764-
this.logDestination = createStdioLogger(process.stderr, 'stderr');
765+
this.logDestination = createStdioLogger(process.stderr);
766+
this.logDestinationIsStdErr = true;
765767
this.clearPendingLog();
766768
this.error(MongoLoggableComponent.CLIENT, {
767769
toLog: function () {
@@ -837,10 +839,12 @@ export class MongoLogger {
837839
clientOptions: MongoLoggerMongoClientOptions
838840
): MongoLoggerOptions {
839841
// client options take precedence over env options
842+
const resolvedLogPath = resolveLogPath(envOptions, clientOptions);
840843
const combinedOptions = {
841844
...envOptions,
842845
...clientOptions,
843-
mongodbLogPath: resolveLogPath(envOptions, clientOptions)
846+
mongodbLogPath: resolvedLogPath.mongodbLogPath,
847+
mongodbLogPathIsStdErr: resolvedLogPath.mongodbLogPathIsStdErr
844848
};
845849
const defaultSeverity = resolveSeverityConfiguration(
846850
combinedOptions.mongodbLogComponentSeverities?.default,
@@ -881,7 +885,8 @@ export class MongoLogger {
881885
combinedOptions.mongodbLogMaxDocumentLength ??
882886
parseUnsignedInteger(combinedOptions.MONGODB_LOG_MAX_DOCUMENT_LENGTH) ??
883887
1000,
884-
logDestination: combinedOptions.mongodbLogPath
888+
logDestination: combinedOptions.mongodbLogPath,
889+
logDestinationIsStdErr: combinedOptions.mongodbLogPathIsStdErr
885890
};
886891
}
887892
}

src/utils.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -171,11 +171,13 @@ export function applyRetryableWrites<T extends HasRetryableWrites>(target: T, db
171171
* @param value - An object that could be a promise
172172
* @returns true if the provided value is a Promise
173173
*/
174-
export function isPromiseLike<T = any>(
175-
value?: PromiseLike<T> | void | unknown
176-
): value is Promise<T> {
177-
// @ts-expect-error since value exists, value.then check is valid ts
178-
return !!value && typeof value.then === 'function';
174+
export function isPromiseLike<T = any>(value?: unknown): value is Promise<T> {
175+
return (
176+
value != null &&
177+
typeof value === 'object' &&
178+
'then' in value &&
179+
typeof value.then === 'function'
180+
);
179181
}
180182

181183
/**

test/unit/mongo_logger.test.ts

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ describe('class MongoLogger', async function () {
6767
const logger = new MongoLogger({
6868
componentSeverities,
6969
maxDocumentLength: 10,
70-
logDestination: stream
70+
logDestination: stream,
71+
logDestinationIsStdErr: false
7172
});
7273

7374
expect(logger).to.have.property('componentSeverities', componentSeverities);
@@ -85,7 +86,8 @@ describe('class MongoLogger', async function () {
8586
} as { buffer: any[]; write: (log: Log) => void };
8687
const logger = new MongoLogger({
8788
componentSeverities: { command: 'error' } as any,
88-
logDestination
89+
logDestination,
90+
logDestinationIsStdErr: false
8991
} as any);
9092

9193
logger.error('command', 'Hello world!');
@@ -105,7 +107,8 @@ describe('class MongoLogger', async function () {
105107

106108
const logger = new MongoLogger({
107109
componentSeverities: { command: 'error' } as any,
108-
logDestination
110+
logDestination,
111+
logDestinationIsStdErr: false
109112
} as any);
110113

111114
logger.error('command', 'Hello world!');
@@ -648,7 +651,8 @@ describe('class MongoLogger', async function () {
648651
componentSeverities: {
649652
topology: 'off'
650653
} as any,
651-
logDestination: stream
654+
logDestination: stream,
655+
logDestinationIsStdErr: false
652656
} as any);
653657

654658
logger[severityLevel]('topology', 'message');
@@ -662,7 +666,8 @@ describe('class MongoLogger', async function () {
662666
componentSeverities: {
663667
command: severityLevel
664668
} as any,
665-
logDestination: stream
669+
logDestination: stream,
670+
logDestinationIsStdErr: false
666671
} as any);
667672

668673
for (let i = index + 1; i < severities.length; i++) {
@@ -681,7 +686,8 @@ describe('class MongoLogger', async function () {
681686
componentSeverities: {
682687
command: severityLevel
683688
} as any,
684-
logDestination: stream
689+
logDestination: stream,
690+
logDestinationIsStdErr: false
685691
} as any);
686692

687693
// Calls all severity logging methods with a level less than or equal to what severityLevel
@@ -706,7 +712,8 @@ describe('class MongoLogger', async function () {
706712
const stream = new BufferingStream();
707713
const logger = new MongoLogger({
708714
componentSeverities: { command: severityLevel } as any,
709-
logDestination: stream
715+
logDestination: stream,
716+
logDestinationIsStdErr: false
710717
} as any);
711718

712719
logger[severityLevel]('command', obj);
@@ -722,7 +729,8 @@ describe('class MongoLogger', async function () {
722729
const stream = new BufferingStream();
723730
const logger = new MongoLogger({
724731
componentSeverities: { command: severityLevel } as any,
725-
logDestination: stream
732+
logDestination: stream,
733+
logDestinationIsStdErr: false
726734
} as any);
727735

728736
logger[severityLevel]('command', obj);
@@ -742,7 +750,8 @@ describe('class MongoLogger', async function () {
742750
const stream = new BufferingStream();
743751
const logger = new MongoLogger({
744752
componentSeverities: { command: severityLevel } as any,
745-
logDestination: stream
753+
logDestination: stream,
754+
logDestinationIsStdErr: false
746755
} as any);
747756

748757
logger[severityLevel]('command', obj);
@@ -760,7 +769,8 @@ describe('class MongoLogger', async function () {
760769
const stream = new BufferingStream();
761770
const logger = new MongoLogger({
762771
componentSeverities: { command: severityLevel } as any,
763-
logDestination: stream
772+
logDestination: stream,
773+
logDestinationIsStdErr: false
764774
} as any);
765775

766776
logger[severityLevel]('command', message);
@@ -780,7 +790,8 @@ describe('class MongoLogger', async function () {
780790
command: 'trace',
781791
connection: 'trace'
782792
} as any,
783-
logDestination: stream
793+
logDestination: stream,
794+
logDestinationIsStdErr: false
784795
} as any);
785796
});
786797

@@ -1358,7 +1369,8 @@ describe('class MongoLogger', async function () {
13581369
const logger = new MongoLogger({
13591370
componentSeverities,
13601371
maxDocumentLength: 1000,
1361-
logDestination: stream
1372+
logDestination: stream,
1373+
logDestinationIsStdErr: false
13621374
});
13631375
// print random message at the debug level
13641376
logger.debug('random message');
@@ -1397,7 +1409,8 @@ describe('class MongoLogger', async function () {
13971409
const logger = new MongoLogger({
13981410
componentSeverities,
13991411
maxDocumentLength: 1000,
1400-
logDestination: stream
1412+
logDestination: stream,
1413+
logDestinationIsStdErr: false
14011414
});
14021415
// print random message at the debug level
14031416
logger.debug('random message');
@@ -1428,7 +1441,8 @@ describe('class MongoLogger', async function () {
14281441
const logger = new MongoLogger({
14291442
componentSeverities,
14301443
maxDocumentLength: 1000,
1431-
logDestination: createStdioLogger(process.stdout, 'stdout')
1444+
logDestination: createStdioLogger(process.stdout),
1445+
logDestinationIsStdErr: false
14321446
});
14331447
logger.debug('random message');
14341448
// manually wait for promise to resolve (takes extra time with promisify)
@@ -1459,7 +1473,8 @@ describe('class MongoLogger', async function () {
14591473
const logger = new MongoLogger({
14601474
componentSeverities,
14611475
maxDocumentLength: 1000,
1462-
logDestination: createStdioLogger(process.stderr, 'stderr')
1476+
logDestination: createStdioLogger(process.stderr),
1477+
logDestinationIsStdErr: true
14631478
});
14641479
expect(() => logger.debug('random message')).to.not.throw(Error);
14651480
expect(Object.keys(logger.componentSeverities).every(key => key === SeverityLevel.OFF));
@@ -1483,7 +1498,8 @@ describe('class MongoLogger', async function () {
14831498
const logger = new MongoLogger({
14841499
componentSeverities,
14851500
maxDocumentLength: 1000,
1486-
logDestination: stream
1501+
logDestination: stream,
1502+
logDestinationIsStdErr: false
14871503
});
14881504

14891505
logger.debug('longer timeout');

0 commit comments

Comments
 (0)