Skip to content

Commit 6cbeea6

Browse files
committed
Fix MongoDB 4.x plugin to support driver 4.9+ (db.bind_vars extraction)
MongoDB driver 4.9 removed InsertOperation, DeleteOperation, UpdateOperation classes. MongoOperationHelper imported them, causing NoClassDefFoundError at class load time which silently broke all db.bind_vars extraction. Fix: use Class.forName check to detect legacy classes at startup, isolate legacy imports into LegacyOperationHelper (only loaded when classes exist). For 4.9+, all write operations go through MixedBulkWriteOperation which the plugin already handles via getWriteRequests().
1 parent 9ff281e commit 6cbeea6

File tree

4 files changed

+92
-19
lines changed

4 files changed

+92
-19
lines changed

CHANGES.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Release Notes.
1111
* Add Spring RabbitMQ 2.x - 4.x plugin.
1212
* Extend MySQL plugin to support MySQL Connector/J 8.4.0 and 9.x (9.0 -> 9.6).
1313
* Extend MariaDB plugin to support MariaDB Connector/J 2.7.x.
14-
* Extend MongoDB 4.x plugin to support MongoDB Java Driver 4.2 -> 4.10.
14+
* Extend MongoDB 4.x plugin to support MongoDB Java Driver 4.2 -> 4.10. Fix db.bind_vars extraction for driver 4.9+ where InsertOperation/DeleteOperation/UpdateOperation classes were removed.
1515
* Extend Feign plugin to support OpenFeign 10.x, 11.x, 12.1.
1616
* Extend Undertow plugin to support Undertow 2.1.x, 2.2.x, 2.3.x.
1717
* Extend GraphQL plugin to support graphql-java 18 -> 24 (20+ requires JDK 17).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
package org.apache.skywalking.apm.plugin.mongodb.v4.support;
20+
21+
import com.mongodb.internal.bulk.DeleteRequest;
22+
import com.mongodb.internal.bulk.InsertRequest;
23+
import com.mongodb.internal.bulk.UpdateRequest;
24+
import com.mongodb.internal.operation.DeleteOperation;
25+
import com.mongodb.internal.operation.InsertOperation;
26+
import com.mongodb.internal.operation.UpdateOperation;
27+
28+
import java.util.List;
29+
30+
/**
31+
* Handles trace parameter extraction for legacy MongoDB driver versions (4.0 - 4.8).
32+
* InsertOperation, DeleteOperation, and UpdateOperation were removed in driver 4.9.
33+
* This class is only loaded when those classes exist (guarded by
34+
* {@link MongoOperationHelper#HAS_LEGACY_WRITE_OPERATIONS}).
35+
*/
36+
@SuppressWarnings("deprecation")
37+
class LegacyOperationHelper {
38+
39+
private LegacyOperationHelper() {
40+
}
41+
42+
/**
43+
* Extract trace parameters from legacy write operation types.
44+
* @return the trace parameter string, or null if obj is not a legacy write operation
45+
*/
46+
static String getTraceParam(Object obj) {
47+
if (obj instanceof DeleteOperation) {
48+
List<DeleteRequest> writeRequestList = ((DeleteOperation) obj).getDeleteRequests();
49+
return MongoOperationHelper.getFilter(writeRequestList);
50+
} else if (obj instanceof InsertOperation) {
51+
List<InsertRequest> writeRequestList = ((InsertOperation) obj).getInsertRequests();
52+
return MongoOperationHelper.getFilter(writeRequestList);
53+
} else if (obj instanceof UpdateOperation) {
54+
List<UpdateRequest> writeRequestList = ((UpdateOperation) obj).getUpdateRequests();
55+
return MongoOperationHelper.getFilter(writeRequestList);
56+
}
57+
return null;
58+
}
59+
}

apm-sniffer/apm-sdk-plugin/mongodb-4.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/mongodb/v4/support/MongoOperationHelper.java

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,15 @@
2727
import com.mongodb.internal.operation.CreateCollectionOperation;
2828
import com.mongodb.internal.operation.CreateIndexesOperation;
2929
import com.mongodb.internal.operation.CreateViewOperation;
30-
import com.mongodb.internal.operation.DeleteOperation;
3130
import com.mongodb.internal.operation.DistinctOperation;
3231
import com.mongodb.internal.operation.FindAndDeleteOperation;
3332
import com.mongodb.internal.operation.FindAndReplaceOperation;
3433
import com.mongodb.internal.operation.FindAndUpdateOperation;
3534
import com.mongodb.internal.operation.FindOperation;
36-
import com.mongodb.internal.operation.InsertOperation;
3735
import com.mongodb.internal.operation.ListCollectionsOperation;
3836
import com.mongodb.internal.operation.MapReduceToCollectionOperation;
3937
import com.mongodb.internal.operation.MapReduceWithInlineResultsOperation;
4038
import com.mongodb.internal.operation.MixedBulkWriteOperation;
41-
import com.mongodb.internal.operation.UpdateOperation;
4239
import org.bson.BsonDocument;
4340

4441
import java.util.List;
@@ -49,6 +46,21 @@
4946
})
5047
public class MongoOperationHelper {
5148

49+
// InsertOperation, DeleteOperation, UpdateOperation were removed in MongoDB driver 4.9.
50+
// Use class existence check to determine which extraction path to use.
51+
private static final boolean HAS_LEGACY_WRITE_OPERATIONS;
52+
53+
static {
54+
boolean hasLegacy;
55+
try {
56+
Class.forName("com.mongodb.internal.operation.InsertOperation");
57+
hasLegacy = true;
58+
} catch (ClassNotFoundException e) {
59+
hasLegacy = false;
60+
}
61+
HAS_LEGACY_WRITE_OPERATIONS = hasLegacy;
62+
}
63+
5264
private MongoOperationHelper() {
5365

5466
}
@@ -69,22 +81,25 @@ public static String getTraceParam(Object obj) {
6981
} else if (obj instanceof FindOperation) {
7082
BsonDocument filter = ((FindOperation) obj).getFilter();
7183
return limitFilter(filter.toString());
72-
} else if (obj instanceof ListCollectionsOperation) {
84+
} else if (obj instanceof ListCollectionsOperation) {
7385
BsonDocument filter = ((ListCollectionsOperation) obj).getFilter();
7486
return limitFilter(filter.toString());
7587
} else if (obj instanceof MapReduceWithInlineResultsOperation) {
7688
BsonDocument filter = ((MapReduceWithInlineResultsOperation) obj).getFilter();
7789
return limitFilter(filter.toString());
78-
} else if (obj instanceof DeleteOperation) {
79-
List<DeleteRequest> writeRequestList = ((DeleteOperation) obj).getDeleteRequests();
80-
return getFilter(writeRequestList);
81-
} else if (obj instanceof InsertOperation) {
82-
List<InsertRequest> writeRequestList = ((InsertOperation) obj).getInsertRequests();
83-
return getFilter(writeRequestList);
84-
} else if (obj instanceof UpdateOperation) {
85-
List<UpdateRequest> writeRequestList = ((UpdateOperation) obj).getUpdateRequests();
86-
return getFilter(writeRequestList);
87-
} else if (obj instanceof CreateCollectionOperation) {
90+
} else if (HAS_LEGACY_WRITE_OPERATIONS) {
91+
String result = LegacyOperationHelper.getTraceParam(obj);
92+
if (result != null) {
93+
return result;
94+
}
95+
return getCommonTraceParam(obj);
96+
} else {
97+
return getCommonTraceParam(obj);
98+
}
99+
}
100+
101+
private static String getCommonTraceParam(Object obj) {
102+
if (obj instanceof CreateCollectionOperation) {
88103
String filter = ((CreateCollectionOperation) obj).getCollectionName();
89104
return limitFilter(filter);
90105
} else if (obj instanceof CreateIndexesOperation) {
@@ -128,7 +143,7 @@ private static String getPipelines(List<BsonDocument> pipelines) {
128143
return params.toString();
129144
}
130145

131-
private static String getFilter(List<? extends WriteRequest> writeRequestList) {
146+
static String getFilter(List<? extends WriteRequest> writeRequestList) {
132147
StringBuilder params = new StringBuilder();
133148
for (WriteRequest request : writeRequestList) {
134149
if (request instanceof InsertRequest) {

test/plugin/scenarios/mongodb-4.x-scenario/support-version.list

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,5 @@
2323
4.6.1
2424
4.7.2
2525
4.8.2
26-
# 4.9+ removed InsertOperation, DeleteOperation, UpdateOperation classes.
27-
# MongoOperationHelper imports them causing NoClassDefFoundError at load time,
28-
# which breaks db.bind_vars extraction. Needs a new mongodb-4.9.x-plugin module.
26+
4.9.1
27+
4.10.2

0 commit comments

Comments
 (0)