Skip to content

Commit 31f941e

Browse files
committed
finish accounting for other BSON types
1 parent d21c4ff commit 31f941e

File tree

1 file changed

+116
-9
lines changed

1 file changed

+116
-9
lines changed

src/mongo_logger.ts

Lines changed: 116 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,24 @@
11
import { inspect, promisify } from 'util';
22
import { isUint8Array } from 'util/types';
33

4-
import { type Document, EJSON, type EJSONOptions, type ObjectId } from './bson';
4+
import {
5+
type Binary,
6+
type BSONRegExp,
7+
type BSONSymbol,
8+
type Code,
9+
type DBRef,
10+
type Decimal128,
11+
type Document,
12+
type Double,
13+
EJSON,
14+
type EJSONOptions,
15+
type Int32,
16+
type Long,
17+
type MaxKey,
18+
type MinKey,
19+
type ObjectId,
20+
type Timestamp
21+
} from './bson';
522
import type { CommandStartedEvent } from './cmap/command_monitoring_events';
623
import type {
724
ConnectionCheckedInEvent,
@@ -414,6 +431,20 @@ export interface LogConvertible extends Record<string, any> {
414431
toLog(): Record<string, any>;
415432
}
416433

434+
type BSONObject =
435+
| BSONRegExp
436+
| BSONSymbol
437+
| Code
438+
| DBRef
439+
| Decimal128
440+
| Double
441+
| Int32
442+
| Long
443+
| MaxKey
444+
| MinKey
445+
| ObjectId
446+
| Timestamp
447+
| Binary;
417448
/** @internal */
418449
export function stringifyWithMaxLen(
419450
value: any,
@@ -427,22 +458,98 @@ export function stringifyWithMaxLen(
427458
if (currentLength >= maxDocumentLength) {
428459
return undefined;
429460
}
461+
// Account for root document
462+
if (key === '') {
463+
// Account for starting brace
464+
currentLength += 1;
465+
return value;
466+
}
430467

468+
// +4 accounts for 2 quotation marks, colon and comma after value
431469
currentLength += key.length + 4;
432470

433471
if (typeof value === 'string') {
434-
currentLength += value.length;
472+
// +2 accounts for quotes
473+
currentLength += value.length + 2;
435474
} else if (typeof value === 'number' || typeof value === 'bigint') {
436-
currentLength += 20;
475+
currentLength += String(value).length;
437476
} else if (typeof value === 'boolean') {
438477
currentLength += value ? 4 : 5;
478+
} else if ('buffer' in value && isUint8Array(value.buffer)) {
479+
// Handle binData
480+
currentLength += (value.buffer.byteLength + value.buffer.byteLength * 0.5) | 0;
439481
} else if (value != null && typeof value === 'object' && '_bsontype' in value) {
440-
if (isUint8Array(value.buffer)) {
441-
currentLength += (value.buffer.byteLength + value.buffer.byteLength * 0.5) | 0;
442-
} else if (value._bsontype === 'Binary') {
443-
currentLength += (value.position + value.position * 0.3) | 0;
444-
} else if (value._bsontype === 'Code') {
445-
currentLength += value.code.length;
482+
const v = value as BSONObject;
483+
if (v._bsontype === 'Binary') {
484+
// This is an estimate based on the fact that the base64 is approximately 1.3x the length of
485+
// the actual binary sequence
486+
// Also accounting for stringified fields before the binary sequence and the fields after
487+
// the binary sequence
488+
currentLength += (value.position + value.position * 0.3 + 22 + 17) | 0;
489+
} else if (v._bsontype === 'Code') {
490+
// '{"$code":"<code>"}' or '{"$code":"<code>","$scope":<scope>}'
491+
// TODO: Account for scope?
492+
if (v.scope == null) {
493+
currentLength += v.code.length + 10 + 2;
494+
} else {
495+
// Ignoring actual scope object
496+
currentLength += v.code.length + 10 + 11;
497+
}
498+
} else if (v._bsontype === 'Decimal128') {
499+
// TODO: Is this worth doing here?
500+
currentLength += value.toExtendedJSON().length;
501+
} else if (v._bsontype === 'Double') {
502+
// Doesn't account for representing integers as <value>.0
503+
if ('value' in v && typeof v.value === 'number') currentLength += String(v.value).length;
504+
} else if (v._bsontype === 'Int32') {
505+
if ('value' in v && typeof v.value === 'number') currentLength += String(v.value).length;
506+
} else if (v._bsontype === 'Long') {
507+
if ('toString' in v && typeof v.toString === 'function') {
508+
currentLength += v.toString().length;
509+
}
510+
} else if (v._bsontype === 'MaxKey' || v._bsontype === 'MinKey') {
511+
// '{"$maxKey":1}' or '{"$minKey":1}'
512+
currentLength += 13;
513+
} else if (v._bsontype === 'ObjectId') {
514+
// '{"$oid":"XXXXXXXXXXXXXXXXXXXXXXXX"}'
515+
currentLength += 35;
516+
} else if (
517+
v._bsontype === 'BSONRegExp' &&
518+
'pattern' in v &&
519+
typeof v.pattern === 'string' &&
520+
'options' in v &&
521+
typeof v.options === 'string'
522+
) {
523+
// '{"$regularExpression":{"pattern":"<pattern>","options":"<options>"}}'
524+
currentLength += 34 + v.pattern.length + 13 + v.options.length + 3;
525+
} else if (v._bsontype === 'BSONSymbol' && 'value' in v && v.value === 'string') {
526+
// '{"$symbol": "<value>"}'
527+
currentLength += 12 + v.value.length + 2;
528+
} else if (
529+
v._bsontype === 'Timestamp' &&
530+
't' in v &&
531+
typeof v.t === 'string' &&
532+
'i' in v &&
533+
typeof v.i === 'string'
534+
) {
535+
currentLength += 19 + String(v.t).length + 5 + String(v.i).length + 2;
536+
} else if (v._bsontype === 'DBRef') {
537+
// '{"$ref":"<collection>","$id":<stringified oid>}' or '{"$ref":"<collection>","$id":<stringified oid>,"$db":"test"}'
538+
currentLength += 9;
539+
// account for collection
540+
if ('collection' in v) {
541+
currentLength += v.collection.length + 1;
542+
}
543+
544+
// account for db if present
545+
if ('db' in v && typeof v.db === 'string') {
546+
currentLength += 8 + v.db.length + 2;
547+
}
548+
549+
// account for oid if present
550+
if ('oid' in v) {
551+
currentLength += 35;
552+
}
446553
}
447554
}
448555

0 commit comments

Comments
 (0)