Report only known collection names in MongoClientTracer (#1625) (#1662)

* Report only known collection names in MongoClientTracer (#1625)

* Use allow-list of commands that are known to use collection name as the value of the command
* Special-case getMore command, which uses a different field for the collection name

* Add create, drop, and createIndexes to list of commands with collection name as their values
This commit is contained in:
Jeff Yemin 2020-11-19 19:26:27 -05:00 committed by GitHub
parent 2738018d9d
commit d093a561b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 103 additions and 3 deletions

View File

@ -211,6 +211,36 @@ class MongoClientTest extends MongoBaseTest {
collectionName = "testCollection"
}
def "test collection name for getMore command"() {
setup:
MongoCollection<Document> collection = runUnderTrace("setup") {
MongoDatabase db = client.getDatabase(dbName)
def coll = db.getCollection(collectionName)
coll.insertMany([new Document("_id", 0), new Document("_id", 1), new Document("_id", 2)])
return coll
}
TEST_WRITER.waitForTraces(1)
TEST_WRITER.clear()
when:
collection.find().filter(new Document("_id", new Document('$gte', 0)))
.batchSize(2).into(new ArrayList())
then:
assertTraces(2) {
trace(0, 1) {
mongoSpan(it, 0, "find", collectionName, dbName, '{"find":"testCollection","filter":{"_id":{"$gte":"?"}},"batchSize":"?"}')
}
trace(1, 1) {
mongoSpan(it, 0, "getMore", collectionName, dbName, '{"getMore":"?","collection":"?","batchSize":"?"}')
}
}
where:
dbName = "test_db"
collectionName = "testCollection"
}
def "test error"() {
setup:
MongoCollection<Document> collection = runUnderTrace("setup") {

View File

@ -221,6 +221,36 @@ class MongoClientTest extends MongoBaseTest {
collectionName = "testCollection"
}
def "test collection name for getMore command"() {
setup:
MongoCollection<Document> collection = runUnderTrace("setup") {
MongoDatabase db = client.getDatabase(dbName)
def coll = db.getCollection(collectionName)
coll.insertMany([new Document("_id", 0), new Document("_id", 1), new Document("_id", 2)])
return coll
}
TEST_WRITER.waitForTraces(1)
TEST_WRITER.clear()
when:
collection.find().filter(new Document("_id", new Document('$gte', 0)))
.batchSize(2).into(new ArrayList())
then:
assertTraces(2) {
trace(0, 1) {
mongoSpan(it, 0, "find", collectionName, dbName, '{"find":"testCollection","filter":{"_id":{"$gte":"?"}},"batchSize":"?"}')
}
trace(1, 1) {
mongoSpan(it, 0, "getMore", collectionName, dbName, '{"getMore":"?","collection":"?","batchSize":"?"}')
}
}
where:
dbName = "test_db"
collectionName = "testCollection"
}
def "test error"() {
setup:
MongoCollection<Document> collection = runUnderTrace("setup") {

View File

@ -5,6 +5,8 @@
package io.opentelemetry.javaagent.instrumentation.mongo;
import static java.util.Arrays.asList;
import com.mongodb.ServerAddress;
import com.mongodb.connection.ConnectionDescription;
import com.mongodb.event.CommandStartedEvent;
@ -17,8 +19,11 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.bson.BsonArray;
import org.bson.BsonDocument;
import org.bson.BsonValue;
@ -106,6 +111,13 @@ public class MongoClientTracer extends DatabaseClientTracer<CommandStartedEvent,
.orElse(null);
}
/**
* The values of these mongo fields will not be scrubbed out. This allows the non-sensitive
* collection names to be captured.
*/
private static final List<String> UNSCRUBBED_FIELDS =
asList("ordered", "insert", "count", "find", "create");
private JsonWriterSettings createJsonWriterSettings(int maxNormalizedQueryLength) {
JsonWriterSettings settings = new JsonWriterSettings(false);
try {
@ -212,10 +224,38 @@ public class MongoClientTracer extends DatabaseClientTracer<CommandStartedEvent,
}
}
private static final Set<String> COMMANDS_WITH_COLLECTION_NAME_AS_VALUE =
new HashSet<>(
asList(
"aggregate",
"count",
"distinct",
"mapReduce",
"geoSearch",
"delete",
"find",
"killCursors",
"findAndModify",
"insert",
"update",
"create",
"drop",
"createIndexes",
"listIndexes"));
private static String collectionName(CommandStartedEvent event) {
BsonValue collectionValue = event.getCommand().get(event.getCommandName());
if (collectionValue != null && collectionValue.isString()) {
return collectionValue.asString().getValue();
if (event.getCommandName().equals("getMore")) {
if (event.getCommand().containsKey("collection")) {
BsonValue collectionValue = event.getCommand().get("collection");
if (collectionValue.isString()) {
return event.getCommand().getString("collection").getValue();
}
}
} else if (COMMANDS_WITH_COLLECTION_NAME_AS_VALUE.contains(event.getCommandName())) {
BsonValue commandValue = event.getCommand().get(event.getCommandName());
if (commandValue != null && commandValue.isString()) {
return commandValue.asString().getValue();
}
}
return null;
}