Skip to content
This repository was archived by the owner on Feb 4, 2022. It is now read-only.

Commit 37dce9c

Browse files
committed
feat(apm): add events for command monitoring support in core
NODE-1390
1 parent 0e660eb commit 37dce9c

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

lib/connection/apm.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
'use strict';
2+
3+
/** Commands that we want to redact because of the sensitive nature of their contents */
4+
const SENSITIVE_COMMANDS = [
5+
'authenticate',
6+
'saslStart',
7+
'saslContinue',
8+
'getnonce',
9+
'createUser',
10+
'updateUser',
11+
'copydbgetnonce',
12+
'copydbsaslstart',
13+
'copydb'
14+
];
15+
16+
// helper methods
17+
function extractCommand(command) { return command.query ? command.query : command; }
18+
function extractCommandName(command) { return Object.keys(command)[0]; }
19+
function calculateDuration(started) { return Date.now() - started; }
20+
function generateConnectionId(pool) { return `${pool.options.host}:${pool.options.port}`; }
21+
function maybeRedact(commandName, result) {
22+
return SENSITIVE_COMMANDS.indexOf(commandName) !== -1 ? {} : result;
23+
}
24+
25+
/** An event indicating the start of a given command */
26+
class CommandStartedEvent {
27+
/**
28+
* Create a started event
29+
*
30+
* @param {Pool} pool the pool that originated the command
31+
* @param {Object} command the command
32+
*/
33+
constructor (pool, command) {
34+
const cmd = extractCommand(command);
35+
const commandName = extractCommandName(cmd);
36+
37+
// NOTE: remove in major revision, this is not spec behavior
38+
if (SENSITIVE_COMMANDS.indexOf(commandName) !== -1) {
39+
this.commandObj = {};
40+
this.commandObj[commandName] = true;
41+
}
42+
43+
Object.assign(this, {
44+
command: cmd,
45+
databaseName: command.ns.split('.')[0],
46+
commandName: extractCommandName(cmd),
47+
requestId: command.requestId,
48+
connectionId: generateConnectionId(pool)
49+
});
50+
}
51+
};
52+
53+
/** An event indicating the success of a given command */
54+
class CommandSucceededEvent {
55+
/**
56+
* Create a succeeded event
57+
*
58+
* @param {Pool} pool the pool that originated the command
59+
* @param {Object} command the command
60+
* @param {Object} reply the reply for this command from the server
61+
* @param {Number} started a timestamp of when the command was first sent to calculate duration
62+
*/
63+
constructor(pool, command, reply, started) {
64+
const cmd = extractCommand(command);
65+
const commandName = extractCommandName(cmd);
66+
67+
Object.assign(this, {
68+
duration: calculateDuration(started),
69+
commandName,
70+
reply: maybeRedact(commandName, reply.result),
71+
requestId: command.requestId,
72+
connectionId: generateConnectionId(pool)
73+
});
74+
}
75+
};
76+
77+
/** An event indicating the failure of a given command */
78+
class CommandFailedEvent {
79+
/**
80+
* Create a failure event
81+
*
82+
* @param {Pool} pool the pool that originated the command
83+
* @param {Object} command the command
84+
* @param {MongoError|Object} error the generated error or a server error response
85+
* @param {Number} started a timestamp of when the command was first sent to calculate duration
86+
*/
87+
constructor(pool, command, error, started) {
88+
const cmd = extractCommand(command);
89+
const commandName = extractCommandName(cmd);
90+
91+
Object.assign(this, {
92+
duration: calculateDuration(started),
93+
commandName,
94+
failure: maybeRedact(commandName, error),
95+
requestId: command.requestId,
96+
connectionId: generateConnectionId(pool)
97+
});
98+
}
99+
};
100+
101+
module.exports = {
102+
CommandStartedEvent,
103+
CommandSucceededEvent,
104+
CommandFailedEvent
105+
};

0 commit comments

Comments
 (0)