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

Commit

Permalink
fix(apm): fix upconversion for OP_QUERY in apm
Browse files Browse the repository at this point in the history
Properly upconverts query-wrapped commands in OP_QUERY to the
proper apm format

Fixes NODE-1655
  • Loading branch information
daprahamian committed Sep 10, 2018
1 parent bf0315d commit f969bee
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 6 deletions.
18 changes: 12 additions & 6 deletions lib/connection/apm.js
Expand Up @@ -76,12 +76,18 @@ const extractCommand = command => {
}

if (command.query && command.query.$query) {
// upconvert legacy find command
const result = { find: collectionName(command) };
Object.keys(LEGACY_FIND_QUERY_MAP).forEach(key => {
if (typeof command.query[key] !== 'undefined')
result[LEGACY_FIND_QUERY_MAP[key]] = command.query[key];
});
let result;
if (command.ns === 'admin.$cmd') {
// upconvert legacy command
result = Object.assign({}, command.query.$query);
} else {
// upconvert legacy find command
result = { find: collectionName(command) };
Object.keys(LEGACY_FIND_QUERY_MAP).forEach(key => {
if (typeof command.query[key] !== 'undefined')
result[LEGACY_FIND_QUERY_MAP[key]] = command.query[key];
});
}

Object.keys(LEGACY_FIND_OPTIONS_MAP).forEach(key => {
if (typeof command.options[key] !== 'undefined')
Expand Down
157 changes: 157 additions & 0 deletions test/tests/unit/apm_tests.js
@@ -0,0 +1,157 @@
'use strict';

const Pool = require('../../../lib/connection/pool');
const BSON = require('bson');
const apm = require('../../../lib/connection/apm');
const expect = require('chai').expect;

const commands = require('../../../lib/connection/commands');
const Query = commands.Query;
const KillCursor = commands.KillCursor;
const GetMore = commands.GetMore;

const bson = new BSON();
const pool = new Pool({}, { bson });

describe('APM tests', function() {
describe('CommandStartedEvent', function() {
// Only run on single topology since these are unit tests
const metadata = { requires: { topology: ['single'] } };

it('should wrap a basic query option', metadata, function() {
const db = 'test1';
const coll = 'testingQuery';
const query = new Query(
bson,
`${db}.${coll}`,
{
testCmd: 1,
fizz: 'buzz',
star: 'trek'
},
{}
);

const startEvent = new apm.CommandStartedEvent(pool, query);

expect(startEvent).to.have.property('commandName', 'testCmd');
expect(startEvent).to.have.property('databaseName', db);
expect(startEvent).to.have.property('requestId', query.requestId);
expect(startEvent)
.to.have.property('connectionId')
.that.is.a('string');
expect(startEvent)
.to.have.property('command')
.that.deep.equals(query.query);
});

it('should wrap a basic killCursor command', metadata, function() {
const db = 'test2';
const coll = 'testingKillCursors';
const killCursor = new KillCursor(bson, `${db}.${coll}`, [12, 42, 57]);

const startEvent = new apm.CommandStartedEvent(pool, killCursor);

expect(startEvent).to.have.property('commandName', 'killCursors');
expect(startEvent).to.have.property('databaseName', db);
expect(startEvent).to.have.property('requestId', killCursor.requestId);
expect(startEvent)
.to.have.property('connectionId')
.that.is.a('string');
expect(startEvent)
.to.have.property('command')
.that.deep.equals({
killCursors: coll,
cursors: killCursor.cursorIds
});
});

it('should wrap a basic GetMore command', metadata, function() {
const db = 'test3';
const coll = 'testingGetMore';
const numberToReturn = 321;
const getMore = new GetMore(bson, `${db}.${coll}`, 5525, { numberToReturn });

const startEvent = new apm.CommandStartedEvent(pool, getMore);

expect(startEvent).to.have.property('commandName', 'getMore');
expect(startEvent).to.have.property('databaseName', db);
expect(startEvent).to.have.property('requestId', getMore.requestId);
expect(startEvent)
.to.have.property('connectionId')
.that.is.a('string');
expect(startEvent)
.to.have.property('command')
.that.deep.equals({
getMore: getMore.cursorId,
collection: coll,
batchSize: numberToReturn
});
});

it(
'should upconvert a Query wrapping a command into the corresponding command',
metadata,
function() {
const db = 'admin';
const coll = '$cmd';
const query = new Query(
bson,
`${db}.${coll}`,
{
$query: {
testCmd: 1,
fizz: 'buzz',
star: 'trek'
}
},
{}
);

const startEvent = new apm.CommandStartedEvent(pool, query);

expect(startEvent).to.have.property('commandName', 'testCmd');
expect(startEvent).to.have.property('databaseName', db);
expect(startEvent).to.have.property('requestId', query.requestId);
expect(startEvent)
.to.have.property('connectionId')
.that.is.a('string');
expect(startEvent)
.to.have.property('command')
.that.deep.equals(query.query.$query);
}
);

it('should upconvert a Query wrapping a query into a find command', metadata, function() {
const db = 'test5';
const coll = 'testingFindCommand';
const query = new Query(
bson,
`${db}.${coll}`,
{
$query: {
testCmd: 1,
fizz: 'buzz',
star: 'trek'
}
},
{}
);

const startEvent = new apm.CommandStartedEvent(pool, query);

expect(startEvent).to.have.property('commandName', 'find');
expect(startEvent).to.have.property('databaseName', db);
expect(startEvent).to.have.property('requestId', query.requestId);
expect(startEvent)
.to.have.property('connectionId')
.that.is.a('string');
expect(startEvent)
.to.have.property('command')
.that.deep.equals({
find: coll,
filter: query.query.$query
});
});
});
});

0 comments on commit f969bee

Please sign in to comment.