Skip to content

Commit 769649d

Browse files
committed
[pinpoint-apm#10940] Fix mongodb reactive streams driver interceptor
1 parent 14ad90c commit 769649d

File tree

12 files changed

+140
-84
lines changed

12 files changed

+140
-84
lines changed

agent-module/agent-testweb/mongodb-plugin-testweb/pom.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
<groupId>org.springframework.boot</groupId>
2929
<artifactId>spring-boot-autoconfigure</artifactId>
3030
</dependency>
31+
<dependency>
32+
<groupId>com.navercorp.pinpoint</groupId>
33+
<artifactId>pinpoint-agent-testweb-commons</artifactId>
34+
</dependency>
3135

3236
<!-- https://mvnrepository.com/artifact/org.mongodb/mongodb-driver -->
3337
<dependency>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright 2022 NAVER Corp.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.pinpoint.test.plugin;
18+
19+
import com.mongodb.client.MongoClient;
20+
import com.mongodb.client.MongoClients;
21+
import org.springframework.context.annotation.Bean;
22+
import org.springframework.context.annotation.Configuration;
23+
24+
@Configuration
25+
public class MongoConfig {
26+
27+
@Bean
28+
public MongoClient mongo() {
29+
MongoClient mongoClient = MongoClients.create(MongoServer.getUri());
30+
return mongoClient;
31+
}
32+
}

agent-module/agent-testweb/mongodb-plugin-testweb/src/main/java/com/pinpoint/test/plugin/MongoPluginController.java

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import com.mongodb.client.FindIterable;
2020
import com.mongodb.client.MongoClient;
21-
import com.mongodb.client.MongoClients;
2221
import com.mongodb.client.MongoCollection;
2322
import com.mongodb.client.MongoDatabase;
2423
import com.mongodb.client.model.Filters;
@@ -29,8 +28,8 @@
2928
import com.mongodb.client.model.UpdateOptions;
3029
import com.mongodb.client.result.DeleteResult;
3130
import com.mongodb.client.result.UpdateResult;
32-
import jakarta.annotation.PostConstruct;
33-
import jakarta.annotation.PreDestroy;
31+
import com.pinpoint.test.common.view.ApiLinkPage;
32+
import com.pinpoint.test.common.view.HrefTag;
3433
import org.bson.BsonArray;
3534
import org.bson.BsonBinary;
3635
import org.bson.BsonBinarySubType;
@@ -55,13 +54,20 @@
5554
import org.bson.Document;
5655
import org.bson.types.Decimal128;
5756
import org.bson.types.ObjectId;
57+
import org.springframework.beans.factory.annotation.Autowired;
58+
import org.springframework.web.bind.annotation.GetMapping;
5859
import org.springframework.web.bind.annotation.RequestMapping;
5960
import org.springframework.web.bind.annotation.RestController;
61+
import org.springframework.web.method.HandlerMethod;
62+
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
63+
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
6064

6165
import java.util.ArrayList;
6266
import java.util.Arrays;
67+
import java.util.Comparator;
6368
import java.util.Date;
6469
import java.util.List;
70+
import java.util.Map;
6571
import java.util.StringJoiner;
6672

6773
import static com.mongodb.client.model.Filters.and;
@@ -84,21 +90,33 @@ public class MongoPluginController {
8490
private static final String DATABASE_NAME_2 = "myMongoDb2";
8591
private static final String COLLECTION_NAME = "customers";
8692

93+
@Autowired
8794
private MongoClient mongoClient;
8895

89-
@PostConstruct
90-
public void start() {
91-
final String connectionString = MongoServer.getUri();
92-
this.mongoClient = MongoClients.create(connectionString);
96+
97+
private final RequestMappingHandlerMapping handlerMapping;
98+
99+
@Autowired
100+
public MongoPluginController(RequestMappingHandlerMapping handlerMapping) {
101+
this.handlerMapping = handlerMapping;
93102
}
94103

95-
@PreDestroy
96-
public void shutdown() {
97-
if (mongoClient != null) {
98-
mongoClient.close();
104+
@GetMapping("/")
105+
String welcome() {
106+
Map<RequestMappingInfo, HandlerMethod> handlerMethods = this.handlerMapping.getHandlerMethods();
107+
List<HrefTag> list = new ArrayList<>();
108+
for (RequestMappingInfo info : handlerMethods.keySet()) {
109+
for (String path : info.getDirectPaths()) {
110+
list.add(HrefTag.of(path));
111+
}
99112
}
113+
list.sort(Comparator.comparing(HrefTag::getPath));
114+
return new ApiLinkPage("mongodb-reactive-plugin-testweb")
115+
.addHrefTag(list)
116+
.build();
100117
}
101118

119+
102120
@RequestMapping(value = "/mongodb/insert")
103121
public String insert() {
104122
MongoCollection<Document> collection = getDatabase(DATABASE_NAME).getCollection(COLLECTION_NAME);

agent-module/agent-testweb/mongodb-plugin-testweb/src/test/java/com/pinpoint/test/plugin/mongo/MongodbTest.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
import org.testcontainers.containers.MongoDBContainer;
2525
import org.testcontainers.utility.DockerImageName;
2626

27-
import java.util.concurrent.TimeUnit;
28-
2927
@Ignore
3028
public class MongodbTest {
3129
private static MongoDBContainer container;
@@ -50,6 +48,5 @@ public static void select() {
5048
@Test
5149
public void test() throws Exception {
5250
System.out.println("TEST");
53-
TimeUnit.HOURS.sleep(8);
5451
}
5552
}

agent-module/bootstraps/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/UnKnownDatabaseInfo.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,11 @@
2727
*/
2828
public class UnKnownDatabaseInfo {
2929
public static final DatabaseInfo INSTANCE;
30-
public static final DatabaseInfo MONGO_INSTANCE;
3130

3231
static{
3332
final List<String> urls = new ArrayList<>();
3433
urls.add("unknown");
3534
INSTANCE = new DefaultDatabaseInfo(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, "unknown", "unknown", urls, "unknown", false);
36-
37-
MONGO_INSTANCE = new MongoDatabaseInfo(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, "unknown", "unknown", urls, "unknown", "unknown", false, "unknown", "unknown");
3835
}
3936

4037
public static DatabaseInfo createUnknownDataBase(String url) {

agent-module/plugins/mongodb/src/main/java/com/navercorp/pinpoint/plugin/mongo/MongoConstants.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,14 @@
1414
*/
1515
package com.navercorp.pinpoint.plugin.mongo;
1616

17+
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.MongoDatabaseInfo;
1718
import com.navercorp.pinpoint.common.trace.AnnotationKey;
1819
import com.navercorp.pinpoint.common.trace.AnnotationKeyFactory;
1920
import com.navercorp.pinpoint.common.trace.ServiceType;
2021
import com.navercorp.pinpoint.common.trace.ServiceTypeFactory;
2122

23+
import java.util.Arrays;
24+
2225
import static com.navercorp.pinpoint.common.trace.AnnotationKeyProperty.VIEW_IN_RECORD_SET;
2326
import static com.navercorp.pinpoint.common.trace.ServiceTypeProperty.INCLUDE_DESTINATION_ID;
2427
import static com.navercorp.pinpoint.common.trace.ServiceTypeProperty.RECORD_STATISTICS;
@@ -82,4 +85,6 @@ private MongoConstants() {
8285
public static final ServiceType MONGODB = ServiceTypeFactory.of(2650, "MONGO", TERMINAL, INCLUDE_DESTINATION_ID);
8386
public static final ServiceType MONGO_EXECUTE_QUERY = ServiceTypeFactory.of(2651, "MONGO_EXECUTE_QUERY", "MONGO", TERMINAL, RECORD_STATISTICS, INCLUDE_DESTINATION_ID);
8487
public static final ServiceType MONGO_REACTIVE = ServiceTypeFactory.of(2652, "MONGO_REACTIVE", "MONGO");
88+
89+
public static final MongoDatabaseInfo UNKNOWN_MONGO_DATABASE_INFO = new MongoDatabaseInfo(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, "unknown", "unknown", Arrays.asList("unknown"), "unknown", "unknown", false, "unknown", "unknown");
8590
}

agent-module/plugins/mongodb/src/main/java/com/navercorp/pinpoint/plugin/mongo/MongoPlugin.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,12 @@ public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, Strin
234234
if (constructorMethod12 != null) {
235235
constructorMethod12.addInterceptor(MongoClientConstructorInterceptor.class);
236236
}
237+
// 4.2
238+
// MongoClient(final MongoClientSettings settings, @Nullable final MongoClientOptions options, @Nullable final MongoDriverInformation mongoDriverInformation)
239+
final InstrumentMethod constructorMethod13 = target.getConstructor("com.mongodb.MongoClientSettings", "com.mongodb.MongoClientOptions", "com.mongodb.MongoDriverInformation");
240+
if (constructorMethod13 != null) {
241+
constructorMethod13.addInterceptor(MongoClientConstructorInterceptor.class);
242+
}
237243

238244
final InstrumentMethod getDatabaseMethod = target.getDeclaredMethod("getDatabase", "java.lang.String");
239245
if (getDatabaseMethod != null) {

agent-module/plugins/mongodb/src/main/java/com/navercorp/pinpoint/plugin/mongo/interceptor/DatabaseInfoUtils.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
2020
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.DatabaseInfoAccessor;
21+
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.MongoDatabaseInfo;
2122

2223
/**
2324
* @author Woonduk Kang(emeroad)
@@ -26,14 +27,13 @@ public final class DatabaseInfoUtils {
2627
private DatabaseInfoUtils() {
2728
}
2829

29-
public static DatabaseInfo getDatabaseInfo(Object target, DatabaseInfo defaultDatabaseInfo) {
30+
public static MongoDatabaseInfo getDatabaseInfo(Object target, MongoDatabaseInfo defaultDatabaseInfo) {
3031
if (target instanceof DatabaseInfoAccessor) {
3132
final DatabaseInfo databaseInfo = ((DatabaseInfoAccessor) target)._$PINPOINT$_getDatabaseInfo();
32-
if (databaseInfo != null) {
33-
return databaseInfo;
33+
if (databaseInfo instanceof MongoDatabaseInfo) {
34+
return (MongoDatabaseInfo) databaseInfo;
3435
}
3536
}
3637
return defaultDatabaseInfo;
3738
}
38-
3939
}

agent-module/plugins/mongodb/src/main/java/com/navercorp/pinpoint/plugin/mongo/interceptor/MongoClientConstructorInterceptor.java

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616

1717
package com.navercorp.pinpoint.plugin.mongo.interceptor;
1818

19+
import com.mongodb.MongoClientSettings;
1920
import com.mongodb.ServerAddress;
2021
import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor;
2122
import com.navercorp.pinpoint.bootstrap.logging.PluginLogManager;
2223
import com.navercorp.pinpoint.bootstrap.logging.PluginLogger;
2324
import com.navercorp.pinpoint.common.plugin.util.HostAndPort;
2425
import com.navercorp.pinpoint.common.util.ArrayArgumentUtils;
2526
import com.navercorp.pinpoint.plugin.mongo.HostListAccessor;
27+
import com.navercorp.pinpoint.plugin.mongo.MongoUtil;
2628

2729
import java.util.ArrayList;
2830
import java.util.List;
@@ -53,35 +55,48 @@ public void after(Object target, Object[] args, Object result, Throwable throwab
5355
}
5456

5557
try {
58+
// over 4.2
59+
final MongoClientSettings mongoClientSettings = ArrayArgumentUtils.getArgument(args, 0, MongoClientSettings.class);
60+
if (mongoClientSettings != null) {
61+
List<String> list = MongoUtil.getHostList(mongoClientSettings);
62+
setHostList(target, list);
63+
return;
64+
}
65+
5666
final List<String> hostList = new ArrayList<>();
5767
// arg0 is ServerAddress
5868
final ServerAddress serverAddress = ArrayArgumentUtils.getArgument(args, 0, ServerAddress.class);
5969
if (serverAddress != null) {
6070
final String hostAddress = HostAndPort.toHostAndPortString(serverAddress.getHost(), serverAddress.getPort());
6171
hostList.add(hostAddress);
62-
} else {
63-
// arg0 is List<ServerAddress>
64-
final List<?> list = ArrayArgumentUtils.getArgument(args, 0, List.class);
65-
if (list != null) {
66-
for (Object o : list) {
67-
if (o instanceof ServerAddress) {
68-
// Set multi address.
69-
final ServerAddress address = (ServerAddress) o;
70-
final String hostAddress = HostAndPort.toHostAndPortString(address.getHost(), address.getPort());
71-
hostList.add(hostAddress);
72-
}
73-
}
74-
}
72+
setHostList(target, hostList);
73+
return;
7574
}
7675

77-
((HostListAccessor) target)._$PINPOINT$_setHostList(hostList);
78-
if (isDebug) {
79-
logger.debug("Set hostList={}", hostList);
76+
// arg0 is List<ServerAddress>
77+
final List<?> list = ArrayArgumentUtils.getArgument(args, 0, List.class);
78+
if (list != null) {
79+
for (Object o : list) {
80+
if (o instanceof ServerAddress) {
81+
// Set multi address.
82+
final ServerAddress address = (ServerAddress) o;
83+
final String hostAddress = HostAndPort.toHostAndPortString(address.getHost(), address.getPort());
84+
hostList.add(hostAddress);
85+
}
86+
}
87+
setHostList(target, hostList);
8088
}
8189
} catch (Throwable th) {
8290
if (logger.isWarnEnabled()) {
8391
logger.warn("AFTER error. Caused:{}", th.getMessage(), th);
8492
}
8593
}
8694
}
87-
}
95+
96+
private void setHostList(Object target, List<String> hostList) {
97+
((HostListAccessor) target)._$PINPOINT$_setHostList(hostList);
98+
if (isDebug) {
99+
logger.debug("Set hostList={}", hostList);
100+
}
101+
}
102+
}

agent-module/plugins/mongodb/src/main/java/com/navercorp/pinpoint/plugin/mongo/interceptor/MongoCollectionImplReadOperationInterceptor.java

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,11 @@
1818

1919
import com.navercorp.pinpoint.bootstrap.async.AsyncContextAccessor;
2020
import com.navercorp.pinpoint.bootstrap.context.AsyncContext;
21-
import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
2221
import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor;
2322
import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder;
2423
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
2524
import com.navercorp.pinpoint.bootstrap.interceptor.SpanEventSimpleAroundInterceptorForPlugin;
2625
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.MongoDatabaseInfo;
27-
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.UnKnownDatabaseInfo;
2826
import com.navercorp.pinpoint.bootstrap.util.InterceptorUtils;
2927
import com.navercorp.pinpoint.plugin.mongo.HostListAccessor;
3028
import com.navercorp.pinpoint.plugin.mongo.MongoConstants;
@@ -47,25 +45,18 @@ public MongoCollectionImplReadOperationInterceptor(TraceContext traceContext, Me
4745
@Override
4846
public void doInBeforeTrace(SpanEventRecorder recorder, Object target, Object[] args) {
4947
recorder.recordApi(methodDescriptor);
50-
51-
if (Boolean.FALSE == (target instanceof HostListAccessor)) {
52-
return;
53-
}
54-
55-
final List<String> hostList = ((HostListAccessor) target)._$PINPOINT$_getHostList();
56-
if (hostList == null) {
57-
return;
48+
MongoDatabaseInfo databaseInfo = DatabaseInfoUtils.getDatabaseInfo(target, MongoConstants.UNKNOWN_MONGO_DATABASE_INFO);
49+
if (target instanceof HostListAccessor) {
50+
final List<String> hostList = ((HostListAccessor) target)._$PINPOINT$_getHostList();
51+
if (hostList != null) {
52+
databaseInfo = new MongoDatabaseInfo(MongoConstants.MONGODB, MongoConstants.MONGO_EXECUTE_QUERY, null, null, hostList, databaseInfo.getDatabaseId(), databaseInfo.getCollectionName(), databaseInfo.getReadPreference(), databaseInfo.getWriteConcern());
53+
}
5854
}
55+
recorder.recordServiceType(databaseInfo.getExecuteQueryType());
56+
recorder.recordEndPoint(databaseInfo.getMultipleHost());
57+
recorder.recordDestinationId(databaseInfo.getDatabaseId());
5958

60-
final DatabaseInfo databaseInfo = DatabaseInfoUtils.getDatabaseInfo(target, UnKnownDatabaseInfo.MONGO_INSTANCE);
61-
final MongoDatabaseInfo mongoDatabaseInfo = new MongoDatabaseInfo(MongoConstants.MONGODB, MongoConstants.MONGO_EXECUTE_QUERY,
62-
null, null, hostList, databaseInfo.getDatabaseId(), ((MongoDatabaseInfo) databaseInfo).getCollectionName(), ((MongoDatabaseInfo) databaseInfo).getReadPreference(), ((MongoDatabaseInfo) databaseInfo).getWriteConcern());
63-
64-
recorder.recordServiceType(mongoDatabaseInfo.getExecuteQueryType());
65-
recorder.recordEndPoint(mongoDatabaseInfo.getMultipleHost());
66-
recorder.recordDestinationId(mongoDatabaseInfo.getDatabaseId());
67-
68-
MongoUtil.recordMongoCollection(recorder, mongoDatabaseInfo.getCollectionName(), mongoDatabaseInfo.getReadPreference());
59+
MongoUtil.recordMongoCollection(recorder, databaseInfo.getCollectionName(), databaseInfo.getReadPreference());
6960
}
7061

7162
@Override

0 commit comments

Comments
 (0)