Skip to content

Commit 41b066b

Browse files
authored
perf(NODE-6452): Optimize CommandStartedEvent and CommandSucceededEvent constructors (#4371)
1 parent cba0a2a commit 41b066b

File tree

3 files changed

+10
-137
lines changed

3 files changed

+10
-137
lines changed

src/cmap/command_monitoring_events.ts

+10-55
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
LEGACY_HELLO_COMMAND,
77
LEGACY_HELLO_COMMAND_CAMEL_CASE
88
} from '../constants';
9-
import { calculateDurationInMs, deepCopy } from '../utils';
9+
import { calculateDurationInMs } from '../utils';
1010
import {
1111
DocumentSequence,
1212
OpMsgRequest,
@@ -125,7 +125,7 @@ export class CommandSucceededEvent {
125125
this.requestId = command.requestId;
126126
this.commandName = commandName;
127127
this.duration = calculateDurationInMs(started);
128-
this.reply = maybeRedact(commandName, cmd, extractReply(command, reply));
128+
this.reply = maybeRedact(commandName, cmd, extractReply(reply));
129129
this.serverConnectionId = serverConnectionId;
130130
}
131131

@@ -214,7 +214,6 @@ const HELLO_COMMANDS = new Set(['hello', LEGACY_HELLO_COMMAND, LEGACY_HELLO_COMM
214214

215215
// helper methods
216216
const extractCommandName = (commandDoc: Document) => Object.keys(commandDoc)[0];
217-
const namespace = (command: OpQueryRequest) => command.ns;
218217
const collectionName = (command: OpQueryRequest) => command.ns.split('.')[1];
219218
const maybeRedact = (commandName: string, commandDoc: Document, result: Error | Document) =>
220219
SENSITIVE_COMMANDS.has(commandName) ||
@@ -242,19 +241,10 @@ const LEGACY_FIND_OPTIONS_MAP = {
242241
returnFieldSelector: 'projection'
243242
} as const;
244243

245-
const OP_QUERY_KEYS = [
246-
'tailable',
247-
'oplogReplay',
248-
'noCursorTimeout',
249-
'awaitData',
250-
'partial',
251-
'exhaust'
252-
] as const;
253-
254244
/** Extract the actual command from the query, possibly up-converting if it's a legacy format */
255245
function extractCommand(command: WriteProtocolMessageType): Document {
256246
if (command instanceof OpMsgRequest) {
257-
const cmd = deepCopy(command.command);
247+
const cmd = { ...command.command };
258248
// For OP_MSG with payload type 1 we need to pull the documents
259249
// array out of the document sequence for monitoring.
260250
if (cmd.ops instanceof DocumentSequence) {
@@ -276,72 +266,37 @@ function extractCommand(command: WriteProtocolMessageType): Document {
276266
result = { find: collectionName(command) };
277267
Object.keys(LEGACY_FIND_QUERY_MAP).forEach(key => {
278268
if (command.query[key] != null) {
279-
result[LEGACY_FIND_QUERY_MAP[key]] = deepCopy(command.query[key]);
269+
result[LEGACY_FIND_QUERY_MAP[key]] = { ...command.query[key] };
280270
}
281271
});
282272
}
283273

284274
Object.keys(LEGACY_FIND_OPTIONS_MAP).forEach(key => {
285275
const legacyKey = key as keyof typeof LEGACY_FIND_OPTIONS_MAP;
286276
if (command[legacyKey] != null) {
287-
result[LEGACY_FIND_OPTIONS_MAP[legacyKey]] = deepCopy(command[legacyKey]);
288-
}
289-
});
290-
291-
OP_QUERY_KEYS.forEach(key => {
292-
if (command[key]) {
293-
result[key] = command[key];
277+
result[LEGACY_FIND_OPTIONS_MAP[legacyKey]] = command[legacyKey];
294278
}
295279
});
296280

297-
if (command.pre32Limit != null) {
298-
result.limit = command.pre32Limit;
299-
}
300-
301-
if (command.query.$explain) {
302-
return { explain: result };
303-
}
304281
return result;
305282
}
306283

307-
const clonedQuery: Record<string, unknown> = {};
308-
const clonedCommand: Record<string, unknown> = {};
284+
let clonedQuery: Record<string, unknown> = {};
285+
const clonedCommand: Record<string, unknown> = { ...command };
309286
if (command.query) {
310-
for (const k in command.query) {
311-
clonedQuery[k] = deepCopy(command.query[k]);
312-
}
287+
clonedQuery = { ...command.query };
313288
clonedCommand.query = clonedQuery;
314289
}
315290

316-
for (const k in command) {
317-
if (k === 'query') continue;
318-
clonedCommand[k] = deepCopy((command as unknown as Record<string, unknown>)[k]);
319-
}
320291
return command.query ? clonedQuery : clonedCommand;
321292
}
322293

323-
function extractReply(command: WriteProtocolMessageType, reply?: Document) {
294+
function extractReply(reply?: Document) {
324295
if (!reply) {
325296
return reply;
326297
}
327298

328-
if (command instanceof OpMsgRequest) {
329-
return deepCopy(reply.result ? reply.result : reply);
330-
}
331-
332-
// is this a legacy find command?
333-
if (command.query && command.query.$query != null) {
334-
return {
335-
ok: 1,
336-
cursor: {
337-
id: deepCopy(reply.cursorId),
338-
ns: namespace(command),
339-
firstBatch: deepCopy(reply.documents)
340-
}
341-
};
342-
}
343-
344-
return deepCopy(reply.result ? reply.result : reply);
299+
return reply.result ? reply.result : reply;
345300
}
346301

347302
function extractConnectionDetails(connection: Connection) {

src/utils.ts

-37
Original file line numberDiff line numberDiff line change
@@ -620,43 +620,6 @@ export function isRecord(
620620
return true;
621621
}
622622

623-
/**
624-
* Make a deep copy of an object
625-
*
626-
* NOTE: This is not meant to be the perfect implementation of a deep copy,
627-
* but instead something that is good enough for the purposes of
628-
* command monitoring.
629-
*/
630-
export function deepCopy<T>(value: T): T {
631-
if (value == null) {
632-
return value;
633-
} else if (Array.isArray(value)) {
634-
return value.map(item => deepCopy(item)) as unknown as T;
635-
} else if (isRecord(value)) {
636-
const res = {} as any;
637-
for (const key in value) {
638-
res[key] = deepCopy(value[key]);
639-
}
640-
return res;
641-
}
642-
643-
const ctor = (value as any).constructor;
644-
if (ctor) {
645-
switch (ctor.name.toLowerCase()) {
646-
case 'date':
647-
return new ctor(Number(value));
648-
case 'map':
649-
return new Map(value as any) as unknown as T;
650-
case 'set':
651-
return new Set(value as any) as unknown as T;
652-
case 'buffer':
653-
return Buffer.from(value as unknown as Buffer) as unknown as T;
654-
}
655-
}
656-
657-
return value;
658-
}
659-
660623
type ListNode<T> = {
661624
value: T;
662625
next: ListNode<T> | HeadNode<T>;

test/integration/command-logging-and-monitoring/command_monitoring.test.ts

-45
Original file line numberDiff line numberDiff line change
@@ -603,49 +603,4 @@ describe('Command Monitoring', function () {
603603
});
604604
}
605605
});
606-
607-
describe('Internal state references', function () {
608-
let client;
609-
610-
beforeEach(function () {
611-
client = this.configuration.newClient(
612-
{ writeConcern: { w: 1 } },
613-
{ maxPoolSize: 1, monitorCommands: true }
614-
);
615-
});
616-
617-
afterEach(function (done) {
618-
client.close(done);
619-
});
620-
621-
// NODE-1502
622-
it('should not allow mutation of internal state from commands returned by event monitoring', function () {
623-
const started = [];
624-
const succeeded = [];
625-
client.on('commandStarted', filterForCommands('insert', started));
626-
client.on('commandSucceeded', filterForCommands('insert', succeeded));
627-
const documentToInsert = { a: { b: 1 } };
628-
const db = client.db(this.configuration.db);
629-
return db
630-
.collection('apm_test')
631-
.insertOne(documentToInsert)
632-
.then(r => {
633-
expect(r).to.have.property('insertedId').that.is.an('object');
634-
expect(started).to.have.lengthOf(1);
635-
// Check if contents of returned document are equal to document inserted (by value)
636-
expect(documentToInsert).to.deep.equal(started[0].command.documents[0]);
637-
// Check if the returned document is a clone of the original. This confirms that the
638-
// reference is not the same.
639-
expect(documentToInsert !== started[0].command.documents[0]).to.equal(true);
640-
expect(documentToInsert.a !== started[0].command.documents[0].a).to.equal(true);
641-
642-
started[0].command.documents[0].a.b = 2;
643-
expect(documentToInsert.a.b).to.equal(1);
644-
645-
expect(started[0].commandName).to.equal('insert');
646-
expect(started[0].command.insert).to.equal('apm_test');
647-
expect(succeeded).to.have.lengthOf(1);
648-
});
649-
});
650-
});
651606
});

0 commit comments

Comments
 (0)