Refactor adapter.
Move into util package. Remove circular dependencies, add nullability annotations, fix Javadoc. Original pull request: #4624 See: #4578
This commit is contained in:
@@ -1,188 +0,0 @@
|
||||
/*
|
||||
* Copyright 2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.mongodb;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import com.mongodb.ServerAddress;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.data.mongodb.core.MongoClientSettingsFactoryBean;
|
||||
import org.springframework.data.mongodb.util.MongoClientVersion;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import com.mongodb.MongoClientSettings;
|
||||
import com.mongodb.MongoClientSettings.Builder;
|
||||
import com.mongodb.client.MapReduceIterable;
|
||||
import com.mongodb.client.model.IndexOptions;
|
||||
import com.mongodb.reactivestreams.client.MapReducePublisher;
|
||||
|
||||
/**
|
||||
* @author Christoph Strobl
|
||||
* @since 2023/12
|
||||
*/
|
||||
public class MongoCompatibilityAdapter {
|
||||
|
||||
private static final String NO_LONGER_SUPPORTED = "%s is no longer supported on Mongo Client 5+";
|
||||
|
||||
public static ClientSettingsBuilderAdapter clientSettingsBuilderAdapter(MongoClientSettings.Builder builder) {
|
||||
return new MongoStreamFactoryFactorySettingsConfigurer(builder)::setStreamFactory;
|
||||
}
|
||||
|
||||
public static ClientSettingsAdapter clientSettingsAdapter(MongoClientSettings clientSettings) {
|
||||
return new ClientSettingsAdapter() {
|
||||
@Override
|
||||
public <T> T getStreamFactoryFactory() {
|
||||
if (MongoClientVersion.is5PlusClient()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Method getStreamFactoryFactory = ReflectionUtils.findMethod(MongoClientSettings.class,
|
||||
"getStreamFactoryFactory");
|
||||
return getStreamFactoryFactory != null
|
||||
? (T) ReflectionUtils.invokeMethod(getStreamFactoryFactory, clientSettings)
|
||||
: null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static IndexOptionsAdapter indexOptionsAdapter(IndexOptions options) {
|
||||
return new IndexOptionsAdapter() {
|
||||
@Override
|
||||
public void setBucketSize(Double bucketSize) {
|
||||
|
||||
if (MongoClientVersion.is5PlusClient()) {
|
||||
throw new UnsupportedOperationException(NO_LONGER_SUPPORTED.formatted("IndexOptions.bucketSize"));
|
||||
}
|
||||
|
||||
Method setBucketSize = ReflectionUtils.findMethod(IndexOptions.class, "bucketSize", Double.class);
|
||||
ReflectionUtils.invokeMethod(setBucketSize, options, bucketSize);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "deprecation" })
|
||||
public static MapReduceIterableAdapter mapReduceIterableAdapter(MapReduceIterable<?> iterable) {
|
||||
return sharded -> {
|
||||
if (MongoClientVersion.is5PlusClient()) {
|
||||
throw new UnsupportedOperationException(NO_LONGER_SUPPORTED.formatted("sharded"));
|
||||
}
|
||||
|
||||
Method shardedMethod = ReflectionUtils.findMethod(iterable.getClass(), "MapReduceIterable.sharded",
|
||||
boolean.class);
|
||||
ReflectionUtils.invokeMethod(shardedMethod, iterable, shardedMethod);
|
||||
};
|
||||
}
|
||||
|
||||
public static MapReducePublisherAdapter mapReducePublisherAdapter(MapReducePublisher<?> publisher) {
|
||||
return sharded -> {
|
||||
if (MongoClientVersion.is5PlusClient()) {
|
||||
throw new UnsupportedOperationException(NO_LONGER_SUPPORTED.formatted("sharded"));
|
||||
}
|
||||
|
||||
Method shardedMethod = ReflectionUtils.findMethod(publisher.getClass(), "MapReduceIterable.sharded",
|
||||
boolean.class);
|
||||
ReflectionUtils.invokeMethod(shardedMethod, publisher, shardedMethod);
|
||||
};
|
||||
}
|
||||
|
||||
public static ServerAddressAdapter serverAddressAdapter(ServerAddress serverAddress) {
|
||||
return new ServerAddressAdapter() {
|
||||
@Override
|
||||
public InetSocketAddress getSocketAddress() {
|
||||
|
||||
if(MongoClientVersion.is5PlusClient()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Method serverAddressMethod = ReflectionUtils.findMethod(serverAddress.getClass(), "getSocketAddress");
|
||||
Object value = ReflectionUtils.invokeMethod(serverAddressMethod, serverAddress);
|
||||
return value != null ? InetSocketAddress.class.cast(value) : null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public interface IndexOptionsAdapter {
|
||||
void setBucketSize(Double bucketSize);
|
||||
}
|
||||
|
||||
public interface ClientSettingsAdapter {
|
||||
<T> T getStreamFactoryFactory();
|
||||
}
|
||||
|
||||
public interface ClientSettingsBuilderAdapter {
|
||||
<T> void setStreamFactoryFactory(T streamFactory);
|
||||
}
|
||||
|
||||
public interface MapReduceIterableAdapter {
|
||||
void sharded(boolean sharded);
|
||||
}
|
||||
|
||||
public interface MapReducePublisherAdapter {
|
||||
void sharded(boolean sharded);
|
||||
}
|
||||
|
||||
public interface ServerAddressAdapter {
|
||||
InetSocketAddress getSocketAddress();
|
||||
}
|
||||
|
||||
static class MongoStreamFactoryFactorySettingsConfigurer {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(MongoClientSettingsFactoryBean.class);
|
||||
|
||||
private static final String STREAM_FACTORY_NAME = "com.mongodb.connection.StreamFactoryFactory";
|
||||
private static final boolean STREAM_FACTORY_PRESENT = ClassUtils.isPresent(STREAM_FACTORY_NAME,
|
||||
MongoCompatibilityAdapter.class.getClassLoader());
|
||||
private final MongoClientSettings.Builder settingsBuilder;
|
||||
|
||||
static boolean isStreamFactoryPresent() {
|
||||
return STREAM_FACTORY_PRESENT;
|
||||
}
|
||||
|
||||
public MongoStreamFactoryFactorySettingsConfigurer(Builder settingsBuilder) {
|
||||
this.settingsBuilder = settingsBuilder;
|
||||
}
|
||||
|
||||
void setStreamFactory(Object streamFactory) {
|
||||
|
||||
if (MongoClientVersion.is5PlusClient()) {
|
||||
logger.warn("StreamFactoryFactory is no longer available. Use TransportSettings instead.");
|
||||
}
|
||||
|
||||
if (isStreamFactoryPresent()) { //
|
||||
try {
|
||||
Class<?> streamFactoryType = ClassUtils.forName(STREAM_FACTORY_NAME,
|
||||
streamFactory.getClass().getClassLoader());
|
||||
if (!ClassUtils.isAssignable(streamFactoryType, streamFactory.getClass())) {
|
||||
throw new IllegalArgumentException("Expected %s but found %s".formatted(streamFactoryType, streamFactory));
|
||||
}
|
||||
|
||||
Method setter = ReflectionUtils.findMethod(settingsBuilder.getClass(), "streamFactoryFactory",
|
||||
streamFactoryType);
|
||||
if (setter != null) {
|
||||
ReflectionUtils.invokeMethod(setter, settingsBuilder, streamFactoryType.cast(streamFactory));
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalArgumentException("Cannot set StreamFactoryFactory for %s".formatted(settingsBuilder), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -114,6 +114,7 @@ public class DefaultIndexOperations implements IndexOperations {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String ensureIndex(final IndexDefinition indexDefinition) {
|
||||
|
||||
return execute(collection -> {
|
||||
|
||||
@@ -88,7 +88,8 @@ public class DefaultReactiveIndexOperations implements ReactiveIndexOperations {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public Mono<String> ensureIndex(final IndexDefinition indexDefinition) {
|
||||
@Override
|
||||
public Mono<String> ensureIndex(IndexDefinition indexDefinition) {
|
||||
|
||||
return mongoOperations.execute(collectionName, collection -> {
|
||||
|
||||
|
||||
@@ -18,11 +18,11 @@ package org.springframework.data.mongodb.core;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.bson.Document;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.mongodb.MongoCompatibilityAdapter;
|
||||
import org.springframework.data.mongodb.core.index.IndexDefinition;
|
||||
import org.springframework.data.mongodb.core.index.IndexInfo;
|
||||
import org.springframework.data.mongodb.util.MongoClientVersion;
|
||||
import org.springframework.data.mongodb.util.MongoCompatibilityAdapter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.core;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
@@ -24,17 +23,13 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.bson.UuidRepresentation;
|
||||
import org.bson.codecs.configuration.CodecRegistry;
|
||||
|
||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
||||
import org.springframework.data.mongodb.MongoCompatibilityAdapter;
|
||||
import org.springframework.data.mongodb.util.MongoClientVersion;
|
||||
import org.springframework.data.mongodb.util.MongoCompatibilityAdapter;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.AutoEncryptionSettings;
|
||||
@@ -62,7 +57,8 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean<MongoCli
|
||||
|
||||
private CodecRegistry codecRegistry = DEFAULT_MONGO_SETTINGS.getCodecRegistry();
|
||||
|
||||
@Nullable private Object streamFactoryFactory;
|
||||
@Nullable private Object streamFactoryFactory = MongoCompatibilityAdapter
|
||||
.clientSettingsAdapter(DEFAULT_MONGO_SETTINGS).getStreamFactoryFactory();
|
||||
@Nullable private TransportSettings transportSettings;
|
||||
|
||||
private ReadPreference readPreference = DEFAULT_MONGO_SETTINGS.getReadPreference();
|
||||
@@ -125,13 +121,9 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean<MongoCli
|
||||
private @Nullable AutoEncryptionSettings autoEncryptionSettings;
|
||||
private @Nullable ServerApi serverApi;
|
||||
|
||||
{
|
||||
streamFactoryFactory = MongoCompatibilityAdapter.clientSettingsAdapter(DEFAULT_MONGO_SETTINGS).getStreamFactoryFactory();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param socketConnectTimeoutMS in msec
|
||||
* @see com.mongodb.connection.SocketSettings.Builder#connectTimeout(int, TimeUnit)
|
||||
* @see com.mongodb.connection.SocketSettings.Builder#connectTimeout(long, TimeUnit)
|
||||
*/
|
||||
public void setSocketConnectTimeoutMS(int socketConnectTimeoutMS) {
|
||||
this.socketConnectTimeoutMS = socketConnectTimeoutMS;
|
||||
@@ -139,7 +131,7 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean<MongoCli
|
||||
|
||||
/**
|
||||
* @param socketReadTimeoutMS in msec
|
||||
* @see com.mongodb.connection.SocketSettings.Builder#readTimeout(int, TimeUnit)
|
||||
* @see com.mongodb.connection.SocketSettings.Builder#readTimeout(long, TimeUnit)
|
||||
*/
|
||||
public void setSocketReadTimeoutMS(int socketReadTimeoutMS) {
|
||||
this.socketReadTimeoutMS = socketReadTimeoutMS;
|
||||
@@ -380,8 +372,11 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean<MongoCli
|
||||
}
|
||||
|
||||
/**
|
||||
* @param streamFactoryFactory // * @see MongoClientSettings.Builder#streamFactoryFactory(StreamFactoryFactory)
|
||||
* @param streamFactoryFactory
|
||||
* @deprecated since 4.3, will be removed in the MongoDB 5.0 driver in favor of
|
||||
* {@code com.mongodb.connection.TransportSettings}.
|
||||
*/
|
||||
@Deprecated(since = "4.3")
|
||||
public void setStreamFactoryFactory(Object streamFactoryFactory) {
|
||||
this.streamFactoryFactory = streamFactoryFactory;
|
||||
}
|
||||
@@ -449,7 +444,6 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean<MongoCli
|
||||
settings.hosts(clusterHosts);
|
||||
}
|
||||
settings.localThreshold(clusterLocalThresholdMS, TimeUnit.MILLISECONDS);
|
||||
// settings.maxWaitQueueSize(clusterMaxWaitQueueSize);
|
||||
settings.requiredClusterType(custerRequiredClusterType);
|
||||
|
||||
if (StringUtils.hasText(clusterSrvHost)) {
|
||||
@@ -518,59 +512,4 @@ public class MongoClientSettingsFactoryBean extends AbstractFactoryBean<MongoCli
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
static class MongoStreamFactoryFactorySettingsConfigurer {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(MongoClientSettingsFactoryBean.class);
|
||||
|
||||
private static final String STREAM_FACTORY_NAME = "com.mongodb.connection.StreamFactoryFactory";
|
||||
private static final boolean STREAM_FACTORY_PRESENT = ClassUtils.isPresent(STREAM_FACTORY_NAME,
|
||||
MongoStreamFactoryFactorySettingsConfigurer.class.getClassLoader());
|
||||
private final MongoClientSettings.Builder settingsBuilder;
|
||||
|
||||
static boolean isStreamFactoryPresent() {
|
||||
return STREAM_FACTORY_PRESENT;
|
||||
}
|
||||
|
||||
static Object getDefaultStreamFactoryFactory() {
|
||||
|
||||
if (MongoClientVersion.is5PlusClient()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Method getStreamFactoryFactory = ReflectionUtils.findMethod(MongoClientSettings.class, "getStreamFactoryFactory");
|
||||
return getStreamFactoryFactory != null
|
||||
? ReflectionUtils.invokeMethod(getStreamFactoryFactory, DEFAULT_MONGO_SETTINGS)
|
||||
: null;
|
||||
}
|
||||
|
||||
public MongoStreamFactoryFactorySettingsConfigurer(Builder settingsBuilder) {
|
||||
this.settingsBuilder = settingsBuilder;
|
||||
}
|
||||
|
||||
void setStreamFactory(Object streamFactory) {
|
||||
|
||||
if (MongoClientVersion.is5PlusClient()) {
|
||||
logger.warn("StreamFactoryFactory is no longer available. Use TransportSettings instead.");
|
||||
}
|
||||
|
||||
if (isStreamFactoryPresent()) { //
|
||||
try {
|
||||
Class<?> streamFactoryType = ClassUtils.forName(STREAM_FACTORY_NAME,
|
||||
streamFactory.getClass().getClassLoader());
|
||||
if (!ClassUtils.isAssignable(streamFactoryType, streamFactory.getClass())) {
|
||||
throw new IllegalArgumentException("Expected %s but found %s".formatted(streamFactoryType, streamFactory));
|
||||
}
|
||||
|
||||
Method setter = ReflectionUtils.findMethod(settingsBuilder.getClass(), "streamFactoryFactory",
|
||||
streamFactoryType);
|
||||
if (setter != null) {
|
||||
ReflectionUtils.invokeMethod(setter, settingsBuilder, streamFactoryType.cast(streamFactory));
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalArgumentException("Cannot set StreamFactoryFactory for %s".formatted(settingsBuilder), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.bson.Document;
|
||||
import org.bson.conversions.Bson;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
@@ -53,7 +54,6 @@ import org.springframework.data.geo.Metric;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.callback.EntityCallbacks;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mongodb.MongoCompatibilityAdapter;
|
||||
import org.springframework.data.mongodb.MongoDatabaseFactory;
|
||||
import org.springframework.data.mongodb.MongoDatabaseUtils;
|
||||
import org.springframework.data.mongodb.SessionSynchronization;
|
||||
@@ -104,7 +104,7 @@ import org.springframework.data.mongodb.core.query.UpdateDefinition;
|
||||
import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter;
|
||||
import org.springframework.data.mongodb.core.timeseries.Granularity;
|
||||
import org.springframework.data.mongodb.core.validation.Validator;
|
||||
import org.springframework.data.mongodb.util.MongoClientVersion;
|
||||
import org.springframework.data.mongodb.util.MongoCompatibilityAdapter;
|
||||
import org.springframework.data.projection.EntityProjection;
|
||||
import org.springframework.data.util.CloseableIterator;
|
||||
import org.springframework.data.util.Optionals;
|
||||
|
||||
@@ -17,8 +17,6 @@ package org.springframework.data.mongodb.core;
|
||||
|
||||
import static org.springframework.data.mongodb.core.query.SerializationUtils.*;
|
||||
|
||||
import org.springframework.data.mongodb.MongoCompatibilityAdapter;
|
||||
import org.springframework.data.mongodb.util.MongoClientVersion;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuple2;
|
||||
@@ -48,6 +46,7 @@ import org.bson.conversions.Bson;
|
||||
import org.bson.types.ObjectId;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.reactivestreams.Subscriber;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
@@ -119,6 +118,7 @@ import org.springframework.data.mongodb.core.query.NearQuery;
|
||||
import org.springframework.data.mongodb.core.query.Query;
|
||||
import org.springframework.data.mongodb.core.query.UpdateDefinition;
|
||||
import org.springframework.data.mongodb.core.query.UpdateDefinition.ArrayFilter;
|
||||
import org.springframework.data.mongodb.util.MongoCompatibilityAdapter;
|
||||
import org.springframework.data.projection.EntityProjection;
|
||||
import org.springframework.data.util.Optionals;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
@@ -15,11 +15,12 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.observability;
|
||||
|
||||
import io.micrometer.common.KeyValues;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
import org.springframework.data.mongodb.MongoCompatibilityAdapter;
|
||||
import org.springframework.data.mongodb.observability.MongoObservation.LowCardinalityCommandKeyNames;
|
||||
import org.springframework.data.mongodb.util.MongoClientVersion;
|
||||
import org.springframework.data.mongodb.util.MongoCompatibilityAdapter;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.mongodb.ConnectionString;
|
||||
@@ -28,8 +29,6 @@ import com.mongodb.connection.ConnectionDescription;
|
||||
import com.mongodb.connection.ConnectionId;
|
||||
import com.mongodb.event.CommandStartedEvent;
|
||||
|
||||
import io.micrometer.common.KeyValues;
|
||||
|
||||
/**
|
||||
* Default {@link MongoHandlerObservationConvention} implementation.
|
||||
*
|
||||
@@ -80,8 +79,8 @@ class DefaultMongoHandlerObservationConvention implements MongoHandlerObservatio
|
||||
LowCardinalityCommandKeyNames.NET_PEER_NAME.withValue(serverAddress.getHost()),
|
||||
LowCardinalityCommandKeyNames.NET_PEER_PORT.withValue("" + serverAddress.getPort()));
|
||||
|
||||
|
||||
InetSocketAddress socketAddress = MongoCompatibilityAdapter.serverAddressAdapter(serverAddress).getSocketAddress();
|
||||
InetSocketAddress socketAddress = MongoCompatibilityAdapter.serverAddressAdapter(serverAddress)
|
||||
.getSocketAddress();
|
||||
|
||||
if (socketAddress != null) {
|
||||
|
||||
|
||||
@@ -80,8 +80,12 @@ public class MongoClientVersion {
|
||||
return REACTIVE_CLIENT_PRESENT;
|
||||
}
|
||||
|
||||
public static boolean is5PlusClient() {
|
||||
return IS_5PlusClient;
|
||||
/**
|
||||
* @return {@literal true} if the MongoDB Java driver version is 5 or newer.
|
||||
* @since 4.3
|
||||
*/
|
||||
public static boolean isVersion5OrNewer() {
|
||||
return IS_VERSION_5_OR_NEWER;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -17,9 +17,16 @@ package org.springframework.data.mongodb.observability;
|
||||
|
||||
import static org.springframework.data.mongodb.test.util.Assertions.*;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.tracing.exporter.FinishedSpan;
|
||||
import io.micrometer.tracing.test.SampleTestRunner;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mongodb.repository.Person;
|
||||
import org.springframework.data.mongodb.repository.PersonRepository;
|
||||
@@ -27,12 +34,6 @@ import org.springframework.data.mongodb.util.MongoClientVersion;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import io.micrometer.observation.ObservationRegistry;
|
||||
import io.micrometer.tracing.exporter.FinishedSpan;
|
||||
import io.micrometer.tracing.test.SampleTestRunner;
|
||||
|
||||
/**
|
||||
* Collection of tests that log metrics and tracing with an external tracing tool.
|
||||
*
|
||||
@@ -82,7 +83,7 @@ public class ImperativeIntegrationTests extends SampleTestRunner {
|
||||
|
||||
assertThat(span.getTags()).containsEntry("db.system", "mongodb").containsEntry("net.transport", "IP.TCP");
|
||||
|
||||
if(MongoClientVersion.is5PlusClient()) {
|
||||
if (MongoClientVersion.isVersion5OrNewer()) {
|
||||
assertThat(span.getTags()).containsKeys("db.connection_string", "db.name", "db.operation",
|
||||
"db.mongodb.collection", "net.peer.name", "net.peer.port");
|
||||
} else {
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.bson.BsonDocument;
|
||||
import org.bson.BsonString;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.data.mongodb.observability.MongoObservation.LowCardinalityCommandKeyNames;
|
||||
|
||||
import com.mongodb.RequestContext;
|
||||
@@ -100,115 +101,115 @@ class MongoObservationCommandListenerTests {
|
||||
void successfullyCompletedCommandShouldCreateTimerWhenParentSampleInRequestContext() {
|
||||
|
||||
// given
|
||||
// Observation parent = Observation.start("name", observationRegistry);
|
||||
// RequestContext traceRequestContext = getContext();
|
||||
//
|
||||
// // when
|
||||
// listener.commandStarted(new CommandStartedEvent(traceRequestContext, 0, //
|
||||
// new ConnectionDescription( //
|
||||
// new ServerId( //
|
||||
// new ClusterId("description"), //
|
||||
// new ServerAddress("localhost", 1234))),
|
||||
// "database", "insert", //
|
||||
// new BsonDocument("collection", new BsonString("user"))));
|
||||
// listener.commandSucceeded(new CommandSucceededEvent(traceRequestContext, 0, null, "insert", null, 0));
|
||||
//
|
||||
// // then
|
||||
// assertThatTimerRegisteredWithTags();
|
||||
Observation parent = Observation.start("name", observationRegistry);
|
||||
RequestContext traceRequestContext = getContext();
|
||||
|
||||
// when
|
||||
listener.commandStarted(new CommandStartedEvent(traceRequestContext, 0, 0, //
|
||||
new ConnectionDescription( //
|
||||
new ServerId( //
|
||||
new ClusterId("description"), //
|
||||
new ServerAddress("localhost", 1234))),
|
||||
"database", "insert", //
|
||||
new BsonDocument("collection", new BsonString("user"))));
|
||||
listener.commandSucceeded(new CommandSucceededEvent(traceRequestContext, 0, 0, null, "insert", null, null, 0));
|
||||
|
||||
// then
|
||||
assertThatTimerRegisteredWithTags();
|
||||
}
|
||||
|
||||
@Test
|
||||
void successfullyCompletedCommandWithCollectionHavingCommandNameShouldCreateTimerWhenParentSampleInRequestContext() {
|
||||
|
||||
// given
|
||||
// Observation parent = Observation.start("name", observationRegistry);
|
||||
// RequestContext traceRequestContext = getContext();
|
||||
//
|
||||
// // when
|
||||
// listener.commandStarted(new CommandStartedEvent(traceRequestContext, 0, //
|
||||
// new ConnectionDescription( //
|
||||
// new ServerId( //
|
||||
// new ClusterId("description"), //
|
||||
// new ServerAddress("localhost", 1234))), //
|
||||
// "database", "aggregate", //
|
||||
// new BsonDocument("aggregate", new BsonString("user"))));
|
||||
// listener.commandSucceeded(new CommandSucceededEvent(traceRequestContext, 0, null, "aggregate", null, 0));
|
||||
Observation parent = Observation.start("name", observationRegistry);
|
||||
RequestContext traceRequestContext = getContext();
|
||||
|
||||
// when
|
||||
listener.commandStarted(new CommandStartedEvent(traceRequestContext, 0, 0, //
|
||||
new ConnectionDescription( //
|
||||
new ServerId( //
|
||||
new ClusterId("description"), //
|
||||
new ServerAddress("localhost", 1234))), //
|
||||
"database", "aggregate", //
|
||||
new BsonDocument("aggregate", new BsonString("user"))));
|
||||
listener.commandSucceeded(new CommandSucceededEvent(traceRequestContext, 0, 0, null, "aggregate", null, null, 0));
|
||||
|
||||
// then
|
||||
// assertThatTimerRegisteredWithTags();
|
||||
assertThatTimerRegisteredWithTags();
|
||||
}
|
||||
|
||||
@Test
|
||||
void successfullyCompletedCommandWithoutClusterInformationShouldCreateTimerWhenParentSampleInRequestContext() {
|
||||
|
||||
// // given
|
||||
// Observation parent = Observation.start("name", observationRegistry);
|
||||
// RequestContext traceRequestContext = getContext();
|
||||
//
|
||||
// // when
|
||||
// listener.commandStarted(new CommandStartedEvent(traceRequestContext, 0, null, "database", "insert",
|
||||
// new BsonDocument("collection", new BsonString("user"))));
|
||||
// listener.commandSucceeded(new CommandSucceededEvent(traceRequestContext, 0, null, "insert", null, 0));
|
||||
//
|
||||
// assertThat(meterRegistry).hasTimerWithNameAndTags(MongoObservation.MONGODB_COMMAND_OBSERVATION.getName(),
|
||||
// KeyValues.of(LowCardinalityCommandKeyNames.MONGODB_COLLECTION.withValue("user"),
|
||||
// LowCardinalityCommandKeyNames.DB_NAME.withValue("database"),
|
||||
// LowCardinalityCommandKeyNames.MONGODB_COMMAND.withValue("insert"),
|
||||
// LowCardinalityCommandKeyNames.DB_SYSTEM.withValue("mongodb")).and("error", "none"));
|
||||
// given
|
||||
Observation parent = Observation.start("name", observationRegistry);
|
||||
RequestContext traceRequestContext = getContext();
|
||||
|
||||
// when
|
||||
listener.commandStarted(new CommandStartedEvent(traceRequestContext, 0, 0, null, "database", "insert",
|
||||
new BsonDocument("collection", new BsonString("user"))));
|
||||
listener.commandSucceeded(new CommandSucceededEvent(traceRequestContext, 0, 0, null, "insert", null, null, 0));
|
||||
|
||||
assertThat(meterRegistry).hasTimerWithNameAndTags(MongoObservation.MONGODB_COMMAND_OBSERVATION.getName(),
|
||||
KeyValues.of(LowCardinalityCommandKeyNames.MONGODB_COLLECTION.withValue("user"),
|
||||
LowCardinalityCommandKeyNames.DB_NAME.withValue("database"),
|
||||
LowCardinalityCommandKeyNames.MONGODB_COMMAND.withValue("insert"),
|
||||
LowCardinalityCommandKeyNames.DB_SYSTEM.withValue("mongodb")).and("error", "none"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void commandWithErrorShouldCreateTimerWhenParentSampleInRequestContext() {
|
||||
|
||||
// // given
|
||||
// Observation parent = Observation.start("name", observationRegistry);
|
||||
// RequestContext traceRequestContext = getContext();
|
||||
//
|
||||
// // when
|
||||
// listener.commandStarted(new CommandStartedEvent(traceRequestContext, 0, //
|
||||
// new ConnectionDescription( //
|
||||
// new ServerId( //
|
||||
// new ClusterId("description"), //
|
||||
// new ServerAddress("localhost", 1234))), //
|
||||
// "database", "insert", //
|
||||
// new BsonDocument("collection", new BsonString("user"))));
|
||||
// listener.commandFailed( //
|
||||
// new CommandFailedEvent(traceRequestContext, 0, null, "insert", 0, new IllegalAccessException()));
|
||||
//
|
||||
// // then
|
||||
// assertThatTimerRegisteredWithTags();
|
||||
// given
|
||||
Observation parent = Observation.start("name", observationRegistry);
|
||||
RequestContext traceRequestContext = getContext();
|
||||
|
||||
// when
|
||||
listener.commandStarted(new CommandStartedEvent(traceRequestContext, 0, 0, //
|
||||
new ConnectionDescription( //
|
||||
new ServerId( //
|
||||
new ClusterId("description"), //
|
||||
new ServerAddress("localhost", 1234))), //
|
||||
"database", "insert", //
|
||||
new BsonDocument("collection", new BsonString("user"))));
|
||||
listener.commandFailed( //
|
||||
new CommandFailedEvent(traceRequestContext, 0, 0, null, "db", "insert", 0, new IllegalAccessException()));
|
||||
|
||||
// then
|
||||
assertThatTimerRegisteredWithTags();
|
||||
}
|
||||
|
||||
@Test // GH-4481
|
||||
void completionShouldIgnoreIncompatibleObservationContext() {
|
||||
|
||||
// // given
|
||||
// RequestContext traceRequestContext = getContext();
|
||||
//
|
||||
// Observation observation = mock(Observation.class);
|
||||
// traceRequestContext.put(ObservationThreadLocalAccessor.KEY, observation);
|
||||
//
|
||||
// // when
|
||||
// listener.commandSucceeded(new CommandSucceededEvent(traceRequestContext, 0, null, "insert", null, 0));
|
||||
//
|
||||
// verify(observation).getContext();
|
||||
// verifyNoMoreInteractions(observation);
|
||||
// given
|
||||
RequestContext traceRequestContext = getContext();
|
||||
|
||||
Observation observation = mock(Observation.class);
|
||||
traceRequestContext.put(ObservationThreadLocalAccessor.KEY, observation);
|
||||
|
||||
// when
|
||||
listener.commandSucceeded(new CommandSucceededEvent(traceRequestContext, 0, 0, null, "insert", null, null, 0));
|
||||
|
||||
verify(observation).getContext();
|
||||
verifyNoMoreInteractions(observation);
|
||||
}
|
||||
|
||||
@Test // GH-4481
|
||||
void failureShouldIgnoreIncompatibleObservationContext() {
|
||||
|
||||
// // given
|
||||
// RequestContext traceRequestContext = getContext();
|
||||
//
|
||||
// Observation observation = mock(Observation.class);
|
||||
// traceRequestContext.put(ObservationThreadLocalAccessor.KEY, observation);
|
||||
//
|
||||
// // when
|
||||
// listener.commandFailed(new CommandFailedEvent(traceRequestContext, 0, null, "insert", 0, null));
|
||||
//
|
||||
// verify(observation).getContext();
|
||||
// verifyNoMoreInteractions(observation);
|
||||
// given
|
||||
RequestContext traceRequestContext = getContext();
|
||||
|
||||
Observation observation = mock(Observation.class);
|
||||
traceRequestContext.put(ObservationThreadLocalAccessor.KEY, observation);
|
||||
|
||||
// when
|
||||
listener.commandFailed(new CommandFailedEvent(traceRequestContext, 0, 0, null, "db", "insert", 0, null));
|
||||
|
||||
verify(observation).getContext();
|
||||
verifyNoMoreInteractions(observation);
|
||||
}
|
||||
|
||||
private RequestContext getContext() {
|
||||
|
||||
Reference in New Issue
Block a user