Skip to content

Commit 9bd360c

Browse files
committed
feat: include connectionId for APM with new CMAP connection pool
With the new CMAP pool we have the ability to include a connection id in all of our APM messages, allowing users to correlate APM events with CMAP events for greater traceability. NODE-2419
1 parent 9541410 commit 9bd360c

File tree

2 files changed

+40
-9
lines changed

2 files changed

+40
-9
lines changed

lib/core/connection/apm.js

+23-6
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const collectionName = command => command.ns.split('.')[1];
2525
const generateConnectionId = pool =>
2626
pool.options ? `${pool.options.host}:${pool.options.port}` : pool.address;
2727
const maybeRedact = (commandName, result) => (SENSITIVE_COMMANDS.has(commandName) ? {} : result);
28+
const isLegacyPool = pool => pool.s && pool.queue;
2829

2930
const LEGACY_FIND_QUERY_MAP = {
3031
$query: 'filter',
@@ -151,6 +152,22 @@ const extractReply = (command, reply) => {
151152
return reply && reply.result ? reply.result : reply;
152153
};
153154

155+
const extractConnectionDetails = pool => {
156+
if (isLegacyPool(pool)) {
157+
return {
158+
connectionId: generateConnectionId(pool)
159+
};
160+
}
161+
162+
// APM in the modern pool is done at the `Connection` level, so we rename it here for
163+
// readability.
164+
const connection = pool;
165+
return {
166+
address: connection.address,
167+
connectionId: connection.id
168+
};
169+
};
170+
154171
/** An event indicating the start of a given command */
155172
class CommandStartedEvent {
156173
/**
@@ -162,15 +179,15 @@ class CommandStartedEvent {
162179
constructor(pool, command) {
163180
const cmd = extractCommand(command);
164181
const commandName = extractCommandName(cmd);
182+
const connectionDetails = extractConnectionDetails(pool);
165183

166184
// NOTE: remove in major revision, this is not spec behavior
167185
if (SENSITIVE_COMMANDS.has(commandName)) {
168186
this.commandObj = {};
169187
this.commandObj[commandName] = true;
170188
}
171189

172-
Object.assign(this, {
173-
connectionId: generateConnectionId(pool),
190+
Object.assign(this, connectionDetails, {
174191
requestId: command.requestId,
175192
databaseName: databaseName(command),
176193
commandName,
@@ -192,9 +209,9 @@ class CommandSucceededEvent {
192209
constructor(pool, command, reply, started) {
193210
const cmd = extractCommand(command);
194211
const commandName = extractCommandName(cmd);
212+
const connectionDetails = extractConnectionDetails(pool);
195213

196-
Object.assign(this, {
197-
connectionId: generateConnectionId(pool),
214+
Object.assign(this, connectionDetails, {
198215
requestId: command.requestId,
199216
commandName,
200217
duration: calculateDurationInMs(started),
@@ -216,9 +233,9 @@ class CommandFailedEvent {
216233
constructor(pool, command, error, started) {
217234
const cmd = extractCommand(command);
218235
const commandName = extractCommandName(cmd);
236+
const connectionDetails = extractConnectionDetails(pool);
219237

220-
Object.assign(this, {
221-
connectionId: generateConnectionId(pool),
238+
Object.assign(this, connectionDetails, {
222239
requestId: command.requestId,
223240
commandName,
224241
duration: calculateDurationInMs(started),

test/functional/apm.test.js

+17-3
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,15 @@ describe('APM', function() {
224224
.then(() => {
225225
expect(started).to.have.lengthOf(2);
226226

227-
// Ensure command was not sent to the primary
228-
expect(started[0].connectionId).to.not.equal(started[1].connectionId);
227+
if (self.configuration.usingUnifiedTopology()) {
228+
expect(started[0])
229+
.property('address')
230+
.to.not.equal(started[1].address);
231+
} else {
232+
// Ensure command was not sent to the primary
233+
expect(started[0].connectionId).to.not.equal(started[1].connectionId);
234+
}
235+
229236
return client.close();
230237
});
231238
});
@@ -274,7 +281,14 @@ describe('APM', function() {
274281
expect(started).to.have.lengthOf(2);
275282

276283
// Ensure command was not sent to the primary
277-
expect(started[0].connectionId).to.not.equal(started[1].connectionId);
284+
if (self.configuration.usingUnifiedTopology()) {
285+
expect(started[0])
286+
.property('address')
287+
.to.not.equal(started[1].address);
288+
} else {
289+
expect(started[0].connectionId).to.not.equal(started[1].connectionId);
290+
}
291+
278292
return client.close();
279293
});
280294
});

0 commit comments

Comments
 (0)