Skip to content

Commit cc60084

Browse files
committed
feat(NODE-4815): add maybeTruncate
1 parent d502eb0 commit cc60084

File tree

2 files changed

+67
-4
lines changed

2 files changed

+67
-4
lines changed

src/mongo_logger.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ export const SeverityLevel = Object.freeze({
5353
OFF: 'off'
5454
} as const);
5555

56+
/** @internal */
57+
export const DEFAULT_MAX_DOCUMENT_LENGTH = 1000;
5658
/** @internal */
5759
export type SeverityLevel = (typeof SeverityLevel)[keyof typeof SeverityLevel];
5860

@@ -254,6 +256,18 @@ export interface LogConvertible extends Record<string, any> {
254256
toLog(): Record<string, any>;
255257
}
256258

259+
/** @internal */
260+
export function maybeTruncate(
261+
ejson: string,
262+
maxDocumentLength: number = DEFAULT_MAX_DOCUMENT_LENGTH
263+
): string {
264+
if (maxDocumentLength === 0) {
265+
return ejson;
266+
}
267+
268+
return ejson.length > maxDocumentLength ? `${ejson.slice(0, maxDocumentLength)}...` : ejson;
269+
}
270+
257271
/** @internal */
258272
export type Loggable = LoggableEvent | LogConvertible;
259273

@@ -292,22 +306,23 @@ function attachConnectionFields(
292306
}
293307

294308
function defaultLogTransform(
295-
logObject: LoggableEvent | Record<string, any>
309+
logObject: LoggableEvent | Record<string, any>,
310+
maxDocumentLength: number = DEFAULT_MAX_DOCUMENT_LENGTH
296311
): Omit<Log, 's' | 't' | 'c'> {
297312
let log: Omit<Log, 's' | 't' | 'c'> = Object.create(null);
298313

299314
switch (logObject.name) {
300315
case COMMAND_STARTED:
301316
log = attachCommandFields(log, logObject);
302317
log.message = 'Command started';
303-
log.command = EJSON.stringify(logObject.command);
318+
log.command = maybeTruncate(EJSON.stringify(logObject.command), maxDocumentLength);
304319
log.databaseName = logObject.databaseName;
305320
return log;
306321
case COMMAND_SUCCEEDED:
307322
log = attachCommandFields(log, logObject);
308323
log.message = 'Command succeeded';
309324
log.durationMS = logObject.duration;
310-
log.reply = EJSON.stringify(logObject.reply);
325+
log.reply = maybeTruncate(EJSON.stringify(logObject.reply), maxDocumentLength);
311326
return log;
312327
case COMMAND_FAILED:
313328
log = attachCommandFields(log, logObject);
@@ -452,7 +467,7 @@ export class MongoLogger {
452467
if (isLogConvertible(message)) {
453468
logMessage = { ...logMessage, ...message.toLog() };
454469
} else {
455-
logMessage = { ...logMessage, ...defaultLogTransform(message) };
470+
logMessage = { ...logMessage, ...defaultLogTransform(message, this.maxDocumentLength) };
456471
}
457472
}
458473
this.logDestination.write(logMessage);

test/unit/mongo_logger.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import {
1919
CONNECTION_POOL_CREATED,
2020
CONNECTION_POOL_READY,
2121
CONNECTION_READY,
22+
DEFAULT_MAX_DOCUMENT_LENGTH,
2223
Log,
24+
maybeTruncate,
2325
MongoDBLogWritable,
2426
MongoLogger,
2527
MongoLoggerOptions,
@@ -1239,4 +1241,50 @@ describe('class MongoLogger', function () {
12391241
});
12401242
}
12411243
});
1244+
1245+
describe('maybeTruncate', function () {
1246+
let largeEjsonString: string;
1247+
let smallEjsonString: string;
1248+
before(function () {
1249+
const largeDoc = {};
1250+
for (let i = 0; i < DEFAULT_MAX_DOCUMENT_LENGTH; i++) {
1251+
largeDoc[`test${i}`] = `Hello_${i}`;
1252+
}
1253+
largeEjsonString = EJSON.stringify(largeDoc);
1254+
const smallDoc = { test: 'Hello' };
1255+
smallEjsonString = EJSON.stringify(smallDoc);
1256+
});
1257+
1258+
context('when maxDocumentLength = 0', function () {
1259+
it('does not truncate document', function () {
1260+
expect(maybeTruncate(largeEjsonString, 0)).to.equal(largeEjsonString);
1261+
});
1262+
});
1263+
1264+
context('when maxDocumentLength is non-zero', function () {
1265+
context('when document has length greater than maxDocumentLength', function () {
1266+
it('truncates ejson string to length of maxDocumentLength + 3', function () {
1267+
expect(maybeTruncate(largeEjsonString)).to.have.lengthOf(DEFAULT_MAX_DOCUMENT_LENGTH + 3);
1268+
});
1269+
it('ends with "..."', function () {
1270+
expect(maybeTruncate(largeEjsonString)).to.match(/^.*\.\.\.$/);
1271+
});
1272+
});
1273+
1274+
context('when document has length less than or equal to maxDocumentLength', function () {
1275+
it('does not truncate document', function () {
1276+
expect(maybeTruncate(smallEjsonString)).to.equal(smallEjsonString);
1277+
});
1278+
it('does not end with "..."', function () {
1279+
expect(maybeTruncate(smallEjsonString)).to.not.match(/^.*\.\.\./);
1280+
});
1281+
1282+
it('produces valid relaxed EJSON', function () {
1283+
expect(() => {
1284+
EJSON.parse(maybeTruncate(smallEjsonString));
1285+
}).to.not.throw();
1286+
});
1287+
});
1288+
});
1289+
});
12421290
});

0 commit comments

Comments
 (0)